pax_global_header00006660000000000000000000000064147544240100014513gustar00rootroot0000000000000052 comment=d05d6ca6dae1a8b5a1ea23aa9e33f6d99bcc9102 QW-Group-ktx-d05d6ca/000077500000000000000000000000001475442401000144305ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/.github/000077500000000000000000000000001475442401000157705ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/.github/ISSUE_TEMPLATE/000077500000000000000000000000001475442401000201535ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000015741475442401000226540ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: "[BUG] Short title describing issue" labels: bug assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Environment(please complete the following information):** - Operation System: [e.g. Windows, Linux, ...] - Processor Architecture: [e.g. x86, x86_64, arm7, ...] - MVDSV Version: [e.g. 0.31, 0.32, custom or specific commit build reference] - KTX Version: [e.g. 1.37, 1.38, custom or specific commit build reference] **Additional context** Add any other context about the problem here. QW-Group-ktx-d05d6ca/.github/workflows/000077500000000000000000000000001475442401000200255ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/.github/workflows/main.yml000066400000000000000000000176151475442401000215060ustar00rootroot00000000000000name: main on: push: # Only build branches on push, tags will be handled by 'release' job. branches: - '**' pull_request: workflow_dispatch: release: types: [published] jobs: build: runs-on: ubuntu-latest timeout-minutes: 10 strategy: fail-fast: false matrix: target: [ linux-amd64, linux-i686, linux-armhf, linux-aarch64, windows-x64, windows-x86, qvm ] include: - target: linux-amd64 os: linux arch: amd64 ext: ".so" packages: [ ] - target: linux-i686 os: linux arch: i686 ext: ".so" packages: [ "gcc-i686-linux-gnu" ] - target: linux-armhf os: linux arch: armhf ext: ".so" packages: [ "gcc-arm-linux-gnueabihf", "libc6-dev-armhf-cross" ] - target: linux-aarch64 os: linux arch: aarch64 ext: ".so" packages: [ "gcc-aarch64-linux-gnu", "libc6-dev-arm64-cross" ] - target: windows-x64 os: windows arch: x64 ext: ".dll" packages: [ "gcc-mingw-w64-x86-64" ] - target: windows-x86 os: windows arch: x86 ext: ".dll" packages: [ "gcc-mingw-w64-i686" ] - target: qvm os: linux arch: qvm ext: ".qvm" packages: [ ] container: image: "debian:stable" steps: - name: Checkout uses: actions/checkout@v4 with: path: ktx - name: Prepare Build Environemnt run: | apt-get -qq update apt-get -qq install build-essential cmake ninja-build ${{ join(matrix.packages, ' ') }} - name: Get number of CPU cores uses: SimenB/github-actions-cpu-cores@v2 id: cpu-cores if: matrix.target == 'qvm' - uses: ammaraskar/gcc-problem-matcher@0.3.0 if: matrix.target != 'qvm' - name: Checkout q3lcc uses: actions/checkout@v4 with: repository: ec-/q3lcc path: q3lcc if: matrix.target == 'qvm' - name: Build q3lcc run: | make -j ${{ steps.cpu-cores.outputs.count }} PLATFORM=$(uname -s) ARCH=$(uname -m) mv build*/q3lcc build*/q3rcc build*/q3cpp /usr/local/bin working-directory: q3lcc if: matrix.target == 'qvm' - name: Build run: | ./build_cmake.sh ${{ matrix.target }} mv build/*/qwprogs.* .. working-directory: ktx - uses: actions/upload-artifact@v4 with: name: qwprogs-${{ matrix.target }} path: | qwprogs.* compression-level: 9 verify-macos: runs-on: macos-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v4 - uses: ammaraskar/gcc-problem-matcher@0.3.0 - name: Build run: | cmake -B builddir -S . -G Xcode -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" cmake --build builddir --config Release --parallel verify-msvc: runs-on: windows-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v4 - uses: ammaraskar/msvc-problem-matcher@0.3.0 - name: Build run: | cmake -B builddir -S . -G "Visual Studio 17 2022" cmake --build builddir --config Release --parallel upload: needs: build timeout-minutes: 10 runs-on: ubuntu-latest if: github.repository == 'QW-Group/ktx' && ((github.event_name == 'push' && github.ref == 'refs/heads/master') || github.event_name == 'release') steps: - name: Checkout uses: actions/checkout@v4 with: path: ktx - name: Get release date run: | RELEASE_DATE=$(git log -1 --format=%cI "${{ github.ref_name }}") echo "RELEASE_DATE=$RELEASE_DATE" >> $GITHUB_ENV working-directory: ktx - name: Download Artifacts uses: actions/download-artifact@v4 - name: Collect GitHub release artifacts run: | dist_dir=$(pwd)/dist mkdir $dist_dir find qwprogs* -type f -exec sha256sum {} \; > "${dist_dir}/checksums.txt" # Reset timestamp to time of tag find qwprogs* -print0 | xargs -0r touch --date="${RELEASE_DATE}" touch --date="${RELEASE_DATE}" "${dist_dir}/checksums.txt" for target in qwprogs*; do (cd $target; zip -o -9 "${dist_dir}/${target}.zip" *) done echo "GITHUB_ARTIFACTS=$dist_dir" >> $GITHUB_ENV if: github.event_name == 'release' - name: Attach artifacts to GitHub release uses: softprops/action-gh-release@v1 with: files: ${{ env.GITHUB_ARTIFACTS }}/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: github.event_name == 'release' - name: Prepare Upload Environemnt run: | sudo apt-get -qq update sudo apt-get -qq --no-install-recommends install openssh-client - name: Setup SSH env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock shell: bash run: | ssh-agent -a $SSH_AUTH_SOCK > /dev/null ssh-add - <<< "${{ secrets.SSH_PRIVATE_KEY }}" - name: Prepare upload to builds.quakeworld.nu env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock shell: bash run: | # Build file structure for uploading # snapshots: # upload/snapshots/latest/$os/$arch/$filename # upload/snapshots/$os/$arch/$prefix_$filename # releases: # upload/releases/latest/$os/$arch/$filename # upload/releases/$tag/$os/$arch/$filename upload_dir="$(pwd)/upload" if [[ $GITHUB_REF == refs/tags/* ]]; then main_dir="${upload_dir}/releases/${{ github.ref_name }}" latest_dir="${upload_dir}/releases/latest" prefix="" else main_dir="${upload_dir}/snapshots" latest_dir="${upload_dir}/snapshots/latest" date=$(TZ="Europe/Amsterdam" date "+%Y%m%d-%H%M%S") prefix="${date}_${GITHUB_SHA::7}_" fi for target in qwprogs*; do os_arch="${target#qwprogs-}" os_arch_dir="${os_arch//-//}" main_target_dir="${main_dir}/${os_arch_dir}" latest_target_dir="${latest_dir}/${os_arch_dir}" mkdir -p "${main_target_dir}" "${latest_target_dir}" for src in $(find "${target}" -type f); do filename=$(basename "${src}") cp "${src}" "${main_target_dir}/${prefix}${filename}" cp "${src}" "${latest_target_dir}/${filename}" done (cd "${main_target_dir}" && md5sum * > "${prefix}qwprogs.md5") (cd "${latest_target_dir}" && md5sum * > "qwprogs.md5") done # Reset timestamp to time of tag find "${upload_dir}" -print0 | xargs -0r touch --date="${RELEASE_DATE}" echo "Artifacts to upload:" find upload echo - name: Upload to builds.quakeworld.nu/ktx/snapshots env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock shell: bash run: | sftp -rp -o 'StrictHostKeyChecking no' -o 'UserKnownHostsFile /dev/null' -P ${{ secrets.SFTP_PORT }} ${{ secrets.SFTP_USERNAME }}@${{ secrets.SFTP_HOST }}:/snapshots <<< $'put -rp upload/snapshots/*' if: github.event_name == 'push' - name: Upload to builds.quakeworld.nu/ktx/releases env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock shell: bash run: | sftp -rp -o 'StrictHostKeyChecking no' -o 'UserKnownHostsFile /dev/null' -P ${{ secrets.SFTP_PORT }} ${{ secrets.SFTP_USERNAME }}@${{ secrets.SFTP_HOST }}:/releases <<< $'put -rp upload/releases/*' if: github.event_name == 'release' QW-Group-ktx-d05d6ca/.gitignore000066400000000000000000000004331475442401000164200ustar00rootroot00000000000000*.o *.s *.so *.dll *.qvm *.map *.suo *.ncb VM/ Debug_*/ Release_*/ *.sdf *.user ./Makefile config.log config.status src/Makefile.dl src/Makefile.dl32 src/Makefile.vm #virtualenv .venv/ # build output dirs build*/ built_items/ x64/* .vs/* *.psess *.vspx *.suobackup *.VC.db /.cache QW-Group-ktx-d05d6ca/CMakeLists.txt000066400000000000000000000166471475442401000172060ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.9.0) # Set project name and languge. project(qwprogs C) include(CheckCCompilerFlag) set(CMAKE_COLOR_DIAGNOSTICS ON) # CMake option for bot support, we check it below and add C preprocessor directive if required. option(BOT_SUPPORT "Build with bot support" ON) # Option for FTE extensions. We also have some basic support for FTE which does not controlled by this setting. # This is en example and extensions unused for now, so its turned off by default. Also turning it ON makes binary incompatibe with MVDSV. option(FTESV "Build with FTE extensions support" OFF) # Set where sources located. set(DIR_SRC "src") # Set variables with different source lists for native or QVM library: # g_syscalls.asm is a mapping between trap name and trap number, used by QVM library (it is q3asm code). set(SRC_VM_SYSCALL "g_syscalls.asm") # Sources for QVM library. set(SRC_VM "${DIR_SRC}/bg_lib.c" ) # Sources for native library. set(SRC_NATIVE "${DIR_SRC}/g_syscalls.c" "${DIR_SRC}/native_lib.c" ) # Common sources for native and QVM. set(SRC_COMMON "${DIR_SRC}/g_main.c" # WARNING: should be first in list for QVM, since it contains vmMain(). "${DIR_SRC}/admin.c" "${DIR_SRC}/arena.c" "${DIR_SRC}/bot_aim.c" "${DIR_SRC}/bot_blocked.c" "${DIR_SRC}/bot_botenemy.c" "${DIR_SRC}/bot_botgoals.c" "${DIR_SRC}/bot_bothazd.c" "${DIR_SRC}/bot_bothelp.c" "${DIR_SRC}/bot_botimp.c" "${DIR_SRC}/bot_botjump.c" "${DIR_SRC}/bot_botpath.c" "${DIR_SRC}/bot_botphys.c" "${DIR_SRC}/bot_botstat.c" "${DIR_SRC}/bot_botthink.c" "${DIR_SRC}/bot_botwater.c" "${DIR_SRC}/bot_botweap.c" "${DIR_SRC}/bot_client.c" "${DIR_SRC}/bot_commands.c" "${DIR_SRC}/bot_items.c" "${DIR_SRC}/bot_load.c" "${DIR_SRC}/bot_loadmap.c" "${DIR_SRC}/bot_match.c" "${DIR_SRC}/bot_movement.c" "${DIR_SRC}/bot_routing.c" "${DIR_SRC}/bot_world.c" "${DIR_SRC}/buttons.c" "${DIR_SRC}/captain.c" "${DIR_SRC}/coach.c" "${DIR_SRC}/clan_arena.c" "${DIR_SRC}/client.c" "${DIR_SRC}/combat.c" "${DIR_SRC}/commands.c" "${DIR_SRC}/ctf.c" "${DIR_SRC}/doors.c" "${DIR_SRC}/fb_globals.c" "${DIR_SRC}/files.c" "${DIR_SRC}/func_bob.c" "${DIR_SRC}/func_laser.c" "${DIR_SRC}/g_cmd.c" "${DIR_SRC}/globals.c" "${DIR_SRC}/g_mem.c" "${DIR_SRC}/grapple.c" "${DIR_SRC}/g_spawn.c" "${DIR_SRC}/g_userinfo.c" "${DIR_SRC}/g_utils.c" "${DIR_SRC}/g_syscalls_extra.c" "${DIR_SRC}/hiprot.c" "${DIR_SRC}/hoonymode.c" "${DIR_SRC}/items.c" "${DIR_SRC}/logs.c" "${DIR_SRC}/maps.c" "${DIR_SRC}/maps_map_amphi2.c" "${DIR_SRC}/maps_map_dm3.c" "${DIR_SRC}/maps_map_dm4.c" "${DIR_SRC}/maps_map_dm6.c" "${DIR_SRC}/maps_map_povdmm4.c" "${DIR_SRC}/marker_load.c" "${DIR_SRC}/marker_util.c" "${DIR_SRC}/match.c" "${DIR_SRC}/mathlib.c" "${DIR_SRC}/misc.c" "${DIR_SRC}/motd.c" "${DIR_SRC}/plats.c" "${DIR_SRC}/player.c" "${DIR_SRC}/q_shared.c" "${DIR_SRC}/race.c" "${DIR_SRC}/rng.c" "${DIR_SRC}/rng_gen_impl.c" "${DIR_SRC}/rng_seed_impl.c" "${DIR_SRC}/route_calc.c" "${DIR_SRC}/route_fields.c" "${DIR_SRC}/route_lookup.c" "${DIR_SRC}/runes.c" "${DIR_SRC}/server.c" "${DIR_SRC}/sp_ai.c" "${DIR_SRC}/sp_boss.c" "${DIR_SRC}/sp_client.c" "${DIR_SRC}/sp_demon.c" "${DIR_SRC}/sp_dog.c" "${DIR_SRC}/spectate.c" "${DIR_SRC}/sp_enforcer.c" "${DIR_SRC}/sp_fish.c" "${DIR_SRC}/sp_hknight.c" "${DIR_SRC}/sp_knight.c" "${DIR_SRC}/sp_monsters.c" "${DIR_SRC}/sp_ogre.c" "${DIR_SRC}/sp_oldone.c" "${DIR_SRC}/sp_shalrath.c" "${DIR_SRC}/sp_shambler.c" "${DIR_SRC}/sp_soldier.c" "${DIR_SRC}/sp_tarbaby.c" "${DIR_SRC}/sp_wizard.c" "${DIR_SRC}/sp_zombie.c" "${DIR_SRC}/stats.c" "${DIR_SRC}/statsTables.c" "${DIR_SRC}/stats_json.c" "${DIR_SRC}/stats_xml.c" "${DIR_SRC}/subs.c" "${DIR_SRC}/teamplay.c" "${DIR_SRC}/triggers.c" "${DIR_SRC}/vip.c" "${DIR_SRC}/vote.c" "${DIR_SRC}/weapons.c" "${DIR_SRC}/world.c" ) # Build native library. add_library(${PROJECT_NAME} SHARED ${SRC_COMMON} ${SRC_NATIVE}) target_include_directories(${PROJECT_NAME} PRIVATE "include") set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" # Strip lib prefix. C_VISIBILITY_PRESET hidden # Hide all symbols unless excplicitly marked to export. ) if(BOT_SUPPORT) target_compile_definitions(${PROJECT_NAME} PRIVATE BOT_SUPPORT=1) endif() if(FTESV) target_compile_definitions(${PROJECT_NAME} PRIVATE FTESV=1) endif() # If not Miscrosoft compilator - then set additional options for linker. if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") # 4100 - unused parameter # 4210 - using extern keyword in functions # 4456 - shadowing locals, broadly used # 4459 - shadowing globals, broadly used target_compile_options(${PROJECT_NAME} PRIVATE /W4 /wd4100 /wd4210 /wd4456 /wd4459) else() target_compile_options(${PROJECT_NAME} PRIVATE -Wall) check_c_compiler_flag("-Wstrict-prototypes" HAS_CFLAG_STRICT_PROTOTYPES) if (HAS_CFLAG_STRICT_PROTOTYPES) target_compile_options(${PROJECT_NAME} PRIVATE -Werror=strict-prototypes) endif() check_c_compiler_flag("-Wstrlcpy-strlcat-size" HAS_STRLCPY_STRLCAT_SIZE) if (HAS_STRLCPY_STRLCAT_SIZE) target_compile_options(${PROJECT_NAME} PRIVATE -Werror=strlcpy-strlcat-size) endif() # Do not allow undefined symbols while linking. if(APPLE) target_link_options(${PROJECT_NAME} PRIVATE "-Wl,-undefined,error") else() target_link_options(${PROJECT_NAME} PRIVATE "-Wl,--no-undefined") endif() target_link_libraries(${PROJECT_NAME} PRIVATE m) # Link with libm. endif() # Build QVM tools if needed. find_program(Q3ASM q3asm) if(Q3ASM) message(STATUS "q3asm found at ${Q3ASM}") set(QVM_LINKER "${Q3ASM}") else() message(STATUS "q3asm not found, compiling bundled q3asm.") # EXCLUDE_FROM_ALL tells to not build tools if they does not required, for example if you build native library only. add_subdirectory(tools/q3asm EXCLUDE_FROM_ALL) set(QVM_LINKER "q3asm") endif() # Set up vars for QVM library. set(VM_DIR "vm") add_custom_target(vmdir COMMAND ${CMAKE_COMMAND} -E make_directory ${VM_DIR} ) set(QVM_COMPILER "q3lcc") set(QVM_C_FLAGS -DQ3_VM -S -Wf-target=bytecode -Wf-g) if(BOT_SUPPORT) set(QVM_C_FLAGS ${QVM_C_FLAGS} -DBOT_SUPPORT=1) endif() set(QVM_INCDIR "${CMAKE_CURRENT_SOURCE_DIR}/include") # Write first chunk of QVM_LIST_FILE. set(QVM_LIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/game.q3asm") file(WRITE ${QVM_LIST_FILE} "-o ${PROJECT_NAME}\n") # Cycle through sources and fill in SRC_ASM varible, continue generate QVM_LIST_FILE. foreach(file ${SRC_COMMON} ${SRC_VM}) get_filename_component(file_asm ${file} NAME_WE) # Get basename without extension. string(CONCAT file_asm ${file_asm} ".asm") # Add asm extension. list(APPEND SRC_ASM ${file_asm}) # Fill in SRC_ASM list. file(APPEND ${QVM_LIST_FILE} "${VM_DIR}/${file_asm}\n") # Continue generate QVM_LIST_FILE. get_filename_component(src_dir ${file} DIRECTORY) file(RELATIVE_PATH QVM_RELINCDIR "${CMAKE_CURRENT_SOURCE_DIR}/${src_dir}" "${QVM_INCDIR}") # Add command to compile c to asm. add_custom_target(${file_asm} COMMAND ${QVM_COMPILER} ${QVM_C_FLAGS} -I${QVM_RELINCDIR} "${CMAKE_CURRENT_SOURCE_DIR}/${file}" -o "${VM_DIR}/${file_asm}" DEPENDS vmdir SOURCES ${file} ) endforeach() # Copy file, but also add dependency. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${DIR_SRC}/${SRC_VM_SYSCALL} ${VM_DIR}/${SRC_VM_SYSCALL}) # Append last chunk of data in QVM_LIST_FILE. file(APPEND ${QVM_LIST_FILE} "${VM_DIR}/${SRC_VM_SYSCALL}\n") # Print location of the file. message(STATUS ${QVM_LIST_FILE}) # Add custom target for processing asm files and generating QVM library. add_custom_target(qvm COMMAND ${QVM_LINKER} -m -f ${QVM_LIST_FILE} DEPENDS ${SRC_ASM} ) QW-Group-ktx-d05d6ca/CODE_OF_CONDUCT.md000066400000000000000000000122341475442401000172310ustar00rootroot00000000000000 # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [community-leaders@quakeworld.nu](mailto:community-leaders@quakeworld.nu). All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. QW-Group-ktx-d05d6ca/LICENSE.md000066400000000000000000000355061475442401000160450ustar00rootroot00000000000000The GNU General Public License, Version 2, June 1991 (GPLv2) ============================================================ > Copyright (C) 1989, 1991 Free Software Foundation, Inc. > 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble -------- The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. 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. QW-Group-ktx-d05d6ca/README.md000066400000000000000000000106721475442401000157150ustar00rootroot00000000000000# KTX: a QuakeWorld server modification ![KTX Logo](https://raw.githubusercontent.com/QW-Group/ktx/master/resources/logo/ktx.png) **[KTX][ktx]** (Kombat Teams eXtreme) is a popular **QuakeWorld** server modification, adding numerous features to the core features of the server. Although it had been developed to be **Quakeworld** server agnostic, it has over the years been developed very close to **[MVDSV][mvdsv]** to which it has become an extent, thus compatibility with other **Quakeworld** servers might not have been maintained. ## Getting Started The following instructions will help you get **[KTX][ktx]** installed on a running **[MVDSV][mvdsv]** server using prebuilt binaries. Details on how to compile your own **[KTX][ktx]** binary will also be included to match specific architectures or for development purposes. ## Supported architectures The following architectures are fully supported by **[KTX][ktx]** and are available as prebuilt binaries: * Linux amd64 (Intel and AMD 64-bits processors) * Linux i686 (Intel and AMD 32-bit processors) * Linux aarch (ARM 64-bit processors) * Linux armhf (ARM 32-bit processors) * Windows x64 (Intel and AMD 64-bits processors) * Windows x86 (Intel and AMD 32-bit processors) ## Prebuilt binaries You can find the prebuilt binaries on [this download page][ktx-builds]. ## Prerequisites **[KTX][ktx]** is a server mod and won't run without a proper **Quakeworld** server set up. **[MVDSV][mvdsv]** is the recommended one, but **[FTE][fte]** might work as well (unconfirmed with current code). ## Installing For more detailed information we suggest looking at the [nQuake server][nquake-linux], which uses **[MVDSV][mvdsv]** and **[KTX][ktx]** as **QuakeWorld** server. ## Building binaries ### Build from source with CMake Assuming you have installed essential build tools and ``CMake`` ```bash mkdir build && cmake -B build . && cmake --build build ``` Build artifacts would be inside ``build/`` directory, for unix like systems it would be ``qwprogs.so``. You can also use ``build_cmake.sh`` script, it mostly suitable for cross compilation and probably useless for experienced CMake user. Some examples: ``` ./build_cmake.sh linux-amd64 ``` should build KTX for ``linux-amd64`` platform, release version, check [cross-cmake](tools/cross-cmake) directory for all platforms ``` B=Debug ./build_cmake.sh linux-amd64 ``` should build KTX for linux-amd64 platform with debug ``` V=1 B=Debug ./build_cmake.sh linux-amd64 ``` should build KTX for linux-amd64 platform with debug, verbose (useful if you need validate compiler flags) ``` V=1 B=Debug BOT_SUPPORT=OFF ./build_cmake.sh linux-amd64 ``` same as above but compile without bot support ``` G="Unix Makefiles" ./build_cmake.sh linux-amd64 ``` force CMake generator to be unix makefiles ``` ./build_cmake.sh linux-amd64 qvm ``` build KTX for ``linux-amd64`` and ``QVM`` version, you can provide any platform combinations. ## Versioning For the versions available, see the [tags on this repository][ktx-tags]. ## Authors (Listed by last name alphabetic order) * **Ivan** *"qqshka"* **Bolsunov** * **Dominic** *"oldman"* **Evans** * **Foobar** * **Anton** *"tonik"* **Gavrilov** * **Andrew** *"ult"* **Grondalski** * **Paul Klumpp** * **Niclas** *"empezar"* **Lindström** * **Dmitry** *"disconnect"* **Musatov** * **Peter** *"meag"* **Nicol** * **Andreas** *"molgrum"* **Nilsson** * **Alexandre** *"deurk"* **Nizoux** * **Tero** *"Renzo"* **Parkkonen** * **Joseph** *"bogojoker"* **Pecoraro** * **Michał** *"\_KaszpiR\_"* **Sochoń** * **Jonny** *"dimman"* **Svärd** * **Vladimir** *"VVD"* **Vladimirovich** * **Florian** *"Tuna"* **Zwoch** ## Code of Conduct We try to stick to our code of conduct when it comes to interaction around this project. See the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file for details. ## License This project is licensed under the GPL-2.0 License - see the [LICENSE.md](LICENSE.md) file for details. ## Acknowledgments * Thanks to kemiKal, Cenobite, Sturm and Fang for Kombat teams 2.21 which has served as a base for **[KTX][ktx]**. * Thanks to **Jon "bps" Cednert** for the **[KTX][ktx]** logo. * Thanks to the fine folks on [Quakeworld Discord][discord-qw] for their support and ideas. [ktx]: https://github.com/QW-Group/ktx [ktx-tags]: https://github.com/QW-Group/ktx/tags [ktx-builds]: https://builds.quakeworld.nu/ktx [mvdsv]: https://github.com/QW-Group/mvdsv [nquake-linux]: https://github.com/nQuake/server-linux [discord-qw]: http://discord.quake.world/ QW-Group-ktx-d05d6ca/build_cmake.sh000077500000000000000000000033161475442401000172310ustar00rootroot00000000000000#!/bin/bash -e # Useful if you willing to stop on first error, also prints what is executed. #set -ex BUILDDIR="${BUILDDIR:-build}" # Default build dir. # Define target platforms, feel free to comment out if you does not require some of it, # or you can call this script with plaforms list you willing to build on the command line. DEFAULT_PLATFORMS=( linux-amd64 linux-aarch64 linux-armhf linux-i686 windows-x64 windows-x86 qvm ) PLATFORMS=("${@:-${DEFAULT_PLATFORMS[@]}}") # CMake option for bot support, CMake default used if not specified here. BOT_SUPPORT="${BOT_SUPPORT:-}" [ ! -z ${BOT_SUPPORT} ] && BOT_SUPPORT="-DBOT_SUPPORT=${BOT_SUPPORT}" # If V variable is not empty then provide -v argument to cmake --build command (verbose output). V="${V:-}" [ ! -z ${V} ] && V="-v" # Overwrite build type with B variable. B="${B:-Release}" [ ! -z ${B} ] && BUILD="-DCMAKE_BUILD_TYPE=${B}" # The maximum number of concurrent processes to use when building. export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-8}" # Use specified (with G variable) CMake generator or use default generator (most of the time its make) or ninja if found. G="${G:-}" [ -z "${G}" ] && hash ninja >/dev/null 2>&1 && G="Ninja" [ ! -z "${G}" ] && export CMAKE_GENERATOR="${G}" rm -rf ${BUILDDIR} mkdir -p ${BUILDDIR} # Build platforms one by one. for name in "${PLATFORMS[@]}"; do P="${BUILDDIR}/$name" mkdir -p "${P}" case "${name}" in "qvm" ) # Build QVM library. cmake -B "${P}" -S . ${BOT_SUPPORT} ${BUILD} cmake --build "${P}" --target qvm ${V} ;; * ) # Build native library. cmake -B "${P}" -S . ${BOT_SUPPORT} ${BUILD} -DCMAKE_TOOLCHAIN_FILE="tools/cross-cmake/${name}.cmake" cmake --build "${P}" ${V} ;; esac done QW-Group-ktx-d05d6ca/include/000077500000000000000000000000001475442401000160535ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/include/bg_lib.h000066400000000000000000000053671475442401000174550ustar00rootroot00000000000000// // $Id$ // // bg_lib.h -- standard C library replacement routines used by code // compiled for the virtual machine // This file is NOT included on native builds typedef int intptr_t; typedef int size_t; typedef char *va_list; #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define va_end(ap) ( ap = (va_list)0 ) #define CHAR_BIT 8 /* number of bits in a char */ #define SCHAR_MIN (-128) /* minimum signed char value */ #define SCHAR_MAX 127 /* maximum signed char value */ #define UCHAR_MAX 0xff /* maximum unsigned char value */ #define SHRT_MIN (-32768) /* minimum (signed) short value */ #define SHRT_MAX 32767 /* maximum (signed) short value */ #define USHRT_MAX 0xffff /* maximum unsigned short value */ #define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ #define INT_MAX 2147483647 /* maximum (signed) int value */ #define UINT_MAX 0xffffffff /* maximum unsigned int value */ #define LONG_MIN (-2147483647L - 1) /* minimum (signed) long value */ #define LONG_MAX 2147483647L /* maximum (signed) long value */ #define ULONG_MAX 0xffffffffUL /* maximum unsigned long value */ // Misc functions void srand(unsigned seed); int rand(void); // String functions size_t strlen(const char *string); char* strcat(char *strDestination, const char *strSource); char* strcpy(char *strDestination, const char *strSource); int strcmp(const char *string1, const char *string2); char* strchr(const char *string, int c); char* strrchr(const char *string, int c); char* strstr(const char *string, const char *strCharSet); char* strncpy(char *strDest, const char *strSource, size_t count); int tolower(int c); int toupper(int c); #define isdigit( c ) ( (c) >= '0' && (c) <= '9' ) double atof(const char *string); int atoi(const char *string); int vsprintf(char *buffer, const char *fmt, va_list argptr); int sscanf(const char *buffer, const char *fmt, ...); int Q_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr); int snprintf(char *buffer, size_t count, char const *format, ...); size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz); // Memory functions void* memmove(void *dest, const void *src, size_t count); void* memset(void *dest, int c, size_t count); void* memcpy(void *dest, const void *src, size_t count); // Math functions double ceil(double x); double floor(double x); double sqrt(double x); double sin(double x); double cos(double x); double atan2(double y, double x); double tan(double x); int abs(int n); double fabs(double x); double acos(double x); double fmod(double x, double y); QW-Group-ktx-d05d6ca/include/deathtype.h000066400000000000000000000016671475442401000202250ustar00rootroot00000000000000DEATHTYPE( dtNONE, none ) DEATHTYPE( dtAXE, axe ) DEATHTYPE( dtSG, sg ) DEATHTYPE( dtSSG, ssg ) DEATHTYPE( dtNG, ng ) DEATHTYPE( dtSNG, sng ) DEATHTYPE( dtGL, gl ) DEATHTYPE( dtRL, rl ) DEATHTYPE( dtLG_BEAM, lg_beam ) DEATHTYPE( dtLG_DIS, lg_dis ) // discharge DEATHTYPE( dtLG_DIS_SELF, lg_dis_self ) // sometimes this sort of discharge happens in dmm > 3 DEATHTYPE( dtHOOK, hook ) DEATHTYPE( dtCHANGELEVEL, changelevel ) DEATHTYPE( dtLAVA_DMG, lava ) DEATHTYPE( dtSLIME_DMG, slime ) DEATHTYPE( dtWATER_DMG, water ) DEATHTYPE( dtFALL, fall ) DEATHTYPE( dtSTOMP, stomp ) DEATHTYPE( dtTELE1, tele1 ) DEATHTYPE( dtTELE2, tele2 ) DEATHTYPE( dtTELE3, tele3 ) DEATHTYPE( dtEXPLO_BOX, explo_box ) DEATHTYPE( dtLASER, laser ) DEATHTYPE( dtFIREBALL, fireball ) DEATHTYPE( dtSQUISH, squish ) DEATHTYPE( dtTRIGGER_HURT, trigger ) DEATHTYPE( dtSUICIDE, suicide ) // client use /kill command DEATHTYPE( dtUNKNOWN, unknown ) QW-Group-ktx-d05d6ca/include/fb_globals.h000066400000000000000000000345251475442401000203270ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifndef FB_GLOBALS_H #define FB_GLOBALS_H #define PATH_SCORE_NULL -1000000 #define FB_OPTION_SHOW_MARKERS 1 #define FB_OPTION_EDITOR_MODE 2 #define FB_OPTION_SHOW_DUEL_LOGIC 4 #define FB_OPTION_SHOW_GOAL_LOGIC 8 #define FB_OPTION_SHOW_ROUTING_LOGIC 16 #define FB_OPTION_SHOW_MOVEMENT_LOGIC 32 #define FB_OPTION_DEMOMARK_ROCKETJUMPS 64 #define FB_OPTION_DEBUG_MOVEMENT 128 #define FB_OPTION_SHOW_THINKING (FB_OPTION_SHOW_DUEL_LOGIC | FB_OPTION_SHOW_GOAL_LOGIC | FB_OPTION_SHOW_ROUTING_LOGIC | FB_OPTION_SHOW_MOVEMENT_LOGIC) typedef void (*fb_spawn_funcref_t)(gedict_t *ent); typedef struct fb_spawn_s { char *name; // classname fb_spawn_funcref_t func; // initialisation function } fb_spawn_t; typedef struct fb_path_eval_s { gedict_t *touch_marker; gedict_t *test_marker; qbool rocket_alert; int description; float path_time; qbool path_normal; vec3_t player_origin; gedict_t *goalentity_marker; float goal_late_time; float lookahead_time_; vec3_t player_direction; qbool be_quiet; gedict_t *player; } fb_path_eval_t; // Globals used for general path-finding extern qbool path_normal; extern gedict_t *look_marker; extern gedict_t *from_marker; extern gedict_t *middle_marker; extern gedict_t *to_marker; extern gedict_t *next_marker; extern gedict_t *prev_marker; extern float traveltime; extern float look_traveltime; extern float zone_time; // Globals for physics variables extern float sv_maxspeed; extern float sv_maxstrafespeed; extern float sv_maxwaterspeed; extern float half_sv_maxspeed; extern float inv_sv_maxspeed; extern float sv_accelerate; extern gedict_t *dropper; // FIXME: A lot of these not used anymore #define FL_ONGROUND_PARTIALGROUND (FL_ONGROUND | FL_PARTIALGROUND) #define IT_EITHER_NAILGUN (IT_NAILGUN | IT_SUPER_NAILGUN) #define IT_NAILGUN_ROCKET (IT_ROCKET_LAUNCHER | IT_SUPER_NAILGUN | IT_NAILGUN) #define IT_CONTINUOUS (IT_LIGHTNING | IT_SUPER_NAILGUN | IT_NAILGUN) #define IT_AXE_SHOTGUN (IT_AXE | IT_SHOTGUN) #define IT_ALL_BUT_GRENADE (IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_ROCKET_LAUNCHER | IT_LIGHTNING) #define IT_ALL (IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING) #define IT_NOT_AMMO 16773375 #define IT_ARMOR (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3) #define IT_NOT_ARMOR (~IT_ARMOR) #define IT_INVULNERABILITY_QUAD (IT_INVULNERABILITY | IT_QUAD) #define IT_NOT_INVISIBILITY (~IT_INVISIBILITY) #define IT_NOT_INVULNERABILITY (~IT_INVULNERABILITY) #define IT_NOT_SUIT (~IT_SUIT) #define IT_NOT_QUAD (~IT_QUAD) #define ITEM_RUNE_MASK (CTF_RUNE_RES | CTF_RUNE_STR | CTF_RUNE_HST | CTF_RUNE_RGN) #define NOT_EF_DIMLIGHT 16777207 #define EF_DIMLIGHT_BLUE (EF_DIMLIGHT | EF_BLUE) #define EF_DIMLIGHT_RED (EF_DIMLIGHT | EF_RED) #define CLIENTKILL 11 #define FB_PREFER_ROCKET_LAUNCHER 1 #define FB_PREFER_LIGHTNING_GUN 2 #define GAME_ENABLE_POWERUPS 1 #define GAME_ENABLE_RUNES 2 #define GAME_RUNE_RJ 4 #define GAME_MATCH 64 #define GAME_ENABLE_DROPWEAP 512 #define GAME_ENABLE_AUTOREPORT 1024 #define GAME_ENABLE_AUTOSTEAMS 2048 #define FORWARD 1 #define BACK 2 #define LEFT 4 #define RIGHT 8 #define FORWARD_LEFT 5 #define FORWARD_RIGHT 9 #define BACK_LEFT 6 #define BACK_RIGHT 10 #define UP 16 #define DOWN 32 #define JUMPSPEED 270 // Fall results #define FALL_FALSE 0 #define FALL_BLOCKED 1 #define FALL_LAND 2 #define FALL_DEATH 3 // Path flags // NOTE: Editor won't save newly-added flags unless added to EXTERNAL_MARKER_PATH_FLAGS #define WATERJUMP_ (1 << 1) #define DM6_DOOR (1 << 8) #define ROCKET_JUMP (1 << 9) #define JUMP_LEDGE (1 << 10) // Implies NO_DODGE #define VERTICAL_PLATFORM (1 << 11) #define BOTPATH_DOOR (1 << 12) #define BOTPATH_DOOR_CLOSED (1 << 13) #define REVERSIBLE (1 << 14) // Set if bi-directional link between markers in the same zone #define WATER_PATH (1 << 15) #define DELIBERATE_AIR (1 << 17) #define WAIT_GROUND (1 << 18) #define STUCK_PATH (1 << 19) #define AIR_ACCELERATION (1 << 20) #define NO_DODGE (1 << 21) #define DELIBERATE_BACKUP (1 << 22) #define BOTPATH_CURLJUMP_HINT (1 << 23) #define BOTPATH_FULL_AIRCONTROL (1 << 24) #define BOTPATH_RJ_IN_PROGRESS (1 << 25) #define DELIBERATE_AIR_WAIT_GROUND (DELIBERATE_AIR | WAIT_GROUND) #define SAVED_DESCRIPTION (DM6_DOOR | ROCKET_JUMP | JUMP_LEDGE | VERTICAL_PLATFORM | BOTPATH_DOOR | BOTPATH_DOOR_CLOSED | NO_DODGE) #define NOT_ROCKET_JUMP (~ROCKET_JUMP) // Marker flags (FIXME: fb.T? check. consistent naming) // NOTE: Editor won't save newly-added flags unless added to EXTERNAL_MARKER_FLAGS #define UNREACHABLE 1 // Typically set for markers that are lava, waterlevel 3? (automate?) #define T_WATER 2 // Set by server if the marker is in liquid #define T_NO_AIR 4 // Set by server (means the bot would be trapped underwater - dm3 tunnel for instance) #define MARKER_IS_DM6_DOOR 8 // Should only be set for DM6 door to LG at the moment (logic needs generalised to all shootable doors) #define MARKER_BLOCKED_ON_STATE_TOP 16 // If set, door is considered 'closed' when STATE_TOP. #define MARKER_FIRE_ON_MATCH_START 32 // Used to automatically fire triggers (open secret doors etc). Ignored if no bots spawned. #define MARKER_DOOR_TOUCHABLE 64 // If set, door will spawn a touchable marker. If not set, door shouldn't be in bot path definitions #define MARKER_ESCAPE_ROUTE 128 // (not currently implemented) bot should head towards marker when in lava or slime (think amphi2/end) #define MARKER_DYNAMICALLY_ADDED 256 // Added dynamically by server. Do not include in .bot file generation #define MARKER_EXPLICIT_VIEWOFFSET 512 // Viewoffset has been set by map definition and should be included in .bot file generation #define MARKER_NOTOUCH 1024 // Not touchable - used when two markers on top of each other // Bot flags (FIXME: fb.state? check. consistent naming, comment with descriptions) #define CAMPBOT 1 #define SHOT_FOR_LUCK 2 #define BACKPACK_IS_UNREACHABLE 4 #define NOTARGET_ENEMY 32 #define AWARE_SURROUNDINGS 128 #define HURT_SELF 1024 #define RUNAWAY 4096 #define WAIT 8192 #define NOT_NOTARGET_ENEMY ~(NOTARGET_ENEMY) #define NOT_AWARE_SURROUNDINGS ~(AWARE_SURROUNDINGS) #define HELP_TEAMMATE 128 // FIXME: same as AWARE_SURROUNDINGS... deliberate? qbool ExistsPath(gedict_t *from_marker, gedict_t *to_marker, int *new_path_state); float boomstick_only(void); float CountTeams(void); qbool EnemyDefenceless(gedict_t *self); qbool enemy_shaft_attack(gedict_t *self, gedict_t *enemy); float W_BestWeapon(void); gedict_t* LocateMarker(vec3_t org); gedict_t* LocateNextMarker(vec3_t org, gedict_t *ignore_ent); float RankForWeapon(float w); float WeaponCode(float w); float crandom(void); void BotCanRocketJump(gedict_t *self); qbool VisibleEntity(gedict_t *ent); gedict_t* IdentifyMostVisibleTeammate(gedict_t *self); float anglemod(float v); gedict_t* HelpTeammate(void); float TotalStrengthAfterDamage(float health, float armorValue, float armorType, float damage); float TotalStrength(float health, float armorValue, float armorType); // char* BotNameGeneric(int botNumber); char* BotNameFriendly(int botNumber); char* BotNameEnemy(int botNumber); qbool Visible_360(gedict_t *self, gedict_t *visible_object); qbool Visible_infront(gedict_t *self, gedict_t *visible_object); // marker_util.qc void marker_touch(void); void check_marker(gedict_t *self, gedict_t *other); void BecomeMarker(gedict_t *marker); // route_calc.qc void CheckWaterColumn(gedict_t *m, vec3_t m_pos, vec3_t testplace); // route_fields.qc gedict_t* CreateNewMarker(vec3_t origin); // botwater.qc void BotWaterMove(gedict_t *self); void BotWaterJumpFix(void); // items.qc float goal_NULL(gedict_t *self, gedict_t *other); // client.qc void BotClientEntersEvent(gedict_t *self, gedict_t *spawn_pos); void BotPreThink(gedict_t *self); void BotClientConnectedEvent(gedict_t *self); void BotOutOfWater(gedict_t *self); void BotSetCommand(gedict_t *self); void BotsThinkTime(gedict_t *self); // botphys.qc void FrogbotPrePhysics1(void); void FrogbotPrePhysics2(void); // bothazd.qc void AvoidHazards(gedict_t *self); void NewVelocityForArrow(gedict_t *self, vec3_t dir_move, const char *explanation); // route_lookup.qc gedict_t* SightMarker(gedict_t *from_marker, gedict_t *to_marker, float max_distance, float min_height_diff); gedict_t* HigherSightFromFunction(gedict_t *from_marker, gedict_t *to_marker); gedict_t* SightFromMarkerFunction(gedict_t *from_marker, gedict_t *to_marker); gedict_t* SubZoneNextPathMarker(gedict_t *from_marker, gedict_t *to_marker); float SubZoneArrivalTime(float zone_time, gedict_t *middle_marker, gedict_t *to_marker, qbool rl_routes); float SightFromTime(gedict_t *from_marker, gedict_t *to_marker); void ZoneMarker(gedict_t *from_marker, gedict_t *to_marker, qbool path_normal, qbool rj_routes); gedict_t* ZonePathMarker(gedict_t *from_marker, gedict_t *to_marker, qbool path_normal, qbool rl_jump_routes); // botweap.qc void FrogbotSetFirepower(gedict_t *self); void SelectWeapon(void); void SetFireButton(gedict_t *self, vec3_t rel_pos, float rel_dist); void FrogbotWeaponFiredEvent(gedict_t *self); void FindRocketExplosionPoint(vec3_t player_origin, vec3_t player_angles, vec3_t output, float *distance_frac); qbool AttackFinished(gedict_t *self); // marker_util.qc void AssignVirtualGoal(gedict_t *item); void AssignVirtualGoal_apply(gedict_t *marker_); void adjust_view_ofs_z(gedict_t *ent); // botenemy.qc void ClearLookObject(gedict_t *client); void LookEnemy(gedict_t *player, gedict_t *enemy); qbool BotsPickBestEnemy(gedict_t *self); void BotDamageInflictedEvent(gedict_t *attacker, gedict_t *targ); // botjump.qc void CheckCombatJump(gedict_t *self); //void BotInLava(void); void BotPerformRocketJump(gedict_t *self); // botgoal.qc void UpdateGoal(gedict_t *self); // botpath.qc void ProcessNewLinkedMarker(gedict_t *self); // marker_load.qc gedict_t* CreateMarker(float x, float y, float z); void AllMarkersLoaded(void); void SetZone(int zone_number, int marker_number); void SetMarkerFlag(int marker_number, int flags); void SetMarkerFixedSize(int marker_number, int size_x, int size_y, int size_z); void AddToQue(gedict_t *ent); void SetGoal(int goal, int marker_number); void SetGoalForMarker(int goal, gedict_t *marker); void SetMarkerPathFlags(int marker_number, int path_index, int flags); void SetMarkerPath(int source_marker, int path_index, int next_marker); void SetMarkerViewOffset(int marker, float zOffset); #define FROGBOT_PATH_FLAG_OPTIONS "w6rjva" #define FROGBOT_MARKER_FLAG_OPTIONS "u6fbte" // added for ktx qbool fb_lg_disabled(void); //void StartItems(void); // maps void LoadMap(void); qbool FrogbotsCheckMapSupport(void); // float pr1_rint(float f); // void BotEvadeLogic(gedict_t *self); qbool SameTeam(gedict_t *p1, gedict_t *p2); // botstat.qc void FrogbotSetHealthArmour(gedict_t *client); void UpdateGoalEntity(gedict_t *item, gedict_t *taker); // bot_client.qc void BotPlayerDeathEvent(gedict_t *self); qbool BotUsingCorrectWeapon(gedict_t *self); // bot_items.qc int ItemSpawnFunctionCount(void); void StartItemFB(gedict_t *ent); qbool NoItemTouch(gedict_t *self, gedict_t *other); qbool BotsPreTeleport(gedict_t *self, gedict_t *other); // FBCA code just set nextthink to 0 when item respawned... qbool WaitingToRespawn(gedict_t *ent); int NumberOfClients(void); qbool TimeTrigger(float *next_time, float time_increment); qbool IsMarkerFrame(void); qbool IsHazardFrame(void); // fb_globals.c gedict_t* FirstZoneMarker(int zone); void AddZoneMarker(gedict_t *marker); void ResetGoalEntity(gedict_t *self); // bot_commands.qc void SetLinkedMarker(gedict_t *player, gedict_t *marker, char *explanation); void SetJumpFlag(gedict_t *player, qbool jumping, const char *explanation); // bot_routing.qc void PathScoringLogic(float goal_respawn_time, qbool be_quiet, float lookahead_time, qbool path_normal, vec3_t player_origin, vec3_t player_direction, gedict_t *touch_marker_, gedict_t *goalentity_marker, qbool rocket_alert, qbool rocket_jump_routes_allowed, qbool trace_bprint, gedict_t *player, float *best_score, gedict_t **linked_marker_, int *new_path_state, int *new_angle_hint, int *new_rj_frame_delay, float new_rj_angles[2]); int BotVersionNumber(void); qbool FrogbotOptionEnabled(int option); qbool FrogbotShowMarkerIndicators(void); void SetDirectionMove(gedict_t *self, vec3_t dir_move, const char *explanation); void BotEventPlatformHitTop(gedict_t *self); void BotEventPlatformHitBottom(gedict_t *self); void BotEventDoorHitTop(gedict_t *self); void BotEventDoorHitBottom(gedict_t *self); void BotPlatformTouched(gedict_t *platform, gedict_t *player); void BotsBackpackTouchedNonPlayer(gedict_t *backpack, gedict_t *entity); void BotsMatchStart(void); void BotsAssignTeamFlags(void); qbool HasWeapon(gedict_t *player, int weapon); int FrogbotSkillLevel(void); int FrogbotHealth(void); int FrogbotWeapon(void); int FrogbotQuadMultiplier(void); // botthink.qc void SetMarker(gedict_t *client, gedict_t *marker); #define PAST(x) (g_globalvars.time >= self->fb.x) #define FUTURE(x) (g_globalvars.time < self->fb.x) #define MIN_FROGBOT_SKILL 0 #define MAX_FROGBOT_SKILL 20 #define MAX_FROGBOT_AIM_SKILL 20 #define PASSINTVEC3(x) ((int)x[0]),((int)x[1]),((int)x[2]) #define PASSINTVEC2(x) ((int)x[0]),((int)x[1]) #define PASSSCALEDINTVEC3(x,y) ((int)(x[0]*y)),((int)(x[1]*y)),((int)(x[2]*y)) #define FB_MAPDEATHHEIGHT_DEFAULT -9999999 int MapDeathHeight(void); void SetMapDeathHeight(int height); // debugging void RunRandomTrials(float min, float max, float mult); // editor qbool HasSavedMarker(void); #define FB_CVAR_ENABLED "k_fb_enabled" #define FB_CVAR_OPTIONS "k_fb_options" #define FB_CVAR_AUTOADD_LIMIT "k_fb_autoadd_limit" #define FB_CVAR_AUTOREMOVE_AT "k_fb_autoremove_at" #define FB_CVAR_AUTO_DELAY "k_fb_auto_delay" #define FB_CVAR_SKILL "k_fb_skill" #define FB_CVAR_DEBUG "k_fb_debug" #define FB_CVAR_ADMIN_ONLY "k_fb_admin_only" #define FB_CVAR_FREEZE_PREWAR "k_fb_freeze_prewar" #define FB_CVAR_HEALTH "k_fb_health" #define FB_CVAR_WEAPON "k_fb_weapon" #define FB_CVAR_BREAK_ON_DEATH "k_fb_break_on_death" #define FB_CVAR_QUAD_MULTIPLIER "k_fb_quad_multiplier" void BotsFireLogic(void); #endif // ifdef(FB_GLOBALS_H) QW-Group-ktx-d05d6ca/include/g_consts.h000066400000000000000000000255151475442401000200530ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ // // constants // // edict.flags #define FL_FLY 1 #define FL_SWIM 2 #define FL_CLIENT 8 // set for all client edicts #define FL_INWATER 16 // for enter / leave water splash #define FL_MONSTER 32 #define FL_GODMODE 64 // player cheat #define FL_NOTARGET 128 // player cheat #define FL_ITEM 256 // extra wide size for bonus items #define FL_ONGROUND 512 // standing on something #define FL_PARTIALGROUND 1024 // not all corners are valid #define FL_WATERJUMP 2048 // player jumping out of water #define FL_JUMPRELEASED 4096 // for jump debouncing #define FL_ATTACKRELEASED 8192 // for attack debouncing // edict.movetype values #define MOVETYPE_NONE 0 // never moves //#define MOVETYPE_ANGLENOCLIP 1 //#define MOVETYPE_ANGLECLIP 2 #define MOVETYPE_WALK 3 // players only #define MOVETYPE_STEP 4 // discrete, not real time unless fall #define MOVETYPE_FLY 5 #define MOVETYPE_TOSS 6 // gravity #define MOVETYPE_PUSH 7 // no clip to world, push and crush #define MOVETYPE_NOCLIP 8 #define MOVETYPE_FLYMISSILE 9 // fly with extra size against monsters #define MOVETYPE_BOUNCE 10 #define MOVETYPE_BOUNCEMISSILE 11 // bounce with extra size #define MOVETYPE_LOCK 15 // used for player spectating != spectator // edict.solid values #define SOLID_NOT 0 // no interaction with other objects #define SOLID_TRIGGER 1 // touch on edge, but not blocking #define SOLID_BBOX 2 // touch on edge, block #define SOLID_SLIDEBOX 3 // touch on edge, but not an onground #define SOLID_BSP 4 // bsp clip, touch on edge, block // range values #define RANGE_MELEE 0 #define RANGE_NEAR 1 #define RANGE_MID 2 #define RANGE_FAR 3 // deadflag values #define DEAD_NO 0 #define DEAD_DYING 1 #define DEAD_DEAD 2 #define DEAD_RESPAWNABLE 3 // takedamage values #define DAMAGE_NO 0 #define DAMAGE_YES 1 #define DAMAGE_AIM 2 // items #define IT_AXE 4096 #define IT_SHOTGUN 1 #define IT_SUPER_SHOTGUN 2 #define IT_NAILGUN 4 #define IT_SUPER_NAILGUN 8 #define IT_GRENADE_LAUNCHER 16 #define IT_ROCKET_LAUNCHER 32 #define IT_LIGHTNING 64 #define IT_EXTRA_WEAPON 128 #define IT_RL_AND_LG (IT_ROCKET_LAUNCHER | IT_LIGHTNING) #define IT_SHELLS 256 #define IT_NAILS 512 #define IT_ROCKETS 1024 #define IT_CELLS 2048 #define IT_ARMOR1 8192 #define IT_ARMOR2 16384 #define IT_ARMOR3 32768 #define IT_SUPERHEALTH 65536 #define IT_KEY1 131072 #define IT_KEY2 262144 #define IT_INVISIBILITY 524288 #define IT_INVULNERABILITY 1048576 #define IT_SUIT 2097152 #define IT_QUAD 4194304 #define IT_HOOK 8388608 /* Could use these so clients can display which rune they have #define IT_SIGIL1 (1<<28) #define IT_SIGIL2 (1<<29) #define IT_SIGIL3 (1<<30) #define IT_SIGIL4 (1<<31) */ // point content values #define CONTENT_EMPTY -1 #define CONTENT_SOLID -2 #define CONTENT_WATER -3 #define CONTENT_SLIME -4 #define CONTENT_LAVA -5 #define CONTENT_SKY -6 #define STATE_TOP 0 #define STATE_BOTTOM 1 #define STATE_UP 2 #define STATE_DOWN 3 // 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 #define CHAN_FLAG 5 #define CHAN_NO_PHS_ADD 8 #define ATTN_NONE 0 #define ATTN_NORM 1 #define ATTN_IDLE 2 #define ATTN_STATIC 3 // update types #define UPDATE_GENERAL 0 #define UPDATE_STATIC 1 #define UPDATE_BINARY 2 #define UPDATE_TEMP 3 // entity effects #define EF_BRIGHTFIELD 1 //#define EF_MUZZLEFLASH 2 #define EF_GREEN 2 #define EF_BRIGHTLIGHT 4 #define EF_DIMLIGHT 8 #define EF_FLAG1 16 #define EF_FLAG2 32 #define EF_BLUE 64 #define EF_RED 128 // messages // Since BROADCAST is never used in QW 1.5, and MULTICAST is used instead, // just define BROADCAST as MULTICAST for QW 1.5 #define MSG_MULTICAST 4 #define MSG_BROADCAST MSG_MULTICAST #define MSG_ONE 1 // reliable to one (msg_entity) #define MSG_ALL 2 // reliable to all #define MSG_INIT 3 // write to the init string // message levels #define PRINT_LOW 0 // pickup messages #define PRINT_MEDIUM 1 // death messages #define PRINT_HIGH 2 // critical messages #define PRINT_CHAT 3 // also goes to chat console #define AS_STRAIGHT 1 #define AS_SLIDING 2 #define AS_MELEE 3 #define AS_MISSILE 4 #define SPAWNFLAG_NOT_EASY 256 #define SPAWNFLAG_NOT_MEDIUM 512 #define SPAWNFLAG_NOT_HARD 1024 #define SPAWNFLAG_NOT_DEATHMATCH 2048 #define SPAWNFLAG_NOT_SP (SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD) // protocol bytes #define SVC_UPDATEFRAGS 14 #define SVC_TEMPENTITY 23 #define SVC_SETPAUSE 24 #define SVC_CENTERPRINT 26 #define SVC_KILLEDMONSTER 27 #define SVC_FOUNDSECRET 28 #define SVC_INTERMISSION 30 #define SVC_FINALE 31 #define SVC_CDTRACK 32 #define SVC_SELLSCREEN 33 #define SVC_SMALLKICK 34 #define SVC_BIGKICK 35 #define SVC_UPDATEPING 36 #define SVC_UPDATEENTERTIME 37 #define SVC_MUZZLEFLASH 39 #define SVC_UPDATEUSERINFO 40 #define TE_SPIKE 0 #define TE_SUPERSPIKE 1 #define TE_GUNSHOT 2 #define TE_EXPLOSION 3 #define TE_TAREXPLOSION 4 #define TE_LIGHTNING1 5 #define TE_LIGHTNING2 6 #define TE_WIZSPIKE 7 #define TE_KNIGHTSPIKE 8 #define TE_LIGHTNING3 9 #define TE_LAVASPLASH 10 #define TE_TELEPORT 11 #define TE_BLOOD 12 #define TE_LIGHTNINGBLOOD 13 // multicast sets #define MULTICAST_ALL 0 // every client #define MULTICAST_PHS 1 // within hearing #define MULTICAST_PVS 2 // within sight #define MULTICAST_ALL_R 3 // every client, reliable #define MULTICAST_PHS_R 4 // within hearing, reliable #define MULTICAST_PVS_R 5 // within sight, reliable #define MULTICAST_KTX1_EXT 6 // Only send to those using ktx1 protocol extension (todo) #define MULTICAST_MVD_HIDDEN 7 // Insert into MVD stream only, as dem_multiple(0) // health flags #define H_ROTTEN (1) #define H_MEGA (2) // kombat flags #define KF_KTSOUNDS ( 1) // use KTSounds #define KF_SCREEN ( 2) // use autoscreenshot // ( 4) use cfgmap // ( 8) female gender if it is set, if not - male // ( 16) based on server type called alias (see below) #define KF_ON_ENTER ( 32) // don't call on_enter event (every map change) #define KF_SPEED ( 64) // show speed in prewar // ( 128) if it is set mod will call menu_in.cfg // ( 256) if it is set menu_out.cfg will be not called // ( 512) use dmm related map cfg // (1024) do not use stuff sounds // events #define EV_ON_CONNECT ( 1) // connect // ( 2) weapon switch #define EV_ON_MATCH_START ( 4) // match start #define EV_ON_MATCH_END ( 8) // match end #define EV_ON_MATCH_BREAK ( 16) // match break // ( 32) map change // ( 64) deathmatch mode change #define EV_ON_ADMIN ( 128) // admin #define EV_ON_UNADMIN ( 256) // unadmin // CTF #define CTF_RUNE_RES 1 // IT_SIGIL1 #define CTF_RUNE_STR 2 // IT_SIGIL2 #define CTF_RUNE_HST 4 // IT_SIGIL3 #define CTF_RUNE_RGN 8 // IT_SIGIL4 #define CTF_RUNE_MASK 15 #define CTF_FLAG 16 #define FLAG_AT_BASE 0 #define FLAG_CARRIED 1 #define FLAG_DROPPED 2 #define FLAG_RETURNED 3 // here only 200ms before going back to FLAG_AT_BASE // spec moreinfo #define MI_ON ( 1<<0) // on/off #define MI_ADM_ONLY ( 1<<1) // send info to admined specs only or to normal specs too // sv_specprint stuff #define SPECPRINT_CENTERPRINT (0x1) #define SPECPRINT_SPRINT (0x2) #define SPECPRINT_STUFFCMD (0x4) // mmode stuff #define MMODE_NONE (0) #define MMODE_PLAYER (1) #define MMODE_TEAM (2) #define MMODE_MULTI (3) #define MMODE_RCON (4) #define MMODE_NAME (5) // rocket arena #define PLAYERSTATTIME (0.5f) #define MAXIDLETIME (300) //5 minutes // k_sudden_death types #define SD_NORMAL (1) #define SD_TIEBREAK (2) // #define CALLALIAS_SIZE (128) #define F_CHECK_SIZE (1024*10) /* FIXME: which size is reason able */ #define TEAM_LOCATION_UPDATE_TIME (1.0) /* 1 second */ #define DMM4_INVINCIBLE_DEFAULT (2.0) #define DMM4_INVINCIBLE_MAX (30.0) // #define MAX_STUFFED_ALIASES_PER_FRAME (15) #define MAX_STUFFED_QUICKMAPS_PER_FRAME (32) enum { mvdhidden_antilag_position = 0x0000, // mvdhidden_antilag_position_header_t mvdhidden_antilag_position_t* mvdhidden_usercmd = 0x0001, // mvdhidden_usercmd_weapons = 0x0002, // mvdhidden_demoinfo = 0x0003, // mvdhidden_commentary_track = 0x0004, // [todo... ?] mvdhidden_commentary_data = 0x0005, // [todo... format-specific] mvdhidden_commentary_text_segment = 0x0006, // [todo... ] mvdhidden_dmgdone = 0x0007, // mvdhidden_usercmd_weapons_ss = 0x0008, // (same format as mvdhidden_usercmd_weapons) mvdhidden_extended = 0xFFFF // doubt we'll ever get here: read next short... }; #define SV_EXTENSIONS_KTXEXTENSION1 1 #define SV_EXTENSIONS_MVDHIDDEN 2 #define MVDHIDDEN_DMGDONE_SPLASHDAMAGE (1 << 15) #define CLIENT_NAME_LEN 32 // Maximum client name, same value as in server. QW-Group-ktx-d05d6ca/include/g_local.h000066400000000000000000001060521475442401000176300ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id: g_local.h 562 2007-09-24 10:11:18Z d3urk $ */ // g_local.h -- local definitions for game module //#define DEBUG #define CTF_RELOADMAP /* changing ctf status will force map reload */ //#define HITBOXCHECK /* various changes which help test players hit box */ #include "q_shared.h" #include "mathlib.h" #include "progs.h" #include "g_public.h" #include "g_consts.h" #include "g_syscalls.h" #include "player.h" #include "rng.h" #if defined(_WIN32) #define QW_PLATFORM "Windows" #define QW_PLATFORM_SHORT "w" #elif defined(__FreeBSD__) #define QW_PLATFORM "FreeBSD" #define QW_PLATFORM_SHORT "f" #elif defined(__OpenBSD__) #define QW_PLATFORM "OpenBSD" #define QW_PLATFORM_SHORT "o" #elif defined(__NetBSD__) #define QW_PLATFORM "NetBSD" #define QW_PLATFORM_SHORT "n" #elif defined(__DragonFly__) #define QW_PLATFORM "DragonFly" #define QW_PLATFORM_SHORT "d" #elif defined(__linux__) #define QW_PLATFORM "Linux" #define QW_PLATFORM_SHORT "l" #elif defined(__sun__) #define QW_PLATFORM "SunOS" #define QW_PLATFORM_SHORT "s" #elif defined(__APPLE__) #define QW_PLATFORM "MacOS" #define QW_PLATFORM_SHORT "m" #else #define QW_PLATFORM "Unknown" #define QW_PLATFORM_SHORT "u" #endif #define MOD_NAME ("KTX") #define MOD_FULLNAME ("KTX: Kombat Teams eXtreme") #define MOD_VERSION ("1.45") #define MOD_BUILD_DATE (__DATE__ ", " __TIME__) #define MOD_SERVERINFO_MOD_KEY ("ktxver") #define MOD_URL ("https://github.com/QW-Group/ktx") #define GIT_COMMIT ("") // keep lines to 38 chars max //#define MOD_RELEASE_QUOTE ("This KTX version is dedicated to the\n2022 November QuakeWorld LAN Parties!\nRadomsko QW Lan, Poland, November 9-13\nQHLAN-22, Stockholm, November 17-20\n") //#define MOD_RELEASE_HASHTAGS ("#COVID19 #StayHomeStaySafe #PlaySomeQW") // qqshka - hmm, seems in C this is macros #undef max #undef min #ifndef min //#define min(a,b) ((a) < (b) ? (a) : (b)) float min(float a, float b); #define KTX_MIN #endif #ifndef max //#define max(a,b) ((a) > (b) ? (a) : (b)) float max(float a, float b); #define KTX_MAX #endif float bound(float a, float b, float c); //#define bound(a,b,c) ((a) >= (c) ? (a) : (b) < (a) ? (a) : (b) > (c) ? (c) : (b)) //used for bots and combat #define PASSINTVEC3(x) ((int)x[0]),((int)x[1]),((int)x[2]) #define PASSSCALEDINTVEC3(x,y) ((int)(x[0]*y)),((int)(x[1]*y)),((int)(x[2]*y)) #if defined(DEBUG) || defined(_DEBUG) #define DebugTrap(x) *(char**)0=x #else #define DebugTrap(x) G_Error(x) #endif #define MOTD_LINES (15) #define MAX_LASTSCORES (30) #define MAX_STRINGS 128 #define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString #define MAX_STRING_TOKENS 1024 // max tokens resulting from Cmd_TokenizeString #define MAX_TOKEN_CHARS 1024 // max length of an individual token #define FOFS(x) ((intptr_t)&(((gedict_t *)0)->x)) #define GOFS(x) ((intptr_t)&(((globalvars_t *)0)->x)) #define FOFCLSN ( FOFS ( classname ) ) int NUM_FOR_EDICT(gedict_t *e); // possible disallowed weapons #define DA_WPNS (IT_AXE|IT_SHOTGUN|IT_SUPER_SHOTGUN|IT_NAILGUN|IT_SUPER_NAILGUN|IT_ROCKET_LAUNCHER|IT_GRENADE_LAUNCHER|IT_LIGHTNING) extern qbool FTE_sv; // is we run on FTE server extern gameData_t gamedata; extern gedict_t g_edicts[]; extern char mapname[64]; extern globalvars_t g_globalvars; extern gedict_t *world; extern gedict_t *self, *other; extern gedict_t *newmis; extern int timelimit, fraglimit, teamplay, deathmatch, framecount, coop, skill; extern int sv_extensions; //extern float rj; #define EDICT_TO_PROG(e) ((byte *)(e) - (byte *)g_edicts) #define PROG_TO_EDICT(e) ((gedict_t *)((byte *)g_edicts + (e))) void G_Printf(const char *fmt, ...) PRINTF_FUNC(1); void G_Error(const char *fmt, ...) PRINTF_FUNC(1); #define PASSVEC3(x) (x[0]),(x[1]),(x[2]) #define SetVector(v,x,y,z) (v[0]=x,v[1]=y,v[2]=z) // some types typedef enum { gtUnknown = 0, gtDuel, gtTeam, gtFFA, gtCTF } gameType_t; typedef enum { umUnknown = 0, um1on1, um2on2, um3on3, um4on4, um10on10, umFfa, umCtf, umHooneyM, umBlitz2v2, umBlitz4v4, um2on2on2, um3on3on3, um4on4on4, umXonX } UserModes_t; typedef enum { lsUnknown = 0, lsDuel, lsTeam, lsFFA, lsCTF, lsRA, // note no correspoding gameType_t for lsType lsCA, lsWO, lsHM, lsRACE } lsType_t; // lastscores type // Spike: // Extension builtins. // The order of these don't matter (qqshka: what about QVM builds? look g_syscalls.asm, we need something similar for extensions I guess), // they'll be blindly assigned to slots without conflicting with extras other engines try to add to core. // They do need indexes that don't conflict with gameImport_t though. #define G_EXTENSIONS_FIRST 256 enum { G_SETEXTFIELD = G_EXTENSIONS_FIRST, G_GETEXTFIELD, G_CHANGELEVEL_HUB, G_URI_QUERY, G_PARTICLEEFFECTNUM, G_TRAILPARTICLES, G_POINTPARTICLES, G_CLIENTSTAT, G_POINTERSTAT, G_MAPEXTFIELDPTR, G_SETEXTFIELDPTR, G_GETEXTFIELDPTR, G_SETSENDNEEDED, G_EXTENSIONS_LAST }; extern qbool haveextensiontab[G_EXTENSIONS_LAST-G_EXTENSIONS_FIRST]; #define HAVEEXTENSION(idx) haveextensiontab[(idx) - G_EXTENSIONS_FIRST] #define DEATHTYPE( _dt_, _dt_str_ ) _dt_, typedef enum { #include "deathtype.h" } deathType_t; #undef DEATHTYPE // g_cmd.c // g_utils.c // K_SPW_0_NONRANDOM changes "Normal QW respawns" to "pre-qtest nonrandom respawns" #define K_SPW_0_NONRANDOM void g_random_seed(int); float g_random(void); float crandom(void); int i_rnd(int from, int to); float dist_random(float minValue, float maxValue, float spreadFactor); float next_frame(void); gedict_t* spawn(void); void ent_remove(gedict_t *t); void soft_ent_remove(gedict_t *ent); gedict_t* nextent(gedict_t *ent); gedict_t* find(gedict_t *start, int fieldoff, char *str); gedict_t* ez_find(gedict_t *start, char *str); int find_cnt(int fieldoff, char *str); gedict_t* find_idx(int idx, int fieldoff, char *str); //gedict_t *findradius( gedict_t * start, vec3_t org, float rad ); gedict_t* findradius_ignore_solid(gedict_t *start, vec3_t org, float rad); void normalize(vec3_t value, vec3_t newvalue); float vlen(vec3_t value1); float vectoyaw(vec3_t value1); void vectoangles(vec3_t value1, vec3_t ret); void changeyaw(gedict_t *ent); char* va(char *format, ...) PRINTF_FUNC(1); char* redtext(char *format); char* cleantext(char *format); char* dig3(int d); char* dig3s(const char *format, ...) PRINTF_FUNC(1); char* striphigh(char *format); char* stripcaps(char *format); void G_sprint(gedict_t *ed, int level, const char *fmt, ...) PRINTF_FUNC(3); void G_sprint_flags(gedict_t *ed, int level, int flags, const char *fmt, ...) PRINTF_FUNC(4); void G_bprint(int level, const char *fmt, ...) PRINTF_FUNC(2); void G_bprint_flags(int level, int flags, const char *fmt, ...) PRINTF_FUNC(3); void G_centerprint(gedict_t *ed, const char *fmt, ...) PRINTF_FUNC(2); /* centerprint to all clients */ void G_cp2all(const char *fmt, ...) PRINTF_FUNC(1); void G_cprint(const char *fmt, ...) PRINTF_FUNC(1); void G_dprint(const char *fmt, ...) PRINTF_FUNC(1); void localcmd(const char *fmt, ...) PRINTF_FUNC(1); int streq(const char *s1, const char *s2); int strneq(const char *s1, const char *s2); int strnull(const char *s1); /* #define strneq(s1,s2) (strcmp( (s1) ? (s1) : "", (s2) ? (s2) : "" )) #define streq(s1,s2) (!strneq((s1), (s2))) #define strnull(s1) ((s1) ? !*(s1) : true) */ void aim(vec3_t ret); void setorigin(gedict_t *ed, float origin_x, float origin_y, float origin_z); void setsize(gedict_t *ed, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); void setmodel(gedict_t *ed, char *model); void sound(gedict_t *ed, int channel, char *samp, float vol, float att); gedict_t* checkclient(void); void traceline(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, int nomonst, gedict_t *ed); void TraceCapsule(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, int nomonst, gedict_t *ed, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); void stuffcmd(gedict_t *ed, const char *fmt, ...) PRINTF_FUNC(2); void stuffcmd_flags(gedict_t *ed, int flags, const char *fmt, ...) PRINTF_FUNC(3); int droptofloor(gedict_t *ed); int walkmove(gedict_t *ed, float yaw, float dist); int movetogoal(float dist); int checkbottom(gedict_t *ed); void makestatic(gedict_t *ed); void setspawnparam(gedict_t *ed); void logfrag(gedict_t *killer, gedict_t *killee); char* infokey(gedict_t *ed, char *key, char *valbuff, int sizebuff); char* ezinfokey(gedict_t *ed, char *key); int iKey(gedict_t *ed, char *key); float fKey(gedict_t *ed, char *key); void WriteEntity(int to, gedict_t *ed); void WriteByte(int to, int data); void WriteShort(int to, int data); void WriteLong(int to, int data); void WriteString(int to, char *data); void WriteAngle(int to, float data); void WriteCoord(int to, float data); float cvar(const char *var); char* cvar_string(const char *var); void cvar_set(const char *var, const char *val); void cvar_fset(const char *var, float val); #define MAX_TEAM_NAME (32) // qqshka: 32 - is max len of team name? //extern char teams[MAX_CLIENTS][MAX_TEAM_NAME]; int getteams(char teams[MAX_CLIENTS][MAX_TEAM_NAME]); char* getteam(gedict_t *ed); char* getname(gedict_t *ed); char* g_his(gedict_t *ed); char* g_he(gedict_t *ed); char* g_himself(gedict_t *ed); gedict_t* find_client(gedict_t *start); gedict_t* find_plr(gedict_t *start); gedict_t* find_plr_same_team(gedict_t *start, char *team); gedict_t* find_spc(gedict_t *start); gedict_t* find_plrghst(gedict_t *start, int *from); gedict_t* find_plrspc(gedict_t *start, int *from); gedict_t* player_by_id(int id); gedict_t* player_by_name(const char *name); gedict_t* player_by_IDorName(const char *IDname); gedict_t* spec_by_id(int id); gedict_t* spec_by_name(const char *name); gedict_t* spec_by_IDorName(const char *IDname); gedict_t* SpecPlayer_by_IDorName(const char *IDname); gedict_t* SpecPlayer_by_id(int id); gedict_t* not_connected_by_id(int id); gedict_t* not_connected_by_name(const char *name); gedict_t* not_connected_by_IDorName(const char *IDname); char* armor_type(int items); qbool isghost(gedict_t *ed); qbool isDuel(void); qbool isTeam(void); qbool isFFA(void); qbool isCTF(void); qbool isUnknown(void); int tp_num(void); int GetUserID(gedict_t *p); char* TrackWhom(gedict_t *p); int GetHandicap(gedict_t *p); qbool SetHandicap(gedict_t *p, int nhdc); void changelevel(const char *name); char* Get_PowerupsStr(void); int Get_Powerups(void); char* count_s(int cnt); char* Enables(float f); char* Enabled(float f); char* Allows(float f); char* Allowed(float f); char* OnOff(float f); int get_scores1(void); int get_scores2(void); int get_scores3(void); gedict_t* get_ed_scores1(void); gedict_t* get_ed_scores2(void); gedict_t* get_ed_best1(void); gedict_t* get_ed_best2(void); gedict_t* get_ed_bestPow(void); char* str_noweapon(int k_disallow_weapons); void cvar_toggle_msg(gedict_t *p, char *cvarName, char *msg); qbool can_exec(char *name); void ghostClearScores(gedict_t *g); void update_ghosts(void); // { events void on_enter(void); void on_connect(void); void on_match_start(gedict_t *p); void on_match_end(gedict_t *p); void on_match_break(gedict_t *p); void on_admin(gedict_t *p); void on_unadmin(gedict_t *p); void info_ev_update(gedict_t *p, char *from, char *to); void info_kf_update(gedict_t *p, char *from, char *to); // } void cl_refresh_plus_scores(gedict_t *p); void refresh_plus_scores(void); void disableupdates(gedict_t *ed, float time); int only_digits(const char *s); char* params_str(int from, int to); char* SD_type_str(void); // sudden death type string char* respawn_model_name(int mdl_num); char* respawn_model_name_short(int mdl_num); int get_fair_pack(void); int get_fallbunny(void); void remove_projectiles(void); void SetUserInfo(gedict_t *p, const char *varname, const char *value, int flags); void safe_precache_model(char *name); void safe_precache_sound(char *name); char* cl_ip(gedict_t *p); char* clean_string(char *s); void visible_to(gedict_t *viewer, gedict_t *first, int len, byte *visible); // Work around for the fact that QVM dos not support ".*s" in printf() family functions. // It retuns dots array filled with dots, amount of dots depends of how long cmd name and longest cmd name. char* make_dots(char *dots, size_t dots_len, int cmd_max_len, char *cmd); // // subs.c void SUB_CalcMove(vec3_t tdest, float tspeed, void (*func)(void)); void SUB_CalcMoveEnt(gedict_t *ent, vec3_t tdest, float tspeed, void (*func)(void)); void SUB_UseTargets(void); void SetMovedir(void); void InitTrigger(void); extern gedict_t *activator; // // g_mem.c void* G_Alloc(int size); void G_InitMemory(void); // // g_spawn.c void G_SpawnEntitiesFromString(void); qbool G_SpawnString(const char *key, const char *defaultString, char **out); qbool G_SpawnFloat(const char *key, const char *defaultString, float *out); qbool G_SpawnInt(const char *key, const char *defaultString, int *out); qbool G_SpawnVector(const char *key, const char *defaultString, float *out); void SUB_Remove(void); void SUB_RM_01(gedict_t *ent); void SUB_Null(void); //world.c void CopyToBodyQue(gedict_t *ent); void ClearBodyQue(void); // client.c extern vec3_t VEC_ORIGIN; extern vec3_t VEC_HULL_MIN; extern vec3_t VEC_HULL_MAX; extern vec3_t VEC_HULL2_MIN; extern vec3_t VEC_HULL2_MAX; extern float intermission_running; extern float intermission_exittime; extern gedict_t *intermission_spot; extern int modelindex_eyes, modelindex_player; void set_nextmap(char *map); void GotoNextMap(void); qbool CheckRate(gedict_t *p, char *newrate); int tiecount(void); void Check_SD(gedict_t *p); void SetChangeParms(void); void SetNewParms(void); void ClientConnect(void); void k_respawn(gedict_t *p, qbool body); void PutClientInServer(void); void ClientDisconnect(void); void PlayerPreThink(void); void BothPostThink(void); // <- called for player and spec void PlayerPostThink(void); qbool PlayerCanPause(gedict_t *p); void SuperDamageSound(void); char *Spawn_GetModel(void); gedict_t* SelectSpawnPoint(char *spawnname); #define WP_STATS_UPDATE (0.3f) void Print_Wp_Stats(void); #define SC_STATS_UPDATE (0.8f) void Print_Scores(void); // { "new weapon stats" void WS_Mark(gedict_t *p, weaponName_t wp); void WS_Reset(gedict_t *p); void WS_OnSpecPovChange(gedict_t *s, qbool force); // } //spectate.c void SpectatorConnect(void); void PutSpectatorInServer(void); void SpectatorDisconnect(void); void SpectatorThink(void); // weapons.c extern int impulse; float W_BestWeapon(void); void W_Precache(void); void W_SetCurrentAmmo(void); void SpawnBlood(vec3_t, float); void SpawnMeatSpray(vec3_t org, vec3_t vel); void W_FireAxe(void); void W_FireSpikes(float ox); void W_FireLightning(void); void LightningDamage(vec3_t p1, vec3_t p2, gedict_t *from, float damage); qbool W_CanSwitch(int wp, qbool warn); void FireBullets(float shotcount, vec3_t dir, float spread_x, float spread_y, float spread_z, deathType_t deathtype); void launch_spike(vec3_t org, vec3_t dir); // match.c int WeirdCountPlayers(void); float CountPlayers(void); float CountBots(void); float CountRTeams(void); qbool isCanStart(gedict_t *s, qbool forceMembersWarn); void StartTimer(void); void StopTimer(int removeDemo); char* WpName(weaponName_t wp); //combat.c extern gedict_t *damage_attacker, *damage_inflictor; char* death_type(deathType_t dt); qbool ISLIVE(gedict_t *e); qbool ISDEAD(gedict_t *e); qbool CanDamage(gedict_t *targ, gedict_t *inflictor); void T_Damage(gedict_t *targ, gedict_t *inflictor, gedict_t *attacker, float damage); void T_RadiusDamage(gedict_t *inflictor, gedict_t *attacker, float damage, gedict_t *ignore, deathType_t dtype); void T_BeamDamage(gedict_t *attacker, float damage); //items.c void DropPowerup(float timeleft, int powerup); void DropPowerups(void); void ShowSpawnPoints(void); void HideSpawnPoints(void); void DropBackpack(void); void adjust_pickup_time(float *current, float *total); //triggers.c void play_teleport(gedict_t *sndspot); void spawn_tfog(vec3_t org); #define TFLAGS_FOG_SRC (1<<0) #define TFLAGS_FOG_DST (1<<1) #define TFLAGS_FOG_DST_SPAWN (1<<2) #define TFLAGS_SND_SRC (1<<3) #define TFLAGS_SND_DST (1<<4) #define TFLAGS_VELOCITY_ADJUST (1<<5) void teleport_player(gedict_t *player, vec3_t origin, vec3_t angles, int flags); #define TELEDEATH(e) ((e)->deathtype == dtTELE1 || (e)->deathtype == dtTELE2 || (e)->deathtype == dtTELE3) // runes.c void DropRune(void); void SpawnRunes(qbool yes); void TossRune(void); void ResistanceSound(gedict_t *player); void HasteSound(gedict_t *player); void RegenerationSound(gedict_t *player); // ctf.c void PlayerDropFlag(gedict_t *player, qbool tossed); void RegenFlags(qbool yes); void AddHook(qbool yes); void CTF_Obituary(gedict_t *targ, gedict_t *attacker); void CTF_CheckFlagsAsKeys(void); // logs.c void log_open(const char *fmt, ...) PRINTF_FUNC(1); void log_printf(const char *fmt, ...) PRINTF_FUNC(1); void log_close(void); extern fileHandle_t log_handle; // commands.c void WillPause(void); typedef struct cmd_s { char *name; // funcref_t f; void (*f)(void); float arg; int cf_flags; const char *description; } cmd_t; #define CF_PLAYER ( 1<<0 ) /* command valid for players */ #define CF_SPECTATOR ( 1<<1 ) /* command valid for specs */ #define CF_BOTH ( CF_PLAYER | CF_SPECTATOR ) /* command valid for both: specs and players */ #define CF_PLR_ADMIN ( 1<<2 ) /* client is player, so this command require admin rights */ #define CF_SPC_ADMIN ( 1<<3 ) /* client is spectator, so this command require admin rights */ #define CF_BOTH_ADMIN ( CF_PLR_ADMIN | CF_SPC_ADMIN ) /* this command require admin rights, any way */ #define CF_MATCHLESS ( 1<<4 ) /* command valid for matchLess mode */ #define CF_PARAMS ( 1<<5 ) /* command have some params */ #define CF_NOALIAS ( 1<<6 ) /* command haven't alias and may be accessed only via /cmd commandname */ #define CF_REDIRECT ( 1<<7 ) /* command will be redirected to server as /cmd commandname */ #define CF_MATCHLESS_ONLY ( 1<<8 ) /* command valid for matchLess mode _only_ */ #define CF_CONNECTION_FLOOD ( 1<<9 ) /* allow flood at connection time, say first 30 seconds */ extern cmd_t cmds[]; extern int cmds_cnt; // count of commands in 'cmds' // // DoCommand/DoCommand_Name return codes // return non-negative value if command success // #define DO_OUT_OF_RANGE_CMDS (-1) // if command is out of range in 'cmds' array or not found #define DO_WRONG_CLASS (-2) // if wrong class #define DO_ACCESS_DENIED (-3) // if access denied #define DO_FUNCTION_IS_WRONG (-4) // if function is wrong #define DO_CMD_DISALLOWED_MATCHLESS (-5) // if cmd does't allowed in matchLess mode #define DO_FLOOD_PROTECT (-6) // if command is blocked due to flood protect #define DO_CMD_MATCHLESS_ONLY (-7) // if cmd allowed in matchLess mode _only_ int DoCommand(int icmd); int DoCommand_Name(char *cmd_name); qbool isCmdFlood(gedict_t *p); void Init_cmds(void); void StuffModCommands(gedict_t *p); void SetPractice(int srv_practice_mode, const char *map); void execute_rules_reset(void); // { usermodes // um_flags #define UM_1ON1 ( 1<<0 ) // `0000 0000 0000 0000 0000 0000 0000 0001` = 1 #define UM_2ON2 ( 1<<1 ) // `0000 0000 0000 0000 0000 0000 0000 0010` = 2 #define UM_3ON3 ( 1<<2 ) // `0000 0000 0000 0000 0000 0000 0000 0100` = 4 #define UM_4ON4 ( 1<<3 ) // `0000 0000 0000 0000 0000 0000 0000 1000` = 8 #define UM_10ON10 ( 1<<4 ) // `0000 0000 0000 0000 0000 0000 0001 0000` = 16 #define UM_FFA ( 1<<5 ) // `0000 0000 0000 0000 0000 0000 0010 0000` = 32 #define UM_CTF ( 1<<6 ) // `0000 0000 0000 0000 0000 0000 0100 0000` = 64 #define UM_1ON1HM ( 1<<7 ) // `0000 0000 0000 0000 0000 0000 1000 0000` = 128 #define UM_2ON2ON2 ( 1<<8 ) // `0000 0000 0000 0000 0000 0001 0000 0000` = 256 #define UM_3ON3ON3 ( 1<<9 ) // `0000 0000 0000 0000 0000 0010 0000 0000` = 512 #define UM_4ON4ON4 ( 1<<10 ) // `0000 0000 0000 0000 0000 0100 0000 0000` = 1024 #define UM_XONX ( 1<<11 ) // `0000 0000 0000 0000 0000 1000 0000 0000` = 2048 #define UM_RACEMODE ( 1<<31 ) // `1000 0000 0000 0000 0000 0000 0000 0000` = typedef struct usermode_s { const char *name; const char *displayname; const char *initstring; int um_flags; int race_plrs_per_team; } usermode; extern usermode um_list[]; extern int um_cnt; // count of entrys in 'um_list' extern UserModes_t current_umode; // current UserMode // for user call this like UserMode( 1 ) // for server call like UserMode( -1 ) void UserMode(float umode); int um_idx_byname(char *name); // return -1 if not found const char *um_name_byidx(UserModes_t idx); // } // { spec more info qbool mi_on(void); qbool mi_adm_only(void); void mi_print(gedict_t *tooker, int it, char *msg); void info_mi_update(gedict_t *p, char *from, char *to); // } // { communication commands void s_lr_clear(gedict_t *dsc); // } // vip.c // qqshka: hmm, like ktpro #define VIP_NORMAL ( 1) // normal VIP (default) #define VIP_NOTKICKABLE ( 2) // not kickable VIP by elected admins #define VIP_ADMIN ( 4) // VIP with admin rights // 8 - VIP with demo admin rights // 16 - VIP with judge rights #define VIP_RCON (32) // VIP with rcon admin rights #define ALLOWED_NOSPECS_VIPS ( VIP_NOTKICKABLE | VIP_ADMIN | VIP_RCON ) int VIP(gedict_t *cl); int VIP_IsFlags(gedict_t *cl, int flags); void VIP_ShowRights(gedict_t *cl); // g_userinfo.c void cmdinfo_infoset(gedict_t *p); // vote.c typedef struct votemap_s { int map_id; int map_votes; int admins; } votemap_t; typedef struct rpickupTeams_s { char name[5]; char topColor[3]; char bottomColor[3]; char stuffCmd[30]; } rpickupTeams_t; extern votemap_t maps_voted[]; int vote_get_maps(void); qbool is_elected(gedict_t *p, electType_t et); int get_elect_type(void); char* get_elect_type_str(void); void vote_clear(int fofs); int get_votes_req(int fofs, qbool diff); int get_votes(int fofs); int get_votes_by_value(int fofs, int value); int is_admins_vote(int fofs); void vote_check_map(void); void vote_check_break(void); void vote_check_elect(void); void vote_check_pickup(void); void vote_check_rpickup(int maxRecursion); void vote_check_swapall(void); void vote_check_all(void); #define VOTE_FOFS(x) ((intptr_t)&(((vote_t *)0)->x)) #define OV_BREAK ( VOTE_FOFS ( brk ) ) #define OV_ELECT ( VOTE_FOFS ( elect ) ) #define OV_PICKUP ( VOTE_FOFS ( pickup ) ) #define OV_RPICKUP ( VOTE_FOFS ( rpickup ) ) #define OV_MAP ( VOTE_FOFS ( map ) ) #define OV_NOSPECS ( VOTE_FOFS ( nospecs ) ) #define OV_TEAMOVERLAY ( VOTE_FOFS ( teamoverlay ) ) #define OV_COOP ( VOTE_FOFS ( coop ) ) #define OV_HOOKSMOOTH (VOTE_FOFS ( hooksmooth ) ) #define OV_HOOKFAST (VOTE_FOFS ( hookfast ) ) #define OV_HOOKCLASSIC (VOTE_FOFS ( hookclassic ) ) #define OV_HOOKCRHOOK (VOTE_FOFS ( hookcrhook ) ) #define OV_ANTILAG ( VOTE_FOFS ( antilag ) ) #define OV_PRIVATE ( VOTE_FOFS ( privategame ) ) //#define OV_KICKUNAUTHED ( VOTE_FOFS (kick_unauthed) ) #define OV_SWAPALL ( VOTE_FOFS ( swapall ) ) #define MAX_RPICKUP_RECUSION 3 #define MAX_PAUSE_REQUESTS 3 void ElectThink(void); void AbortElect(void); // admin.c // admin flags #define AF_ADMIN (1<<0) // elected admin #define AF_REAL_ADMIN (1<<1) // pass/vip granted admin (real admin in terms of ktpro) qbool is_real_adm(gedict_t *p); // is pass/vip granted admin (real admin in terms of ktpro) qbool is_adm(gedict_t *p); // is elected admin (admin rigths granted by /elect command) void KickThink(void); void ExitKick(gedict_t *kicker); void BecomeAdmin(gedict_t *p, int adm_flags); void VoteAdmin(void); void PlayerStopFire(gedict_t *p); void do_force_spec(gedict_t *p, gedict_t *admin, qbool spec); // arena.c void ra_init_que(void); gedict_t* ra_que_first(void); void ra_in_que(gedict_t *p); void ra_out_que(gedict_t *p); qbool ra_isin_que(gedict_t *p); int ra_pos_que(gedict_t *p); qbool isRA(void); // not game mode, but just modificator of duel qbool isWinner(gedict_t *p); qbool isLoser(gedict_t *p); gedict_t* getWinner(void); gedict_t* getLoser(void); void ra_ClientDisconnect(void); void ra_ClientObituary(gedict_t *targ, gedict_t *attacker); void ra_PutClientInServer(void); void RocketArenaPre(void); qbool readytostart(void); void ra_Frame(void); void setfullwep(gedict_t *anent); void setnowep(gedict_t *anent); // { ra commands void ra_PlayerStats(void); void ra_PrintPos(void); void ra_break(void); // } // clan_arena.c qbool isCA(void); qbool CA_CheckAlive(gedict_t *p); int CA_wins_required(void); int CA_count_ready_players(void); int CA_get_score_1(void); int CA_get_score_2(void); void SM_PrepareCA(void); void CA_ClientObituary(gedict_t *targ, gedict_t *attacker); void CA_MatchBreak(void); void CA_PrintScores(void); void CA_TeamsStats(void); void CA_player_pre_think(void); void CA_spectator_think(void); void CA_Frame(void); void CA_PutClientInServer(void); qbool CA_can_fire(gedict_t *p); // captain.c int capt_num(gedict_t *p); // coach.c int coach_num(gedict_t *p); qbool is_coach(gedict_t *p); void ExitCoach(void); // maps.c void StuffMaps(gedict_t *p); void GetMapList(void); char* GetMapName(int imp); int GetMapNum(char *mapname); void DoSelectMap(int iMap); void SelectMap(void); void VoteMap(void); qbool VoteMapSpecific(char *map); // match.c void EndMatch(float skip_log); void StatsToFile(void); // grapple.c void GrappleThrow(void); void GrappleService(void); void GrappleReset(gedict_t *rhook); void CancelHook(gedict_t *owner); float IncreasePullSpeed(float speed, float incr); float DecreasePullSpeed(float speed, float decr); // hoonymode.c #define HM_PT_FINAL 1 #define HM_PT_SET 2 qbool isHoonyModeDuel(void); qbool isHoonyModeAny(void); qbool isHoonyModeTDM(void); gedict_t* HM_choose_spawn_point(gedict_t *player); void HM_log_spawn_point(gedict_t *player, gedict_t *spawn); void HM_draw(void); void HM_suicide(gedict_t *player); void HM_next_point(gedict_t *won, gedict_t *lost); void HM_all_ready(void); void HM_reset_map(void); void HM_initialise_rounds(void); void HM_rounds_adjust(int change); int HM_current_point_type(void); int HM_current_point(void); int HM_rounds(void); int HM_timelimit(void); char* HM_lastscores_extra(void); qbool HM_is_game_over(void); void HM_name_map_spawn(gedict_t *spawn); void HM_pick_spawn(void); void HM_unpick_all_spawns(void); void HM_roundsup(void); void HM_roundsdown(void); void HM_point_stats(void); void HM_restore_spawns(void); void HM_match_break(void); const char* HM_round_explanation(void); const char* HM_series_explanation(void); const char* HM_round_results(gedict_t *player); // race.c typedef struct race_stats_score_s { char *name; int wins; int score; int completions; float best_time; float total_time; float total_distance; } race_stats_score_t; qbool isRACE(void); void apply_race_settings(void); void ToggleRace(void); void RaceCountdownChange(float t); void StartDemoRecord(void); qbool race_weapon_allowed(gedict_t *p); void race_init(void); void race_shutdown(char *msg); void race_think(void); void race_add_standard_routes(void); void race_set_one_player_movetype_and_etc(gedict_t *p); gedict_t* race_get_racer(void); void setwepnone(gedict_t *p); void setwepall(gedict_t *p); qbool race_handle_event(gedict_t *player, gedict_t *object, const char *eventName); void race_player_pre_think(void); void race_player_post_think(void); int race_count_votes_req(float percentage); qbool race_allow_map_vote(gedict_t *player); gedict_t* race_find_race_participants(gedict_t *p); qbool race_match_mode(void); char* race_scoring_system_name(void); void race_match_stats(void); race_stats_score_t* race_get_player_stats(int *players); // globals.c extern int k_bloodfest; // blood fest mode extern float k_killquad; // killquad mode extern float framechecks; // if timedemo/uptime bugs are tolerated extern float k_attendees; // stores number of players on server - used in 'ready' checking extern float k_captains; // number of captains extern float k_captainturn; // which captain comes in line to pick extern float k_coaches; // number of coaches extern float k_checkx; extern float k_force; // used in forcing matchstart extern float k_maxspeed; // used to store server maxspeed to allow switching by admins extern float k_oldmaxspeed; // used to store old value of maxspeed prior to freezing the map extern float k_showscores; // whether or not should print the scores or not extern float k_nochange; // used to indicate if frags changes somehow since last time 'scores' command was called extern float k_standby; // if server is in standy mode extern float k_sudden_death; // to mark if sudden death overtime is currently the case extern float k_teamid; extern float k_userid; extern float k_whonottime; // NOT_SURE: extern float match_in_progress; // if a match has begun extern float match_start_time; // time when match has been started extern float match_end_time; // time when match is expected to end extern float match_over; // boolean - whether or not the match stats have been printed at end of game extern int k_berzerk; // berzerk mode extern float k_berzerktime; // berzerk mode time left extern gedict_t *newcomer; // stores last player who joined extern int k_overtime; // is overtime is going on extern float current_maxfps; // current value of maxfps // { yawn mode extern int k_yawnmode; // is server in yawn mode extern int k_fallbunny_cap; // fallbunny cap procent in yawn mode extern int k_teleport_cap; // cap for keeping velocity through tele // } extern int k_practice; // is server in practice mode extern int k_matchLess; // is server in matchLess mode extern int k_matchLess_idle_time; extern int k_matchLess_idle_warn; extern gameType_t k_mode; // game type: DUEL, TP, FFA extern int k_lastvotedmap; // last voted map, used for agree command? // { CTF extern int k_ctf_custom_models; // use or not custom models extern int k_allowed_free_modes; // reflect appropriate cvar - but changed only at map load #ifdef CTF_RELOADMAP extern qbool k_ctf; // is ctf was active at map load #endif // } // { cmd flood protection extern int k_cmd_fp_count; // 10 commands allowed .. extern float k_cmd_fp_per; // per 4 seconds extern float k_cmd_fp_for; // skip commands for 5 seconds extern int k_cmd_fp_kick; // kick after 4 warings extern int k_cmd_fp_dontkick; // if 1 - don't use kick extern int k_cmd_fp_disabled; // if 1 - don't use cmd floodprot // } extern float k_sv_locktime; // some time before non VIP players can't connect, spectators not affected extern qbool vw_available; // vwep extension available extern qbool vw_enabled; // vweps enabled // { rocket arena extern float time_to_start; //time to start match extern int ra_match_fight; // have winner and loser fighting // } // { clan arena extern int ca_round_pause; // } extern int jumpf_flag; // falling velocity criteria extern float f_check; // is we in state of some f_xxx check extern float lastTeamLocationTime; // next udate for CheckTeamStatus() extern qbool first_rl_taken; // true when some one alredy took rl extern int sv_minping; // used to broadcast changes // { SP #define FRAMETIME 0.1 // ANIM() macro idea I got from Tonik #define ANIM(name, _frame, _next) \ void name (void) { \ self->s.v.frame = _frame; \ self->s.v.nextthink = g_globalvars.time + FRAMETIME; \ self->think = ( func_t ) _next; } // sp_client.c void ExitIntermission(void); char* ObituaryForMonster(char *attacker_class); // sp_dog.c float DogCheckAttack(void); // sp_demon.c float DemonCheckAttack(void); // sp_ogre.c float OgreCheckAttack(void); // sp_shambler.c float ShamCheckAttack(void); // sp_soldier.c float SoldierCheckAttack(void); // sp_wizard.c float WizardCheckAttack(void); // sp_ai.c // FIXME: make them static or get rid of globals... extern float enemy_vis, enemy_infront, enemy_range; extern float enemy_yaw; void FoundTarget(void); void GetMadAtAttacker(gedict_t *attacker); void SUB_AttackFinished(float normal); void SUB_CheckRefire(func_t thinkst); void ai_stand(void); void ai_walk(float dist); void ai_run(float dist); void ai_pain(float dist); void ai_face(void); void ai_charge(float d); void ai_charge_side(void); void ai_forward(float dist); void ai_back(float dist); void ai_turn(void); void ai_painforward(float dist); void ai_melee(void); void ai_melee_side(void); // sp_monsters.c typedef struct bloodfest_s { float monsters_spawn_time; // is it time to start monsters spawn wave. int monsters_to_spawn; // amount of monsters we want to spawn in this wave. qbool spawn_boss; // spawn boss in this wave. } bloodfest_t; extern bloodfest_t g_bloodfest; // reset bloodfest runtime variables to default values. void bloodfest_reset(void); void monster_death_use(void); void check_monsters_respawn(void); void walkmonster_start(char *model); void flymonster_start(char *model); void swimmonster_start(char *model); // } // misc.c void LaunchLaser(vec3_t org, vec3_t vec); // identify alternative .ent files by format #.ent #define K_ENTITYFILE_SEPARATOR '#' // bots qbool bots_enabled(void); // files fileHandle_t std_fropen(const char *fmt, ...) PRINTF_FUNC(1); fileHandle_t std_fwopen(const char *fmt, ...) PRINTF_FUNC(1); int std_fgetc(fileHandle_t handle); char* std_fgets(fileHandle_t handle, char *buf, int limit); void std_fclose(fileHandle_t handle); void std_fprintf(fileHandle_t handle, const char *fmt, ...) PRINTF_FUNC(2); // teamplay void TeamplayEventItemTaken(gedict_t *client, gedict_t *item); void TeamplayDeathEvent(gedict_t *client); void TeamplayMessage(void); qbool TeamplayMessageByName(gedict_t *client, const char *message); void TeamplayGameTick(void); void LocationInitialise(void); qbool SameTeam(gedict_t *p1, gedict_t *p2); #ifndef BOT_SUPPORT #define bots_enabled() (false) #else #include "fb_globals.h" #endif #define LGCMODE_VARIABLE "k_lgcmode" qbool lgc_enabled(void); void lgc_register_fire_stop(gedict_t *player); void lgc_register_kill(gedict_t *player); void lgc_register_miss(vec3_t start, gedict_t *player); void lgc_register_hit(vec3_t start, gedict_t *player, gedict_t *victim); #define TOT_MODE_VARIABLE "k_tot_mode" qbool tot_mode_enabled(void); // private games qbool is_private_game(void); qbool is_logged_in(gedict_t *p); void private_game_toggle(qbool enable); void private_game_vote(void); void vote_check_privategame(void); qbool private_game_voteable(void); qbool private_game_by_default(void); // set when match is starting, otherwise a normal spawn extern qbool initial_match_spawns; // highest number of players in all teams, used to allow (re)connect during match extern int maxPlayerCount; #define AUTOTRACK_POWERUPS_PREDICT_TIME 2 qbool AllowMonster(gedict_t *e); QW-Group-ktx-d05d6ca/include/g_public.h000066400000000000000000000125341475442401000200150ustar00rootroot00000000000000/* * QW262 * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ #ifndef __G_PUBLIC_H__ #define __G_PUBLIC_H__ // Copyright (C) 1999-2000 Id Software, Inc. // // g_public.h -- game module information visible to server #define GAME_API_VERSION 16 //=============================================================== // !!! new traps comes to end of list !!! // // system traps provided by the main engine // typedef enum { //============== general Quake services ================== G_GETAPIVERSION, // ( void); G_DPRINT, // ( const char *string ); // print message on the local console G_ERROR, // ( const char *string ); // abort the game G_GetEntityToken, G_SPAWN_ENT, G_REMOVE_ENT, G_PRECACHE_SOUND, G_PRECACHE_MODEL, G_LIGHTSTYLE, G_SETORIGIN, G_SETSIZE, G_SETMODEL, G_BPRINT, G_SPRINT, G_CENTERPRINT, G_AMBIENTSOUND, G_SOUND, G_TRACELINE, G_CHECKCLIENT, G_STUFFCMD, G_LOCALCMD, G_CVAR, G_CVAR_SET, G_FINDRADIUS, G_WALKMOVE, G_DROPTOFLOOR, G_CHECKBOTTOM, G_POINTCONTENTS, G_NEXTENT, G_AIM, G_MAKESTATIC, G_SETSPAWNPARAMS, G_CHANGELEVEL, G_LOGFRAG, G_GETINFOKEY, G_MULTICAST, G_DISABLEUPDATES, G_WRITEBYTE, G_WRITECHAR, G_WRITESHORT, G_WRITELONG, G_WRITEANGLE, G_WRITECOORD, G_WRITESTRING, G_WRITEENTITY, G_FLUSHSIGNON, g_memset, g_memcpy, g_strncpy, g_sin, g_cos, g_atan2, g_sqrt, g_floor, g_ceil, g_acos, G_CMD_ARGC, G_CMD_ARGV, G_TraceCapsule, G_FSOpenFile, G_FSCloseFile, G_FSReadFile, G_FSWriteFile, G_FSSeekFile, G_FSTellFile, G_FSGetFileList, G_CVAR_SET_FLOAT, G_CVAR_STRING, G_Map_Extension, G_strcmp, G_strncmp, G_stricmp, G_strnicmp, G_Find, G_executecmd, G_conprint, G_readcmd, G_redirectcmd, G_Add_Bot, G_Remove_Bot, G_SetBotUserInfo, G_SetBotCMD, G_QVMstrftime, G_CMD_ARGS, G_CMD_TOKENIZE, g_strlcpy, g_strlcat, G_MAKEVECTORS, G_NEXTCLIENT, G_PRECACHE_VWEP_MODEL, G_SETPAUSE, G_SETUSERINFO, G_MOVETOGOAL, G_VISIBLETO, } gameImport_t; // !!! new things comes to end of list !!! // // functions exported by the game subsystem // typedef enum { GAME_INIT, // ( int levelTime, int randomSeed, int restart ); // init and shutdown will be called every single level // The game should call G_GET_ENTITY_TOKEN to parse through all the // entity configuration text and spawn gentities. GAME_LOADENTS, GAME_SHUTDOWN, // (void); GAME_CLIENT_CONNECT, // ( int clientNum ,int isSpectator); // ( int clientNum, qbool firstTime, qbool isBot ); // return NULL if the client is allowed to connect, otherwise return // a text string with the reason for denial GAME_PUT_CLIENT_IN_SERVER, //GAME_CLIENT_BEGIN, // ( int clientNum ,int isSpectator); GAME_CLIENT_USERINFO_CHANGED, // ( int clientNum,int isSpectator ); GAME_CLIENT_DISCONNECT, // ( int clientNum,int isSpectator ); GAME_CLIENT_COMMAND, // ( int clientNum,int isSpectator ); GAME_CLIENT_PRETHINK, GAME_CLIENT_THINK, // ( int clientNum,int isSpectator ); GAME_CLIENT_POSTTHINK, GAME_START_FRAME, // ( int levelTime ); GAME_SETCHANGEPARMS, // self GAME_SETNEWPARMS, GAME_CONSOLE_COMMAND, // ( void ); GAME_EDICT_TOUCH, //(self,other) GAME_EDICT_THINK, //(self,other=world,time) GAME_EDICT_BLOCKED, //(self,other) // ConsoleCommand will be called when a command has been issued // that is not recognized as a builtin function. // The game can issue trap_argc() / trap_argv() commands to get the command // and parameters. Return false if the game doesn't recognize it as a command. GAME_CLIENT_SAY, // ( int isTeamSay ); GAME_PAUSED_TIC, // ( int duration_msec ); // duration is in msecs GAME_CLEAR_EDICT, // (self) GAME_EDICT_CSQCSEND = 200, //entrypoint, called when using SendEntity } gameExport_t; 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_ENTITY, // index on disk, pointer in memory // F_ITEM, // index on disk, pointer in memory // F_CLIENT, // index on disk, pointer in memory F_IGNORE } fieldtype_t; typedef struct { string_t name; int ofs; fieldtype_t type; // int flags; } field_t; typedef struct { edict_t *ents; int sizeofent; globalvars_t *global; field_t *fields; int APIversion; int maxentities; } gameData_t; typedef int fileHandle_t; typedef enum { FS_READ_BIN, FS_READ_TXT, FS_WRITE_BIN, FS_WRITE_TXT, FS_APPEND_BIN, FS_APPEND_TXT } fsMode_t; typedef enum { FS_SEEK_CUR, FS_SEEK_END, FS_SEEK_SET } fsOrigin_t; #endif /* !__G_PUBLIC_H__ */ QW-Group-ktx-d05d6ca/include/g_syscalls.h000066400000000000000000000200011475442401000203600ustar00rootroot00000000000000/* * QWProgs-QVM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ intptr_t trap_GetApiVersion(void); qbool trap_GetEntityToken(char *token, intptr_t size); void trap_DPrintf(const char *fmt); void trap_conprint(const char *fmt); #define BPRINT_IGNOREINDEMO (1<<0) // broad cast print will be not put in demo #define BPRINT_IGNORECLIENTS (1<<1) // broad cast print will not be seen by clients, but may be seen in demo #define BPRINT_QTVONLY (1<<2) // if broad cast print goes to demo, then it will be only qtv sream, but not file #define BPRINT_IGNORECONSOLE (1<<3) // broad cast print will not be put in server console void trap_BPrint(intptr_t level, const char *fmt, intptr_t flags); // trap_SPrint() flags #define SPRINT_IGNOREINDEMO ( 1<<0) // do not put such message in mvd demo void trap_SPrint(intptr_t edn, intptr_t level, const char *fmt, intptr_t flags); void trap_CenterPrint(intptr_t edn, const char *fmt); void trap_Error(const char *fmt); intptr_t trap_spawn(void); void trap_remove(intptr_t edn); void trap_precache_sound(char *name); void trap_precache_model(char *name); intptr_t trap_precache_vwep_model(char *name); void trap_setorigin(intptr_t edn, float origin_x, float origin_y, float origin_z); void trap_setsize(intptr_t edn, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); void trap_setmodel(intptr_t edn, char *model); void trap_ambientsound(float pos_x, float pos_y, float pos_z, char *samp, float vol, float atten); void trap_sound(intptr_t edn, intptr_t channel, char *samp, float vol, float att); intptr_t trap_checkclient(void); void trap_traceline(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, intptr_t nomonst, intptr_t edn); #define STUFFCMD_IGNOREINDEMO ( 1<<0) // do not put in mvd demo #define STUFFCMD_DEMOONLY ( 1<<1) // put in mvd demo only void trap_stuffcmd(intptr_t edn, const char *fmt, intptr_t flags); void trap_localcmd(const char *fmt); void trap_executecmd(void); void trap_readcmd(const char *str, char *buf, intptr_t size); void trap_redirectcmd(gedict_t *ent, char *str); float trap_cvar(const char *var); void trap_cvar_string(const char *var, char *buffer, intptr_t bufsize); void trap_cvar_set(const char *var, const char *val); void trap_cvar_set_float(const char *var, float val); intptr_t trap_droptofloor(intptr_t edn); intptr_t trap_walkmove(intptr_t edn, float yaw, float dist); void trap_lightstyle(intptr_t style, char *val); intptr_t trap_checkbottom(intptr_t edn); intptr_t trap_pointcontents(float origin_x, float origin_y, float origin_z); intptr_t trap_nextent(intptr_t n); gedict_t* trap_nextclient(gedict_t *ent); //intptr_t trap_find( intptr_t n,intptr_t fofs, char*str ); gedict_t* trap_find(gedict_t *ent, intptr_t fofs, char *str); gedict_t* trap_findradius(gedict_t *ent, float *org, float rad); void trap_makestatic(intptr_t edn); void trap_setspawnparam(intptr_t edn); void trap_changelevel(const char *name, const char *entityname); intptr_t trap_multicast(float origin_x, float origin_y, float origin_z, intptr_t to); void trap_logfrag(intptr_t killer, intptr_t killee); void trap_infokey(intptr_t edn, char *key, char *valbuff, intptr_t sizebuff); void trap_WriteByte(intptr_t to, intptr_t data); void trap_WriteChar(intptr_t to, intptr_t data); void trap_WriteShort(intptr_t to, intptr_t data); void trap_WriteLong(intptr_t to, intptr_t data); void trap_WriteAngle(intptr_t to, float data); void trap_WriteCoord(intptr_t to, float data); void trap_WriteString(intptr_t to, char *data); void trap_WriteEntity(intptr_t to, intptr_t edn); void trap_FlushSignon(void); void trap_disableupdates(intptr_t edn, float time); intptr_t trap_CmdArgc(void); void trap_CmdArgv(intptr_t arg, char *valbuff, intptr_t sizebuff); void trap_CmdArgs(char *valbuff, intptr_t sizebuff); void trap_CmdTokenize(char *str); void trap_TraceCapsule(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, intptr_t nomonst, intptr_t edn, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); intptr_t trap_FS_OpenFile(char *name, fileHandle_t *handle, fsMode_t fmode); void trap_FS_CloseFile(fileHandle_t handle); intptr_t trap_FS_ReadFile(char *dest, intptr_t quantity, fileHandle_t handle); intptr_t trap_FS_WriteFile(char *src, intptr_t quantity, fileHandle_t handle); intptr_t trap_FS_SeekFile(fileHandle_t handle, intptr_t offset, intptr_t type); intptr_t trap_FS_TellFile(fileHandle_t handle); #define FILELIST_GAMEDIR_ONLY (1<<0) // if set then search in gamedir only #define FILELIST_WITH_PATH (1<<1) // include path to file #define FILELIST_WITH_EXT (1<<2) // include extension of file intptr_t trap_FS_GetFileList(const char *path, const char *extension, char *listbuf, intptr_t bufsize, intptr_t flags); intptr_t trap_Map_Extension(const char *ext_name, intptr_t mapto); /* return: 0 success maping -1 not found -2 cannot map */ intptr_t trap_AddBot(const char *name, intptr_t bottomcolor, intptr_t topcolor, const char *skin); intptr_t trap_RemoveBot(intptr_t edn); intptr_t trap_SetBotUserInfo(intptr_t edn, const char *varname, const char *value, intptr_t flags); intptr_t trap_SetBotCMD(intptr_t edn, intptr_t msec, float angles_x, float angles_y, float angles_z, intptr_t forwardmove, intptr_t sidemove, intptr_t upmove, intptr_t buttons, intptr_t impulse); void trap_setpause(intptr_t pause); intptr_t QVMstrftime(char *valbuff, intptr_t sizebuff, const char *fmt, intptr_t offset); void trap_makevectors(float *v); #define SETUSERINFO_STAR (1<<0) // allow set star keys intptr_t trap_SetUserInfo(intptr_t edn, const char *varname, const char *value, intptr_t flags); intptr_t trap_movetogoal(float dist); void trap_VisibleTo(intptr_t viewer, intptr_t first, intptr_t len, byte *visible); // Raw calls, use _i and _f helpers instead. void trap_SetExtField(gedict_t *ed, const char *fieldname, intptr_t val); int trap_GetExtField(gedict_t *ed, const char *fieldname); intptr_t trap_MapExtFieldPtr(const char *fieldname); intptr_t trap_SetExtFieldPtr(gedict_t *ed, intptr_t fieldref, intptr_t *data, intptr_t size); intptr_t trap_GetExtFieldPtr(gedict_t *ed, intptr_t fieldref, intptr_t *data, intptr_t size); intptr_t trap_SetSendNeeded(intptr_t subject, intptr_t flags, intptr_t to); // Checks for server support before call void ExtFieldSetAlpha(gedict_t *ed, float alpha); float ExtFieldGetAlpha(gedict_t *ed); void ExtFieldSetColorMod(gedict_t *ed, float r, float g, float b); void ExtFieldSetSendEntity(gedict_t *ed, func_t callback); void ExtFieldSetPvsFlags(gedict_t *ed, float pvsflags); void SetSendNeeded(gedict_t *ed, int sendflags, int unicast); void trap_changelevelHub(const char *name, const char *entityname, const char *startspot); int trap_URI_Query(const char *uri, int vmentry/*GAME_...*/, void *cbcontext, const char *mimetype, const char *data, size_t datasize); int trap_particleeffectnum(const char *effectname); int trap_trailparticles(int effecttype, int entnum, float start_x, float start_y, float start_z, float end_x, float end_y, float end_z); int trap_pointparticles(int effecttype, float org_x, float org_y, float org_z, float vel_x, float vel_y, float vel_z, int count); int trap_clientstat(int statidx, int stattype, int fieldoffset); int trap_pointerstat(int statidx, int stattype, void *offset); QW-Group-ktx-d05d6ca/include/mathlib.h000066400000000000000000000066431475442401000176550ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ // mathlib.h //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 typedef struct mplane_s { vec3_t normal; float dist; byte type; // for texture axis selection and fast side tests byte signbits; // signx + signy<<1 + signz<<1 byte pad[2]; } mplane_t; extern vec3_t vec3_origin; extern int nanmask; #define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) #define Q_rint(x) ((x) > 0 ? (int)((x) + 0.5) : (int)((x) - 0.5)) #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 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); 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); int VectorCompare(vec3_t v1, vec3_t v2); int VectorCompareF(vec3_t v1, float x, float y, float z); vec_t VectorLength(vec3_t v); float VectorDistance(vec3_t v1, vec3_t v2); void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross); float VectorNormalize(vec3_t v); // returns vector length 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 FloorDivMod(double numer, double denom, int *quotient, int *rem); fixed16_t Invert24To16(fixed16_t val); fixed16_t Mul16_30(fixed16_t multiplier, fixed16_t multiplicand); int GreatestCommonDivisor(int i1, int i2); void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct mplane_s *plane); float anglemod(float a); void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); #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))) QW-Group-ktx-d05d6ca/include/player.h000066400000000000000000000075771475442401000175400ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ void player_stand1(void); void player_run(void); void player_shot1(void); void player_shot2(void); void player_shot3(void); void player_shot4(void); void player_shot5(void); void player_shot6(void); void player_axe1(void); void player_axe2(void); void player_axe3(void); void player_axe4(void); void player_axeb1(void); void player_axeb2(void); void player_axeb3(void); void player_axeb4(void); void player_axec1(void); void player_axec2(void); void player_axec3(void); void player_axec4(void); void player_axed1(void); void player_axed2(void); void player_axed3(void); void player_axed4(void); void player_chain1(void); void player_chain2(void); void player_chain3(void); void player_chain4(void); void player_chain5(void); void player_nail1(void); void player_nail2(void); void player_light1(void); void player_light2(void); void player_rocket1(void); void player_rocket2(void); void player_rocket3(void); void player_rocket4(void); void player_rocket5(void); void player_rocket6(void); void player_pain1(void); void player_pain2(void); void player_pain3(void); void player_pain4(void); void player_pain5(void); void player_pain6(void); void player_axpain1(void); void player_axpain2(void); void player_axpain3(void); void player_axpain4(void); void player_axpain5(void); void player_axpain6(void); void player_pain(struct gedict_s *attacker, float take); void player_diea1(void); void player_diea2(void); void player_diea3(void); void player_diea4(void); void player_diea5(void); void player_diea6(void); void player_diea7(void); void player_diea8(void); void player_diea9(void); void player_diea10(void); void player_diea11(void); void player_dieb1(void); void player_dieb2(void); void player_dieb3(void); void player_dieb4(void); void player_dieb5(void); void player_dieb6(void); void player_dieb7(void); void player_dieb8(void); void player_dieb9(void); void player_diec1(void); void player_diec2(void); void player_diec3(void); void player_diec4(void); void player_diec5(void); void player_diec6(void); void player_diec7(void); void player_diec8(void); void player_diec9(void); void player_diec10(void); void player_diec11(void); void player_diec12(void); void player_diec13(void); void player_diec14(void); void player_diec15(void); void player_died1(void); void player_died2(void); void player_died3(void); void player_died4(void); void player_died5(void); void player_died6(void); void player_died7(void); void player_died8(void); void player_died9(void); void player_diee1(void); void player_diee2(void); void player_diee3(void); void player_diee4(void); void player_diee5(void); void player_diee6(void); void player_diee7(void); void player_diee8(void); void player_diee9(void); void player_die_ax1(void); void player_die_ax2(void); void player_die_ax3(void); void player_die_ax4(void); void player_die_ax5(void); void player_die_ax6(void); void player_die_ax7(void); void player_die_ax8(void); void player_die_ax9(void); void PlayerDead(void); void PlayerDie(void); gedict_t* ThrowGib(char *gibname, float dm); void ThrowHead(char *gibname, float dm); void muzzleflash(void); QW-Group-ktx-d05d6ca/include/progdefs.h000066400000000000000000000111761475442401000200430ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* file generated by qcc, do not modify */ // FIXME: temporary till we move fields like netname/model/etc from gedict_t back to entvars_t. #define PR_ALWAYS_REFS 1 typedef struct { int pad[28]; int self; int other; int world; float time; float frametime; int newmis; float force_retouch; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t mapname_; // Unused by mod, placeholder so server is happy. #else string_t mapname; // Unused by mod, placeholder so server is happy. #endif float serverflags; float total_secrets; float total_monsters; float found_secrets; float killed_monsters; float parm1; float parm2; float parm3; float parm4; float parm5; float parm6; float parm7; float parm8; float parm9; float parm10; float parm11; float parm12; float parm13; float parm14; float parm15; float parm16; vec3_t v_forward; vec3_t v_up; vec3_t v_right; float trace_allsolid; float trace_startsolid; float trace_fraction; vec3_t trace_endpos; vec3_t trace_plane_normal; float trace_plane_dist; int trace_ent; float trace_inopen; float trace_inwater; int msg_entity; funcref_t main; funcref_t StartFrame; funcref_t PlayerPreThink; funcref_t PlayerPostThink; funcref_t ClientKill; funcref_t ClientConnect; funcref_t PutClientInServer; funcref_t ClientDisconnect; funcref_t SetNewParms; funcref_t SetChangeParms; } globalvars_t; typedef struct { float modelindex; vec3_t absmin; vec3_t absmax; float ltime; float lastruntime; float movetype; float solid; vec3_t origin; vec3_t oldorigin; vec3_t velocity; vec3_t angles; vec3_t avelocity; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t classname_; stringref_t model_; #else string_t classname; string_t model; #endif float frame; float skin; float effects; vec3_t mins; vec3_t maxs; vec3_t size; #if defined(idx64) || defined(PR_ALWAYS_REFS) funcref_t touch_; funcref_t use_; funcref_t think_; funcref_t blocked_; #else func_t touch; func_t use; func_t think; func_t blocked; #endif float nextthink; int groundentity; float health; float frags; float weapon; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t weaponmodel_; #else string_t weaponmodel; #endif float weaponframe; float currentammo; float ammo_shells; float ammo_nails; float ammo_rockets; float ammo_cells; float items; float takedamage; int chain; float deadflag; vec3_t view_ofs; float button0; float button1; float button2; float impulse; float fixangle; vec3_t v_angle; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t netname_; #else string_t netname; #endif int enemy; float flags; float colormap; float team; float max_health; float teleport_time; float armortype; float armorvalue; float waterlevel; float watertype; float ideal_yaw; float yaw_speed; int aiment; int goalentity; float spawnflags; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t target_; stringref_t targetname_; #else string_t target; string_t targetname; #endif float dmg_take; float dmg_save; int dmg_inflictor; int owner; vec3_t movedir; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t message_; #else string_t message; #endif float sounds; #if defined(idx64) || defined(PR_ALWAYS_REFS) stringref_t noise_; stringref_t noise1_; stringref_t noise2_; stringref_t noise3_; #else string_t noise; string_t noise1; string_t noise2; string_t noise3; #endif #if 0 // FIXME: PR_ALWAYS_REFS: this should be returned once KTX start using ent->s.v.fields again. #ifdef idx64 //fields that used to be pointers are now byte offsets to these pointers... string_t classname; string_t model; func_t touch; func_t use; func_t think; func_t blocked; string_t weaponmodel; string_t netname; string_t target; string_t targetname; string_t message; string_t noise; string_t noise1; string_t noise2; string_t noise3; #endif #endif } entvars_t; #define PROGHEADER_CRC 54730 QW-Group-ktx-d05d6ca/include/progs.h000066400000000000000000001304151475442401000173620ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "progdefs.h" #define MAX_ROUTE_NODES 20 // max race checkpoints per race (including start and finish checkpoints) #define MAX_ROUTES 20 // max race route per map #define LGCMODE_MAX_DISTANCE 700 #define LGCMODE_DISTANCE_BUCKETS 20 #define LGCMODE_BUCKET_DISTANCE (LGCMODE_MAX_DISTANCE / LGCMODE_DISTANCE_BUCKETS) typedef struct shared_edict_s { entvars_t v; // C exported fields from progs // other fields from progs come immediately after } edict_t; struct gedict_s; typedef void (*th_die_funcref_t)(void); typedef void (*th_pain_funcref_t)(struct gedict_s*, float); // { SP typedef void (*th_sp_funcref_t)(void); // } typedef enum { ctNone = 0, ctPlayer, ctSpec } clientType_t; typedef enum { wpNONE = 0, wpAXE, wpSG, wpSSG, wpNG, wpSNG, wpGL, wpRL, wpLG, wpMAX } weaponName_t; typedef enum { lgcUndershaft = 0, lgcNormal = 1, lgcOvershaft = 2 } lgc_state_t; typedef struct wpType_s { int hits; // hits with this weapon, for SG and SSG this is count of bullets int rhits; // real hits for this weapon (direct + splash), used for RL and GL only int vhits; // virtual hits for this weapon (direct + splash, do not care about pent and such), used for RL and GL only int attacks; // all attacks with this weapon, for SG and SSG this is count of bullets int kills; // kills with this weapon int deaths; // deaths from this weapon int tkills; // team kills with this weapon int suicides; // suicides with this weapon int ekills; // killed enemies which contain this weapon in inventory int drops; // number of packs dropped which contain this weapon int tooks; // took this weapon and doesn't have this weapon before took (weapon from packs counted too) int stooks; // spawned items taken (backpacks not included), and didn't have weapon beforehand int ttooks; // total taken, even if you already had this weapon int sttooks; // spawned items taken (backpacks not included), even if you already had this weapon int edamage; // damage to enemies int tdamage; // damage to team-mates int enemyjustkilled; int lastfraghits; // count of hits for lg per frag int lastfragattacks; // count of attacks for lg per frag int lastfragdisplayhits; // stores count of last frag hits int lastfragdisplayattacks; // stores count of last frag attacks float time; // total time u have some weapon } wpType_t; typedef enum { itNONE = 0, itHEALTH_15, itHEALTH_25, itHEALTH_100, itGA, itYA, itRA, itQUAD, itPENT, itRING, itMAX } itemName_t; typedef struct itType_s { int tooks; // taken count float time; // total time u have some item } itType_t; // store player statistic here, like taken armors etc... typedef struct player_stats_s { wpType_t wpn[wpMAX]; itType_t itm[itMAX]; float dmg_t; // damage taken float dmg_g; // damage given float dmg_g_rl; // virtual given rl damage float dmg_team; // damage to team float dmg_self; // damage to own player float dmg_eweapon; // damage to enemy weapons float dmg_tweapon; // damage to team weapons // { k_dmgfrags float dmg_frags; // frags awarded from damage (CA) // } int ot_a; // overtime armor value // float ot_at; // overtime armor type int ot_items; // overtime items int ot_h; // overtime health int spawn_frags; int handicap; int transferred_RLpacks; int transferred_LGpacks; // ctf stats int ctf_points; // use frags - this to calculate efficiency for ctf int caps; // flag captures int f_defends; // flag defends int c_defends; // carrier defends int c_frags; // frags on enemy carriers int pickups; // flag pickups int returns; // flag returns float res_time; // time with resistance rune float str_time; // time with strength rune float hst_time; // time with haste rune float rgn_time; // time with regen rune // midair stats int mid_stomps; // stomps done on other players int mid_bronze; // bronze midairs int mid_silver; // silver midairs int mid_gold; // gold midairs int mid_platinum; // platinum midairs int mid_total; // total of midairs int mid_bonus; // total of bonuses float mid_totalheight; // maximum height of midairs float mid_maxheight; // maximum height of midairs float mid_avgheight; // average height of midairs // spree stats int spree_current; // number of frags since our last death int spree_current_q; // number of frags in current quad run int spree_max; // largest spree throughout game int spree_max_q; // largest quad spree throughout game // time stats float control_time; // time spent in control // rocket arena int wins; //number of wins they have int loses; //number of loses they have // velocity stats float velocity_max; // maximum velocity float velocity_sum; // summary velocity from all frames int vel_frames; // number of frames // instagib stats int i_height; // Cumulated height of airgibs int i_maxheight; int i_cggibs; // Kills with coil gun int i_axegibs; // Kills with axe int i_stompgibs; // Kills with stomp int i_multigibs; // int i_airgibs; // Number of airgibs int i_maxmultigibs; // int i_rings; // // lgc stats int lgc_undershaft; // cells fired before hitting target int lgc_overshaft; // cells fired after killing target } player_stats_t; typedef enum { etNone = 0, etCaptain, etCoach, etAdmin } electType_t; // store player votes here typedef struct vote_s { int brk; int elect; int map; int pickup; int rpickup; int teamoverlay; int nospecs; int coop; int hooksmooth; int hookfast; int hookclassic; int hookcrhook; int antilag; int privategame; //int kick_unauthed; int swapall; electType_t elect_type; // election type float elect_block_till; // block election for this time } vote_t; // demo marker typedef struct demo_marker_s { float time; char markername[64]; } demo_marker_t; // cmd flood protection #define MAX_FP_CMDS (10) typedef struct fp_cmd_s { float locked; float cmd_time[MAX_FP_CMDS]; int last_cmd; int warnings; } fp_cmd_t; // store wregs here #define MAX_WREGS (256) #define MAX_WREG_IMP (9) typedef struct wreg_s { qbool init; int attack; int impulse[MAX_WREG_IMP]; } wreg_t; // { #define MAX_PLRFRMS (77*15) /* 77 frames for each of 15 seconds */ typedef struct { float time; // float modelindex; vec3_t origin; vec3_t angles; float frame; float effects; // vec3_t v_angle; float colormap; } plrfrm_t; // } // player position #define MAX_POSITIONS (5) typedef struct pos_s { vec3_t velocity; vec3_t origin; vec3_t v_angle; } pos_t; typedef enum { atNone = 0, atBest, atPow, atKTPRO } autoTrackType_t; // { rocket arena typedef enum { raNone = 0, raWinner, raLoser, raQue } raPlayerType_t; // } typedef struct teamplay_memory_s { unsigned long item; // classname of saved item vec3_t location; // location of item float time; // time details were saved int flags; // flags about the particular item } teamplay_memory_t; typedef struct teamplay_preferences_s { char need_weapons[10]; // weapons (ezQuake: ) int need_health; // threshold for announcing player needs health } teamplay_preferences_t; typedef struct teamplay_s { teamplay_memory_t took; teamplay_memory_t point; unsigned long enemy_items; // powerup flags, updated when enemy powerup (or eyes) visible float enemy_itemtime; // time when enemy_items was last set vec3_t enemy_location; // location of player when enemy_items was last set int enemy_count; // number of enemies in pvs (also eyes) int teammate_count; // number of teammates in pvs // Last location (FIXME: last_death_location) float death_time; vec3_t death_location; int death_items; int death_weapon; // Client's preferences teamplay_preferences_t preferences; } teamplay_t; #define NEED_WEAPONS_DEFAULT "87" #define it_quad (1 << 0) #define it_pent (1 << 1) #define it_ring (1 << 2) #define it_suit (1 << 3) #define it_ra (1 << 4) #define it_ya (1 << 5) #define it_ga (1 << 6) #define it_mh (1 << 7) #define it_health (1 << 8) #define it_lg (1 << 9) #define it_rl (1 << 10) #define it_gl (1 << 11) #define it_sng (1 << 12) #define it_ng (1 << 13) #define it_ssg (1 << 14) #define it_pack (1 << 15) #define it_cells (1 << 16) #define it_rockets (1 << 17) #define it_nails (1 << 18) #define it_shells (1 << 19) #define it_flag (1 << 20) #define it_teammate (1 << 21) #define it_enemy (1 << 22) #define it_eyes (1 << 23) #define it_sentry (1 << 24) #define it_disp (1 << 25) #define it_quaded (1 << 26) #define it_pented (1 << 27) #define it_rune1 (1 << 28) #define it_rune2 (1 << 29) #define it_rune3 (1 << 30) #define it_rune4 ((unsigned int) (1 << 31)) #define NUM_ITEMFLAGS 32 #define it_runes (it_rune1|it_rune2|it_rune3|it_rune4) #define it_powerups (it_quad|it_pent|it_ring|it_suit) #define it_weapons (it_lg|it_rl|it_gl|it_sng|it_ssg) #define it_armor (it_ra|it_ya|it_ga) #define it_ammo (it_cells|it_rockets|it_nails|it_shells) #define it_players (it_teammate|it_enemy|it_eyes) #define MAX_SPAWN_WEIGHTS (64) #define HM_MAX_ROUNDS 64 #ifdef BOT_SUPPORT // frogbots typedef void (*fb_void_funcref_t)(void); typedef qbool (*fb_bool_funcref_t)(void); typedef float (*fb_desire_funcref_t)(struct gedict_s* self, struct gedict_s* other); typedef qbool (*fb_touch_funcref_t)(struct gedict_s* item, struct gedict_s* player); typedef void (*fb_taken_funcref_t)(struct gedict_s* item, struct gedict_s* player); typedef void (*fb_entity_funcref_t)(struct gedict_s* item); #ifndef NUMBER_MARKERS #define NUMBER_MARKERS 300 #endif #ifndef NUMBER_GOALS #define NUMBER_GOALS 24 #endif #ifndef NUMBER_ZONES #define NUMBER_ZONES 24 #endif #ifndef NUMBER_PATHS #define NUMBER_PATHS 8 #endif #ifndef NUMBER_SUBZONES #define NUMBER_SUBZONES 32 #endif typedef struct fb_runaway_route_s { struct gedict_s* next_marker; struct gedict_s* prev_marker; float time; float score; } fb_runaway_route_t; typedef struct fb_path_s { struct gedict_s* next_marker; // next marker in the graph float time; // time to travel if walking (0 if teleporting) float rj_time; // time to travel if using rocket jump int flags; // hints on how to travel to next marker short angle_hint; // When travelling to marker, offset to standard angle (+ = anti-clockwise) float rj_pitch; // ideal pitch angle when rocket jumping float rj_yaw; // ideal yaw angle when rocket jumping (0 for no change) int rj_delay; // number of frames to delay between jumping and firing rocket } fb_path_t; typedef struct fb_goal_s { struct gedict_s* next_marker; float time; struct gedict_s* next_marker_rj; float rj_time; } fb_goal_t; typedef struct fb_subzone_s { struct gedict_s* next_marker; float time; struct gedict_s* next_marker_rj; float rj_time; } fb_subzone_t; typedef struct fb_zone_s { // Standard routing struct gedict_s* marker; float time; struct gedict_s* next; struct gedict_s* next_zone; // Rocket jumping struct gedict_s* marker_rj; float rj_time; struct gedict_s* next_rj; float reverse_time; struct gedict_s* reverse_marker; struct gedict_s* reverse_next; float from_time; struct gedict_s* sight_from; float sight_from_time; struct gedict_s* higher_sight_from; float higher_sight_from_time; // FIXME: Never used? Was used in runaway code, but in peculiar fashion... int task; } fb_zone_t; typedef struct fb_botaim_s { float scale; // difference between current viewangle and desired is scaled by this float minimum; // minimum & maximum final variation float maximum; float multiplier; // alter } fb_botaim_t; typedef struct fb_botskill_s { int skill_level; // 0-20 as standard float dodge_amount; // left/right strafing float lookahead_time; // how far ahead the bot can think (regarding items respawning etc) 5-30s in original float prediction_error; // affects goal travellling error (lower values => turn up earlier) 1-0 in original. randomised. float look_anywhere; // 0...1 determines when the bot will look at the enemy's location float accuracy; float lg_preference; // 0...1 previously game-wide, look to use LG when possible float rl_preference; // 0...1 previously game-wide, look to use RL when possible float visibility; // cos(fov / 2) ... fov 90 = cos(45) = 0.7071067, fov 120 = cos(60) = 0.5 qbool attack_respawns; // fire at respawns if enemy just died float min_volatility; float max_volatility; float reduce_volatility; float ownspeed_volatility_threshold; float ownspeed_volatility; float enemyspeed_volatility_threshold; float enemyspeed_volatility; float enemydirection_volatility; float pain_volatility; // when bot has taken damage in last second float opponent_midair_volatility; // when opponent is in midair float self_midair_volatility; // when bot is in midair float initial_volatility; // when bot sees player for first time float current_volatility; float awareness_delay; float spawn_move_delay; float movement_estimate_error; // % of time the bot gets wrong when predicting player location fb_botaim_t aim_params[2]; float movement; float combat_jump_chance; float missile_dodge_time; // minimum time in seconds before bot dodges missile qbool customised; // if set, customised file qbool wiggle_run_dmm4; // if set, wiggle run on dmm4 (and up) int wiggle_run_limit; // number of frames until bot will switch strafe direction float wiggle_toggle; // % chance of switching direction when being hit } fb_botskill_t; // FIXME: Need to break this up into marker fields, client fields and entity fields // Currently using way too much memory as a lot of these are invalid for particular entity types typedef struct fb_entvars_s { fb_zone_t zones[NUMBER_ZONES]; // directions to zones fb_subzone_t subzones[NUMBER_SUBZONES]; // links to subzones (subzone is unique marker inside a zone) fb_goal_t goals[NUMBER_GOALS]; // links to goals fb_runaway_route_t runaway[NUMBER_PATHS]; // routes when running away fb_path_t paths[NUMBER_PATHS]; // direct links from this marker to next int path_state; // flags for next path, copied from routing definition int angle_hint; // for curl-jumping, angle offset (right-handed, +ve = to left, -ve = to right) int index; // marker number float wait; float fl_ontrain; // FIXME: never set (used for frogbot train movement) struct gedict_s* touchPlayer; // last player to touch this object (see below) float touchPlayerTime; // how long the current item will be considered touched by touchPlayer int teamflag; // This is used to add a teamflag to a goal entity, so it bots on same team ignore item float oldwaterlevel; // used to detect FL_WATERJUMP waterjump... may not be required? server will set... float oldwatertype; // FIXME: never read. server will set, this is in MOVETYPE_STEP code... // these determine the strength of each player float total_armor; float total_damage; float firepower; float enemy_time; // Time before bot re-evaluates who is its primary enemy float enemy_dist; // Distance to primary enemy int oldsolid; // need to keep track of this for hazard calculations // these determine the desire for items for each player // (not just for bots ... bot's desire can take enemy's desire into consideration) fb_desire_funcref_t desire; float desire_armor1; float desire_armor2; float desire_armorInv; float desire_health0; float desire_mega_health; float desire_supershotgun; float desire_nailgun; float desire_supernailgun; float desire_grenadelauncher; float desire_rocketlauncher; float desire_lightning; float desire_rockets; float desire_cells; float desire_nails; float desire_shells; int state; // WAIT | RUNAWAY | NOTARGET_ENEMY | HELP_TEAMMATE | STATE_BOTTOM (doors) | SHOT_FOR_LUCK int camp_state; // CAMPBOT (FIXME: values set, but read value never acted on) float arrow; qbool wasinwater; float swim_arrow; float arrow_time; // If set in future, bots will avoid this path. Used to detect grenade/rocket at teleport exit. struct gedict_s* arrow_time_setby; // Which player set the most recent arrow time? float arrow_time2; // If set in future, sustain current direction (used to avoid edges or back away from objects) float linked_marker_time; vec3_t oldvelocity; vec3_t obstruction_normal; vec3_t obstruction_direction; // Instead of storing in rel_pos, store direction to obstruction here (for BotWaterMove) qbool avoiding; // Avoiding next path marker, due to incoming rocket or arrow_time in future qbool fl_marker; // true if the current item is considered a marker (used when finding all objects in given radius) //struct gedict_s* next; // Goal evaluation struct gedict_s* best_goal; float best_goal_score; float saved_goal_desire; // the desire for the current goal entity float saved_respawn_time; // seconds until this item respawns (includes current bot's error) float saved_goal_time; float saved_enemy_time_squared; float goal_respawn_time; // the time when this->best_goal2 will respawn (can be in past) float goal_refresh_time; float goal_enemy_repel; float goal_enemy_desire; struct gedict_s* best_goal2; float best_score2; float best_goal_time; struct gedict_s* linked_marker; // the next path in the route to goalentity struct gedict_s* old_linked_marker; // the previous linked marker struct gedict_s* look_object; // the player/marker/entity that the bot is locked onto float frogbot_nextthink; // when to next run periodic movement logic for this player int T; // flags for this individual marker int G_; // assigned goal number for this marker [1-based...] int Z_; // assigned zone for this marker int S_; // subzone for this marker vec3_t fixed_size; // fixed dimensions for this marker. if dimension is 0, default marker size used struct gedict_s* virtual_goal; struct gedict_s* zone_stack_next; struct gedict_s* Z_head; struct gedict_s* Z_next; float path_normal_; fb_bool_funcref_t pickup; // return true if a player would pickup an item as they touch it float weapon_refresh_time; struct gedict_s* prev_touch_marker; // the last touch marker processed struct gedict_s* touch_marker; // the last marker touched, while we were expecting to touch something (ignored during rocket jumps) float touch_distance; // distance from player to touch marker. used when multiple touch events fired in same frame float touch_marker_time; // if < time, run a brute force closest-marker search for marker the player is closest to // These settings dictate the 'skill' of the bot fb_botskill_t skill; // These control the bot's next command qbool firing; // does the bot want to attack this frame? qbool jumping; // does the bot want to jump this frame? int desired_weapon_impulse; // impulse to send the next time the player vec3_t desired_angle; // for 'perfect' aim, this is where the bot wants to be aiming qbool botchose; // next_impulse is valid int next_impulse; // the impulse to send in next command vec3_t virtual_mins; // true bounds of the object (items are markers, so size is boosted) vec3_t virtual_maxs; // true bounds of the object vec3_t dir_move_; // the direction the bot wants to move in float dir_speed; // the magnitude of vector the bot wants to move in int wiggle_run_dir; // when wiggle-running, going left or right qbool wiggle_increasing; // dictates direction, positive or negative vec3_t last_cmd_direction; // the direction the bot did move in (scaled for speed) float ledge_backup_time; // Bot's missile parameters struct gedict_s* missile_dodge; // rocket belonging to look_object int tread_water_count; // number of frames spent treading water vec3_t predict_origin; // origin of enemy, or where the bot thinks they will land qbool predict_shoot; // make a prediction shot this frame? // frogbot logic (move out of entity) qbool allowedMakeNoise; // if false, paths involving picking up an item are penalised // Rocket jumping logic qbool canRocketJump; // will consider rocket jump routes qbool rocketJumping; // in middle of rocket jumping int rocketJumpPathFrameDelay; // value rocketJumpPathFrameDelay int rocketJumpFrameDelay; // active delay between jumping and firing int rocketJumpAngles[2]; // pitch/yaw for rocket jump angle int lavaJumpState; // keep track of submerge/rise/fire sequence // Editor int last_jump_frame; // framecount when player last jumped. used to help setting rj fields qbool bot_evade; // float help_teammate_time; float frogwatermove_time; float up_finished; // Swimming, used to keep pushing up for a period during lavajump int botnumber; // bots[botnumber] float last_cmd_sent; struct gedict_s* prev_look_object; // stores whatever the bot was looking at last frame // Item event functions fb_touch_funcref_t item_touch; // called whenever an item is touched fb_taken_funcref_t item_taken; // called whenever an item is taken fb_taken_funcref_t item_affect; // called whenever an item affects a player (mega-health) fb_entity_funcref_t item_respawned; // called whenever an item respawns fb_entity_funcref_t item_placed; // called when item has been placed in the map // Player event functions fb_entity_funcref_t ammo_used; // Whenever ammo is updated qbool be_quiet; qbool enemy_visible; float last_death; // Last time this player died struct gedict_s* virtual_enemy; vec3_t rocket_endpos; // where an incoming rocket will explode. // Debugging qbool debug; // If set, trace logic qbool debug_path; // Set by "debug botpath" command qbool debug_path_rj; // Set by "debug botpath" command: can rocket jump float debug_path_start; // Set by "debug botpath" command: time debug started struct gedict_s* fixed_goal; // Set by "debug botpath" command: target goal entity to move to vec3_t prev_velocity; // used by "debug botpath" command: keep track of acceleration float last_spec_cp; // last spectator centerprint // Navigation struct gedict_s* door_entity; // actual door entity (we spawn markers in doorway for navigation) // Teamplay float last_mm2_status; // last time this bot reported float last_mm2_spot; // last time this player had powerup reported by enemy float last_mm2_spot_attempt; // last time this bot tried to report enemy powerup qbool waterjumping; // true if the bot should waterjump int dbg_countdown; // bot will be stationary for x frames // Aiming float last_rndaim[2]; float last_rndaim_time; float min_fire_time; // time before bot will fire float min_move_time; // time before bot will move (used off spawn) // Stored on missile to detect where item will explode vec3_t missile_forward; vec3_t missile_right; float missile_spawntime; // last time this player was hurt float last_hurt; float cmd_msec_lost; int cmd_msec_last; } fb_entvars_t; #endif //typedef (void(*)(gedict_t *)) one_edict_func; typedef struct gedict_s { edict_t s; //fields that used to be pointers are now byte offsets to these pointers... string_t classname; string_t model; func_t touch; func_t use; func_t think; func_t blocked; string_t weaponmodel; string_t netname; string_t target; string_t targetname; string_t message; string_t noise; string_t noise1; string_t noise2; string_t noise3; //custom fields int isMissile; // treat some objects as missiles. float vw_index; float maxspeed, gravity; int isBot; float brokenankle; // player can't jump for a while after falling and get damaged char *mdl; char *killtarget; int worldtype; // 0=medieval 1=metal 2=base char *map; //player int walkframe; // // quakeed fields // int style; float speed; int state; int voided; //items.c float healamount, healtype; //ammo int aflag; // // doors, etc // vec3_t movement; vec3_t dest, dest1, dest2; vec3_t pos1, pos2; vec3_t mangle; float t_length, t_width, height; float wait; // time from firing to restarting float delay; // time from activation to firing struct gedict_s *trigger_field; // door's trigger entity struct gedict_s *movetarget; float pausetime; char *noise4; float count; // // misc // float cnt; // misc flag void (*think1)(void); //calcmove vec3_t finaldest; //combat float dmg; float lip; float attack_finished; float pain_finished; float invincible_finished; float invisible_finished; float super_damage_finished; float radsuit_finished; float invincible_time, invincible_sound; float invisible_time, invisible_sound; float super_time, super_sound; float rad_time; float fly_sound; float axhitme; float show_hostile; // set to time+0.2 whenever a client fires a // weapon or takes damage. Used to alert // monsters that otherwise would let the player go float jump_flag; // player jump flag float swim_flag; // player swimming sound flag float air_finished; // when time > air_finished, start drowning float bubble_count; // keeps track of the number of bubbles int deathtype; // keeps track of how the player died float dmgtime; th_die_funcref_t th_die; th_pain_funcref_t th_pain; // below is KTX fields // { SP // // monster ai // th_sp_funcref_t th_stand; th_sp_funcref_t th_walk; th_sp_funcref_t th_run; th_sp_funcref_t th_missile; th_sp_funcref_t th_melee; th_sp_funcref_t th_respawn; // for nightmare mode struct gedict_s *oldenemy; // mad at this player before taking damage float lefty; float search_time; float attack_state; float monster_desired_spawn_time; // in nightmare mode monster desire respawn at this time after last death vec3_t oldangles; // for nightmare skill, need remember monster angles before respawn again // } float cnt2; // NOT_SURE: cnt2 = seconds left? float dead_time; // time at which player last died - used in autorespawn float spawn_time; // time at which player last spawned, // NOTE: ->spawn_time also used in spawn() function, so we know when edict was spawned float connect_time; // time at which player connect float deaths; // number of times player died float efficiency; // stores player efficiency rating float friendly; // number of times player killed teammates float kills; // number of times player killed enemy float suicides; // number of times player killed themselves float ready; // if a player is ready or not char *killer; // name of player who last killed player char *victim; // name of player last killed char *backpack_player_name; // player who dropped the backpack char backpack_team_name[32 /*MAX_TEAM_NAME*/]; // team associated with the backpack struct gedict_s *k_lastspawn; // NOT_SURE: spot at which player last spawned? // { kick mode struct gedict_s *k_playertokick; // player selected to be kicked float k_kicking; // if player is in kick mode // } float k_1spawn; // NOT_SURE: used in kteams respawn code... float k_accepted; // NOT_SURE: int k_added; // NOT_SURE: stores the entered admin code? int k_adminc; // number of digits of admin code still to enter int k_admin; // if player is an admin, flags float k_adm_lasttime; // store time of last attempt getting admin rights int k_captain; // if player is team captain int k_coach; // if player is team coach float k_flag; // flagvalue to customise settings such as sounds/autoscreenshot float k_msgcount; // NOT_SURE: last time mod printed a message to client? float k_picked; // NOT_SURE: int k_pauseRequests; // number of 'pause' commands the player executed during a match int k_stuff; // if player has received stuffed aliases|commands // k_stuff flags #define STUFF_MAPS (1<<0) #define STUFF_COMMANDS (1<<1) float k_teamnumber; // team the player is a member of, 1 = team1, 2 = team2 float k_teamnum; // NOT_SURE: float lastwepfired; // float maxspeed; // Used to set Maxspeed on a player moved from old qw defs.qc float suicide_time; // can't suicide sooner than this // ILLEGALFPS[ // Zibbo's frametime checking code float real_time; float uptimebugpolicy; float fAverageFrameTime; float fFrameCount; float fDisplayIllegalFPS; float fCurrentFrameTime; float fLowestFrameTime; float fHighestFrameTime; float fIllegalFPSWarnings; // ILLEGALFPS] float shownick_time; // used to force centerprint is off at desired time clientType_t ct; // client type for client edicts // { timing float k_lastPostThink; // last time PlayerPostThink or SpectatorThink was called float k_timingWarnTime; // time of last client is timing warning int k_timingTakedmg; // .... so we can restore int k_timingSolid; // .... so we can restore int k_timingMovetype; // .... so we can restore // } // { stats int wp_stats; // show +wp_stats or not float wp_stats_time; // used to force centerprint is off at desired time int sc_stats; // show +scores or not float sc_stats_time; // used to force centerprint is off at desired time player_stats_t ps; // store player statistic here, like taken armors etc... float control_start_time; // time when player gained control float it_pickup_time[itMAX]; // total possession time of items float wp_pickup_time[wpMAX]; // total possession time of weapons // } // { mvd demo weapon stats int wpstats_mask; // bit mask, like ( 1 << wpSG | 1 << wpLG ), tell us which weapon stats need to be sent to demo at some point // } int need_clearCP; // if this true, clear center print at certain cases // { ghost stuff int ghost_slot; // now ktx put ghost in players scoreboards in one of free slots - store this slot float ghost_dt; // ghost drop time - time when player dropped int ghost_clr; // color of dropped player // } vote_t v; // player votes stored here // { spec stuff int favx[MAX_CLIENTS]; // here stored players number for appropriate favX_add/Xfav_go commands int fav[MAX_CLIENTS]; // here stored players number for fav_add/next_fav commands autoTrackType_t autotrack; // is autotrack or auto_pow or ktpro autorack qbool apply_ktpro_autotrack; // if we use ktpro's autotrack, that a hint to apply pov switch struct gedict_s *autotrack_hint; // per spectator autotrack hint, this helps switch pov more precise struct gedict_s *wizard; // for specs, link to the entity which represent wizard int last_goal; // just store here self->s.v.goal from last spec frame, so we can catch pov switch // } pos_t pos[MAX_POSITIONS]; // for player pos_save / pos_move float pos_move_time; // for player pos_save / pos_move // { CTF struct gedict_s *hook; // grapple qbool on_hook; // are we on the grapple? qbool hook_out; // is the grapple in flight? int ctf_flag; // do we have a rune or flag? float regen_time; // time to update health if regen rune float rune_sound_time; // dont spam rune sounds (1 per second) float carrier_frag_time; // used for carrier assists float return_flag_time; // used for flag return assists float rune_notify_time; // already have a rune spam prevention float carrier_hurt_time; // time we last hurt enemy carrier float rune_pickup_time; // time we picked up current rune float hook_damage_time; // manage dps dealt to hooked enemies float hook_cancel_time; // delay cancel on throw with smooth hook float hook_reset_time; // marker for grapple reset (decoupled from `attack_finished`) float hook_pullspeed; // accelerate grapple velocity float hook_pullspeed_accel; // number by which to increment velocity char *last_rune; // name of last rune we send to client float items2; // using ZQ_ITEMS2 extension in mvdsv we can use per client sigils for runes // // TF -- well, we does not support TF but require it for loading TF map as CTF map. // int team_no; // team number, as I got TF support it from 1 to 4. (up to 4 teams). // } // int i_agmr; // Instagib AirGib Master rune qbool was_jump; // { wreg qbool wreg_attack; // client simulate +attack via "cmd wreg" feature wreg_t *wreg; // [256] // } // { communication commands struct gedict_s *s_last_to; // last direct msg to struct gedict_s *s_last_from; // last direct msf from // } fp_cmd_t fp_c; // cmd flood protection fp_cmd_t fp_s; // say flood protection float tdeath_time; // when player invoke spawn_tdeath(...), help reduce double telefrags // { rocket arena float idletime; // how long they can idle float lasttime; // last time idle was checked float laststattime; // time of last status update raPlayerType_t ra_pt; // ra player type // } // { Clan Arena/Wipepout struct gedict_s *track_target; // who are we tracking? qbool ca_alive; qbool ca_ready; qbool can_respawn; qbool in_play; // is player still fighting? qbool in_limbo; // waiting to respawn during wipeout qbool last_alive_active; // if last alive timer is active qbool no_pain; // if player can take any damage to health or armor float ca_round_frags; float ca_round_kills; float ca_round_dmg; float ca_round_dmgt; float ca_round_deaths; float ca_round_glhit; float ca_round_glfired; float ca_round_rlhit; float ca_round_rldirect; float ca_round_lghit; float ca_round_lgfired; float alive_time; // number of seconds player is in play float time_of_respawn; // server time player respawned or round started float seconds_to_respawn; // number of seconds until respawn float escape_time; // number of seconds after "escaping" char *teamcolor; // color of player's team char cptext[100]; // centerprint for player int ca_ammo_grenades; // grenade ammo int tracking_enabled; int round_deaths; // number of times player has died in the round int round_kills; // number of kills in the round int spawn_delay; // total delay between death and spawn // } // { float pb_time; float pb_old_time; int pb_frame; // frame which currently must be or already played qbool is_playback; float rec_start_time; // time when record starts int rec_count; // count of recorded frames qbool is_recording; struct gedict_s *pb_ent; // enitity which used to show our model during playback plrfrm_t *plrfrms; // [MAX_PLRFRMS] for record trix // } // { for /cmd callalias char *callalias; // store alias name float callalias_time; // time when we must activate that alias // } char *f_checkbuf; // for /cmd check f_xxx // Yawnmode variables vec3_t old_vel; // store pre physicsthink velocity float spawn_weights[MAX_SPAWN_WEIGHTS]; // spawn point weights used by "fair respawns" // yeah its lame, but better than checking setinfo each time. int ezquake_version; // midair float mid_top_height; float mid_top_avgheight; float mid_top_score; float mid_top_kills; float mid_top_stomps; float mid_top_streak; float mid_top_spawnfrag; float mid_top_rl_efficiency; // { race int race_id; // used by checkpoints, // start checkpoint have id = 0, // intermediate checkpoints have it from 1 to xxx, // and end checkpoint have id xxx + 1 float race_volume; // how loud to play sound() when you tocuh this checkpoint int race_effects; // apply this effects when checkpoint is touched int race_RouteNodeType; // this is actually must be raceRouteNodeType_t // but unwilling to move type definition out of race.c so using int int race_ready; // is player ready for race int race_chasecam; // does player want to follow other racers in line int race_chasecam_freelook; // disable server forcing v_angle on client int race_chasecam_view; // does follow uses the chasecam or 1st person view int race_afk; // counter for afk starts qbool racer; // this player is actively racing right now qbool race_participant; // this player participated in the current race qbool muted; // this player produces no sound int hideentity; // links to entity to hide in eye chasecam qbool hideplayers; // if set, all players hidden (read by mvdsv) qbool hideplayers_default; // racer can choose to have this on or off int race_closest_guide_pos; // when guide route loaded, this is closest position // race_route_start entity fields char *race_route_name; // the name of the route char *race_route_description; // the description of the route int race_route_timeout; // the maximum time to complete the route int race_route_weapon_mode; // the weapon mode - see raceWeapoMode_t int race_route_falsestart_mode; // the falsestart mode - see raceFalseStartMode_t float race_route_start_yaw; // the player's initial yaw angle float race_route_start_pitch; // the player's initial pitch angle int race_flags; // flags affecting this particular object (teleports only atm) int race_track; // ent# of person this player is tracking (0 for default) // } int trackent; // pseudo spectating for players. // { bloodfest qbool bloodfest_boss; // is monsters is bloodfest boss? // } qbool dropitem; // true if placed with "dropitem" command. // { hoonymode struct gedict_s *k_hoonyspawn; // hoonymode: the player's spawn on even-numbered round struct gedict_s *k_hoony_new_spawn; // hoonymode: the player's spawn for the current round float initial_spawn_delay; // should be 'taken' at game start and spawn after delay int hoony_timelimit; // maximum time for each round char *hoony_defaultwinner; // if round time expires, who wins the round? if null then both players score point byte hoony_results[HM_MAX_ROUNDS]; // store results of each round int hoony_prevfrags; // frags at end of previous round int hoony_nomination; // links player -> nominated spawn and vice versa int hoony_spawn_order; // spawn order when shuffling // } #ifdef BOT_SUPPORT // { frogbots fb_entvars_t fb; // } #endif // { teamplay extensions, for server-side mm2 teamplay_t tp; unsigned int tp_flags; // } // { lgc lgc_state_t lgc_state; int lgc_distance_misses[LGCMODE_DISTANCE_BUCKETS]; int lgc_distance_hits[LGCMODE_DISTANCE_BUCKETS]; // } // { // let mvdsv know when player has teleported, and adjust for high-ping int teleported; // } // { // Allow teleports to vote for maps string_t ktx_votemap; // } // { qbool spawn_effect_queued; // } // { hiprot fields int rotate_type; // internal, rotate(0), movewall(1), setorigin(2), see hiprot.c vec3_t neworigin; // internal, origin tracking vec3_t rotate; // rotation angle vec3_t finalangle; // normalized version of 'angles' float endtime; // internal, animation tracking float duration; // internal, animation tracking string_t group; // linking of rotating brushes string_t path; // from ent field 'target', as 'path' to mirror original source string_t event; // events that may happen at path corners // } // { func_bob float distance; // distance between vantage points float waitmin; // speed-up factor, >0, see func_bob.c for defaults float waitmin2; // slowdown factor, >0, see func_bob.c for defaults // } // { ambient_general float volume; // attenuation, see misc.c for defaults // } // { trigger_heal float healmax; // maximum health see triggers.c for defaults float healtimer; // internal timer for tracking health replenishment interval // } // { csqc func_t SendEntity; // } } gedict_t; typedef enum { raceWeaponUnknown = 0, // this must never happens raceWeaponNo, // weapon not allowed. NOTE: must be second in this enum!!! raceWeaponAllowed, // weapon allowed raceWeapon2s, // weapon allowed after 2s raceWeaponMAX } raceWeapoMode_t; typedef enum { raceFalseStartUnknown = 0, // this must never happens raceFalseStartNo, // no false start, player is stuck until 'go' raceFalseStartYes, // false start allowed, player can move anytime before 'go' raceFalseStartMAX } raceFalseStartMode_t; typedef enum { nodeUnknown = 0, // this node is fucked by lame coding, I mean this must never happens nodeStart, // this node is start of race route nodeCheckPoint, // this node is intermediate nodeEnd, // this node is end of race route nodeMAX } raceRouteNodeType_t; typedef struct { raceRouteNodeType_t type; // race route node type vec3_t ang; // this is only need for start node, so we can set player view angles vec3_t org; // node origin in 3D space vec3_t sizes; // dimensions (if 0, default) } raceRouteNode_t; typedef struct { char name[128]; // NOTE: this will probably FUCK QVM!!! char desc[128]; // NOTE: this will probably FUCK QVM!!! int cnt; // how much nodes we actually have, no more than MAX_ROUTE_NODES float timeout; // when timeout of race must occur raceWeapoMode_t weapon; // weapon mode raceFalseStartMode_t falsestart; // start mode raceRouteNode_t node[MAX_ROUTE_NODES]; // nodes of this route, fixed array, yeah I'm lazy } raceRoute_t; typedef struct { float time; char racername[64]; char demoname[64]; float distance; float maxspeed; float avgspeed; float avgcount; char date[64]; raceWeapoMode_t weaponmode; // weapon mode raceFalseStartMode_t startmode; // start mode int playernumber; int position; } raceRecord_t; typedef enum { raceNone = 0, // race is inactive raceCD, // race in count down state raceActive, // race is active } raceStatus_t; #define NUM_CHASECAMS 4 // number of camera views defined #define NUM_BESTSCORES 10 typedef struct { raceRecord_t records[NUM_BESTSCORES]; // array of best scores information raceRecord_t currentrace[MAX_CLIENTS]; // curent score information int cnt; // how much we actually have of routes, no more than MAX_ROUTES int active_route; // which route active right now raceRoute_t route[MAX_ROUTES]; // fixed array of routes // { count down int cd_cnt; // 4 3 2 1 GO! float cd_next_think; // // } int timeout_setting; // just how long timeout float timeout; // when timeout of race must occur float start_time; // when race was started // { char top_nick[64]; // NOTE: this will probably FUCK QVM!!! int top_time; // } int next_race_time; // used for centerprint, help us print it not each server frame but more rare, each 100ms or something qbool warned; // do we warned why we can't start race qbool race_recording; // is race being recorded? int next_racer; // this is queue of racers raceWeapoMode_t weapon; // weapon mode raceFalseStartMode_t falsestart; // start type raceStatus_t status; // race status int pacemaker_time; // time of the current pacemaker route char pacemaker_nick[64]; // name of the current pacemaker int racers_complete; // number of players finished current race int last_completion_time; // time of last player to complete the race int last_completion_eq; // number of players equalling the last completion time int racers_competing; // number of players starting current race int rounds; // number of rounds in this match int round_number; // current round number } race_t; extern race_t race; // whole race struct QW-Group-ktx-d05d6ca/include/q_shared.h000066400000000000000000000135441475442401000200210ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #ifndef __Q_SHARED_H #define __Q_SHARED_H // q_shared.h -- included first by ALL program modules. // A user mod should never modify this file #ifdef _MSC_VER #pragma warning(disable : 4244) #pragma warning(disable : 4305) // truncation from const double to float #pragma warning(disable : 4996) // MSVS8 warnings about POSIX functions #pragma warning(disable : 4311) // pointer truncation #pragma warning(disable : 4267) // conversion from 'size_t' to 'int', possible loss of data #endif #if defined(__GNUC__) #define PRINTF_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) #define SCANF_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) #else #define PRINTF_FUNC( fmtargnumber ) #define SCANF_FUNC( fmtargnumber ) #endif /********************************************************************** VM Considerations The VM can not use the standard system headers because we aren't really using the compiler they were meant for. We use bg_lib.h which contains prototypes for the functions we define for our own use in bg_lib.c. When writing mods, please add needed headers HERE, do not start including stuff like in the various .c files that make up each of the VMs since you will be including system headers files can will have issues. Remember, if you use a C library function that is not defined in bg_lib.c, you will have to add your own version for support in the VM. **********************************************************************/ #ifdef Q3_VM // QVM does not have such thing as visibility, using empty value to make compiler happy. #define VISIBILITY_VISIBLE #include "bg_lib.h" #else // Visibility for native library. #ifdef _WIN32 #define VISIBILITY_VISIBLE __declspec(dllexport) #else #define VISIBILITY_VISIBLE __attribute__((visibility("default"))) #endif #include #include #include #include #include #include #include #include #include #if !defined( _WIN32 ) || !defined(_MSC_VER) // so intptr_t is defined for all non MS compilers #include #endif #if defined( __linux__ ) || defined( _WIN32 ) /* || defined( __APPLE__ ) require?*/ // this is trap/syscalls, for popular functions like cos/sin/tan prototypes // most likely alredy declared in above included headers, but not for below functions, // because they are BSD originated, so we need declare it. size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz); #endif // native_lib.c #if defined( _WIN32 ) int Q_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr); int snprintf(char *buffer, size_t count, char const *format, ...); #else #define Q_vsnprintf vsnprintf #endif // defined( _WIN32 ) #endif #define MAX_CLIENTS 32 #define MAX_QPATH 64 // max length of a quake game pathname #define MAX_OSPATH 128 // max length of a filesystem pathname #define MAX_EDICTS 2048 #define MAX_LIGHTSTYLES 64 #define MAX_MODELS 256 // these are sent over the net as bytes #define MAX_SOUNDS 256 // so they cannot be blindly increased #define MAX_STYLESTRING 64 // up / down #define PITCH 0 // left / right #define YAW 1 // fall over #define ROLL 2 #define QDECL typedef unsigned char byte; typedef enum { false, true } qbool; #ifndef NULL #define NULL ((void *)0) #endif typedef char *string_t; typedef intptr_t func_t; typedef int stringref_t; typedef int funcref_t; typedef float vec_t; typedef vec_t vec3_t[3]; typedef vec_t vec5_t[5]; //============================================= short ShortSwap(short l); int LongSwap(int l); float FloatSwap(const float *f); //============================================= // 64-bit integers for global rankings interface // implemented as a struct for qvm compatibility typedef struct { byte b0; byte b1; byte b2; byte b3; byte b4; byte b5; byte b6; byte b7; } qint64; //============================================= /* short BigShort(short l); short LittleShort(short l); int BigLong (int l); int LittleLong (int l); qint64 BigLong64 (qint64 l); qint64 LittleLong64 (qint64 l); float BigFloat (const float *l); float LittleFloat (const float *l); void Swap_Init (void); */ //============================================= int Q_isprint(int c); int Q_islower(int c); int Q_isupper(int c); int Q_isalpha(int c); // portable case insensitive compare int Q_stricmp(const char *s1, const char *s2); int Q_strncmp(const char *s1, const char *s2, int n); int Q_stricmpn(const char *s1, const char *s2, int n); char* Q_strlwr(char *s1); char* Q_strupr(char *s1); char* Q_strrchr(const char *string, int c); // buffer size safe library replacements void Q_strncpyz(char *dest, const char *src, int destsize); void Q_strcat(char *dest, int size, const char *src); // strlen that discounts Quake color sequences int Q_PrintStrlen(const char *string); // removes color sequences from string char* Q_CleanStr(char *string); #endif // __Q_SHARED_H QW-Group-ktx-d05d6ca/include/rng.h000066400000000000000000000004101475442401000170050ustar00rootroot00000000000000// rng.h -- High-quality random number generation. #ifndef __RNG_H__ #define __RNG_H__ #include "rng_gen_state.h" void rng_seed(RngState*, int seed); unsigned int rng_next(RngState*); void rng_seed_global(int seed); unsigned int rng_next_global(void); #endif QW-Group-ktx-d05d6ca/include/rng_gen_impl.h000066400000000000000000000003601475442401000206630ustar00rootroot00000000000000// rng_gen_impl.h -- Xoroshiro128** implementation. #ifndef __RNG_GEN_IMPL_H__ #define __RNG_GEN_IMPL_H__ #include "rng_gen_state.h" RngState rng_gen_impl_initial_state(int seed); unsigned int rng_gen_impl_next(RngState* state); #endif QW-Group-ktx-d05d6ca/include/rng_gen_state.h000066400000000000000000000002551475442401000210450ustar00rootroot00000000000000#ifndef __RNG_STATE_H__ #define __RNG_STATE_H__ // You must initialize this with rng_seed/rng_seed_global! typedef struct RngState { unsigned int s[4]; } RngState; #endif QW-Group-ktx-d05d6ca/include/rng_seed_impl.h000066400000000000000000000004151475442401000210330ustar00rootroot00000000000000// rng_seed_impl.h -- SplitMix64 implementation. #ifndef __RNG_SEED_IMPL_H__ #define __RNG_SEED_IMPL_H__ #ifndef Q3_VM #include typedef uint64_t rng_seed_t; #else typedef unsigned int rng_seed_t; #endif rng_seed_t rng_seed_impl_next(rng_seed_t*); #endif QW-Group-ktx-d05d6ca/include/stats.h000066400000000000000000000041451475442401000173660ustar00rootroot00000000000000#ifndef STATS_H #define STATS_H #define MAX_TM_STATS (MAX_CLIENTS) typedef struct teamStats_s { char *name; // team name int gfrags; // frags from ghosts int frags; int deaths; int tkills; float dmg_t; float dmg_g; float dmg_team; float dmg_eweapon; float res; float str; float rgn; float hst; int caps; int pickups; int returns; int f_defends; int c_defends; wpType_t wpn[wpMAX]; itType_t itm[itMAX]; int transferred_RLpacks; int transferred_LGpacks; } teamStats_t; extern teamStats_t tmStats[MAX_TM_STATS]; extern int tmStats_cnt; extern qbool lastStatsData; typedef struct stats_format_s { char *name; void (*match_header)(fileHandle_t handle, char *ip, int port); void (*match_footer)(fileHandle_t handle); void (*teams_header)(fileHandle_t handle); void (*team_detail)(fileHandle_t handle, int num, teamStats_t *stats); void (*teams_footer)(fileHandle_t handle, int teams); void (*players_header)(fileHandle_t handle); void (*player_detail)(fileHandle_t handle, int num, gedict_t *plr, const char *team); void (*players_footer)(fileHandle_t handle, int players); void (*race_detail)(fileHandle_t handle); } stats_format_t; #define FILE_FORMAT_DECL(x) \ void x##_match_header(fileHandle_t handle, char* ip, int port ); \ void x##_match_footer(fileHandle_t handle); \ void x##_teams_header(fileHandle_t handle); \ void x##_team_detail(fileHandle_t handle, int num, teamStats_t* stats); \ void x##_teams_footer(fileHandle_t handle, int team_count); \ void x##_players_header(fileHandle_t handle); \ void x##_player_detail(fileHandle_t handle, int num, gedict_t* plr, const char* team); \ void x##_players_footer(fileHandle_t handle, int players); \ void x##_race_detail(fileHandle_t handle); #define FILE_FORMAT_DEF(x) { \ #x, \ x##_match_header, \ x##_match_footer, \ x##_teams_header, \ x##_team_detail, \ x##_teams_footer, \ x##_players_header, \ x##_player_detail, \ x##_players_footer, \ x##_race_detail \ } const char* GetMode(void); char* ItName(itemName_t it); void S2di(fileHandle_t file_handle, const char *fmt, ...) PRINTF_FUNC(2); void MatchEndStatsTables(void); #endif // STATS_H QW-Group-ktx-d05d6ca/resources/000077500000000000000000000000001475442401000164425ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/000077500000000000000000000000001475442401000215235ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/id1/000077500000000000000000000000001475442401000222005ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/id1/copy PAK0 and PAK1 here000066400000000000000000000000021475442401000256450ustar00rootroot00000000000000 QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/000077500000000000000000000000001475442401000231405ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/arena3.ent000066400000000000000000000313241475442401000250240ustar00rootroot00000000000000// Entity 0 // worldspawn { "classname" "worldspawn" "message" "Terrain : by Drastic_Man" "worldtype" "0" "sounds" "-1" "light" "0" } // Entity 1 // Entities:g[1] -> info_player_deathmatch:e[1] { "classname" "info_player_deathmatch" "origin" "-154.4 -374.9 -620" "angle" "28" } // Entity 2 // Entities:g[1] -> info_player_deathmatch:e[2] { "classname" "info_player_deathmatch" "origin" "321 159.3 -620" "angle" "249" } // Entity 3 // Entities:g[1] -> info_player_deathmatch:e[3] { "classname" "info_player_deathmatch" "origin" "230.3 -384.7 -640" "angle" "100" } // Entity 4 // Entities:g[1] -> info_player_deathmatch:e[4] { "classname" "info_player_deathmatch" "origin" "767 -127.4 -625" "angle" "187" } // Entity 5 // Entities:g[1] -> info_player_deathmatch:e[5] { "classname" "info_player_deathmatch" "origin" "-352 16 -660" "angle" "339" } // Entity 6 // Entities:g[1] -> info_player_start:e[6] { "origin" "-31 403 -604" "angle" "-76" "classname" "info_player_deathmatch" } { "origin" "607 -637 -629" "angle" "114" "classname" "info_player_deathmatch" } { "origin" "775 -125 -629" "angle" "-176" "classname" "info_player_deathmatch" } { "origin" "574 266 -632" "angle" "-132" "classname" "info_player_deathmatch" } { "classname" "info_player_start" "origin" "189 -192 -512" } // Entity 7 // Entities:g[1] -> light_fluoro:e[7] { "classname" "light_fluoro" "light" "500" "style" "0" "origin" "227 -192 -261" } // Entity 8 // Entities:g[1] -> light_fluoro:e[8] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "715 245 -408" } // Entity 9 // Entities:g[1] -> light_fluoro:e[9] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "194 435 -408" } // Entity 10 // Entities:g[1] -> light_fluoro:e[10] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "733 -574 -408" } // Entity 11 // Entities:g[1] -> light_fluoro:e[11] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "-333 247 -408" } // Entity 12 // Entities:g[1] -> light_fluoro:e[12] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "-548 -159 -408" } // Entity 13 // Entities:g[1] -> light_fluoro:e[13] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "-333 -557 -408" } // Entity 14 // Entities:g[1] -> light_fluoro:e[14] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "189 -733 -408" } // Entity 15 // Entities:g[1] -> light_fluoro:e[15] { "classname" "light_fluoro" "light" "400" "style" "0" "origin" "928 -150 -408" } // Entity 16 // Entities:g[1] -> light_fluoro:e[16] { "classname" "light_fluoro" "light" "600" "style" "0" "origin" "-128 -192 -512" } // Entity 17 // Entities:g[1] -> light_fluoro:e[17] { "classname" "light_fluoro" "light" "600" "style" "0" "origin" "454 -192 -512" } // Entity 18 // Entities:g[1] -> info_teleport_destination:e[18] { "classname" "info_teleport_destination" "targetname" "tele1" "origin" "-373 -209 -513" } // Entity 19 // Entities:g[1] -> info_teleport_destination:e[19] { "classname" "info_teleport_destination" "targetname" "tele1" "origin" "800 -203 -512" } // Entity 20 // Entities:g[1] -> info_teleport_destination:e[20] { "classname" "info_teleport_destination" "targetname" "tele1" "origin" "213 -320 -512" } { "classname" "info_monster_start" "origin" "-172.875 -192.875 -654.5" } { "classname" "info_monster_start" "origin" "-81.75 -172 -695.875" } { "classname" "info_monster_start" "origin" "-261.25 -136.75 -679.875" } { "classname" "info_monster_start" "origin" "-123.125 -56.125 -695.875" } { "classname" "info_monster_start" "origin" "4.625 -109.875 -695.875" } { "classname" "info_monster_start" "origin" "92.75 -164.625 -695.875" } { "classname" "info_monster_start" "origin" "93.5 -234.75 -695.875" } { "classname" "info_monster_start" "origin" "122.25 -292.875 -680.5" } { "classname" "info_monster_start" "origin" "207.75 -268.25 -667.75" } { "classname" "info_monster_start" "origin" "195.75 -177.25 -685.125" } { "classname" "info_monster_start" "origin" "341.5 -164.875 -695.875" } { "classname" "info_monster_start" "origin" "432.625 -176.75 -695.875" } { "classname" "info_monster_start" "origin" "366.875 -262.625 -695.875" } { "classname" "info_monster_start" "origin" "489.625 -286.375 -695.875" } { "classname" "info_monster_start" "origin" "434.125 -370 -695.875" } { "classname" "info_monster_start" "origin" "489.625 -439.75 -695.875" } { "classname" "info_monster_start" "origin" "445.625 -558.25 -676.25" } { "classname" "info_monster_start" "origin" "345.5 -579.875 -694.25" } { "classname" "info_monster_start" "origin" "299.875 -680.75 -695.875" } { "classname" "info_monster_start" "origin" "256.625 -599 -695.5" } { "classname" "info_monster_start" "origin" "310.375 -777.875 -695.875" } { "classname" "info_monster_start" "origin" "204 -813.5 -691.75" } { "classname" "info_monster_start" "origin" "176.375 -619.25 -694.5" } { "classname" "info_monster_start" "origin" "90.5 -543.375 -695.875" } { "classname" "info_monster_start" "origin" "53.375 -440.875 -670.125" } { "classname" "info_monster_start" "origin" "10.75 -631.25 -655.75" } { "classname" "info_monster_start" "origin" "99.875 -784.625 -642.25" } { "classname" "info_monster_start" "origin" "19.125 -759.625 -608" } { "classname" "info_monster_start" "origin" "-86.375 -715.5 -581.75" } { "classname" "info_monster_start" "origin" "-64.375 -556 -653.75" } { "classname" "info_monster_start" "origin" "-141.5 -453.25 -628.875" } { "classname" "info_monster_start" "origin" "-45.625 -449.75 -647.125" } { "classname" "info_monster_start" "origin" "-108.375 -360.5 -628.875" } { "classname" "info_monster_start" "origin" "10.75 -245.125 -695.875" } { "classname" "info_monster_start" "origin" "163.375 -80.75 -661.875" } { "classname" "info_monster_start" "origin" "313 -10 -671" } { "classname" "info_monster_start" "origin" "503.375 94.375 -695.875" } { "classname" "info_monster_start" "origin" "633.125 -196.25 -657.75" } { "classname" "info_monster_start" "origin" "796.875 -121.125 -628.875" } { "classname" "info_monster_start" "origin" "139 35.875 -672.75" } { "classname" "info_monster_start" "origin" "255.25 60.25 -675.75" } { "classname" "info_monster_start" "origin" "322.375 131.625 -627.875" } { "classname" "info_monster_start" "origin" "-200.625 -293.625 -629.5" } { "classname" "info_monster_start" "origin" "-279.125 -344.25 -639.75" } { "classname" "info_monster_start" "origin" "-218.375 -422.125 -632.5" } { "classname" "info_monster_start" "origin" "-353.875 -290 -675.875" } { "classname" "info_monster_start" "origin" "-408 -195.125 -664.875" } { "classname" "info_monster_start" "origin" "-541.375 -335.75 -685.375" } { "classname" "info_monster_start" "origin" "-577.625 -265.125 -680.25" } { "classname" "info_monster_start" "origin" "-610.375 -201.375 -675.5" } { "classname" "info_monster_start" "origin" "-478.25 -74.25 -640.25" } { "classname" "info_monster_start" "origin" "-560.625 -1.625 -664.875" } { "classname" "info_monster_start" "origin" "-510.625 95.625 -664.875" } { "classname" "info_monster_start" "origin" "-414.375 37.75 -664.875" } { "classname" "info_monster_start" "origin" "-299.125 -7.25 -664.875" } { "classname" "info_monster_start" "origin" "-225.125 67.375 -670.25" } { "classname" "info_monster_start" "origin" "8.875 -12.875 -687.5" } { "classname" "info_monster_start" "origin" "764.625 -226.25 -648.125" } { "classname" "info_monster_start" "origin" "728.125 -344.75 -671.625" } { "classname" "info_monster_start" "origin" "682.5 -430.125 -682.875" } { "classname" "info_monster_start" "origin" "537.875 -538.375 -665.75" } { "classname" "info_monster_start" "origin" "-479.5 156.125 -664.875" } { "classname" "info_monster_start" "origin" "-406.875 297.75 -675.875" } { "classname" "info_monster_start" "origin" "-496.5 -423 -691.875" } { "classname" "info_monster_start" "origin" "-455 -504 -695.875" } { "classname" "info_monster_start" "origin" "421.25 128.5 -665.25" } { "classname" "info_monster_start" "origin" "330.75 -352.375 -668.5" } { "classname" "info_monster_start" "origin" "595.625 -682.25 -633.875" } { "classname" "info_monster_start" "origin" "503.125 -713.25 -669.125" } { "classname" "info_monster_start" "origin" "407.875 -745.25 -695.875" } { "classname" "info_monster_start" "origin" "-176 -688.25 -618.125" } { "classname" "info_monster_start" "origin" "-267.125 -660.625 -668.125" } { "classname" "info_monster_start" "origin" "-367.625 -630 -695.875" } { "classname" "info_monster_start" "origin" "-411.875 -587.875 -695.875" } { "classname" "info_monster_start" "origin" "661.5 -660.25 -632.875" } { "classname" "info_monster_start" "origin" "739.375 -634.125 -662.5" } { "classname" "info_monster_start" "origin" "793.375 -592.875 -687.5" } { "classname" "info_monster_start" "origin" "829.125 -523 -695.875" } { "classname" "info_monster_start" "origin" "871.125 -441.375 -695.875" } { "classname" "info_monster_start" "origin" "914.625 -356.5 -695.875" } { "classname" "info_monster_start" "origin" "954.25 -279.25 -664.875" } { "classname" "info_monster_start" "origin" "987.375 -214.875 -636.625" } { "classname" "info_monster_start" "origin" "1018.62 -145.875 -609.375" } { "classname" "info_monster_start" "origin" "971.375 -53.875 -636" } { "classname" "info_monster_start" "origin" "905.5 74.25 -669.125" } { "classname" "info_monster_start" "origin" "842.625 196.75 -690.25" } { "classname" "info_monster_start" "origin" "812.625 255.25 -695.875" } { "classname" "info_monster_start" "origin" "777.375 321.375 -695.875" } { "classname" "info_monster_start" "origin" "712.25 343.125 -686" } { "classname" "info_monster_start" "origin" "636.5 368.375 -670.25" } { "classname" "info_monster_start" "origin" "567.875 391.25 -663.25" } { "classname" "info_monster_start" "origin" "94.75 484.125 -660.25" } { "classname" "info_monster_start" "origin" "-608.25 -94.625 -664.875" } { "classname" "info_monster_start" "origin" "596.5 -525.625 -659.125" } { "classname" "info_monster_start" "origin" "219 -442.375 -645.625" } { "classname" "info_monster_start" "origin" "-93.625 56.25 -691.75" } { "classname" "info_monster_start" "origin" "3.125 114.5 -685.875" } { "classname" "info_monster_start" "origin" "101.125 166.5 -695.875" } { "classname" "info_monster_start" "origin" "198.75 171.5 -665.375" } { "classname" "info_monster_start" "origin" "174.25 510.625 -692.625" } { "classname" "info_monster_start" "origin" "479 420.875 -691.75" } { "classname" "info_monster_start" "origin" "371.5 456.75 -695.875" } { "classname" "info_monster_start" "origin" "249 497.625 -695.875" } { "classname" "info_monster_start" "origin" "29.375 462.375 -633.75" } { "classname" "info_monster_start" "origin" "-31.75 442 -613.75" } { "classname" "info_monster_start" "origin" "-96 420.625 -622.375" } { "classname" "info_monster_start" "origin" "-162.875 398.25 -639.5" } { "classname" "info_monster_start" "origin" "-254 367.875 -666.625" } { "classname" "info_monster_start" "origin" "-442.625 228.125 -664.875" } { "classname" "info_monster_start" "origin" "-313.875 184.75 -673.875" } { "classname" "info_monster_start" "origin" "-153 140 -695" } { "classname" "info_monster_start" "origin" "-99.5 193.875 -672.75" } { "classname" "info_monster_start" "origin" "-45.75 248.125 -641" } { "classname" "info_monster_start" "origin" "-1.875 288 -633.75" } { "classname" "info_monster_start" "origin" "53.125 273.75 -655" } { "classname" "info_monster_start" "origin" "195.75 394.375 -669.5" } { "classname" "info_monster_start" "origin" "310.875 477 -695.875" } { "classname" "info_monster_start" "origin" "357.5 341.125 -695.875" } { "classname" "info_monster_start" "origin" "240.875 227.75 -661.875" } { "classname" "info_monster_start" "origin" "341.125 201.875 -640.625" } { "classname" "info_monster_start" "origin" "426.25 179.75 -653.875" } { "classname" "info_monster_start" "origin" "523.25 154.625 -672" } { "classname" "info_monster_start" "origin" "600.25 132.625 -669.875" } { "classname" "info_monster_start" "origin" "561.875 -243.5 -677.25" } { "classname" "info_monster_start" "origin" "721.375 -4 -655.25" } { "classname" "info_monster_start" "origin" "594.625 -13.625 -690.125" } { "classname" "info_monster_start" "origin" "634.125 -76.75 -671.375" } { "classname" "info_monster_start" "origin" "480.625 -71 -695.875" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/arena5.ent000066400000000000000000000430471475442401000250330ustar00rootroot00000000000000{ "classname" "worldspawn" } { "classname" "info_player_start" "angle" "225" "origin" "320 832 832" } { "classname" "func_plat" "angle" "96" "height" "280" "sounds" "2" "model" "*1" } { "classname" "func_plat" "angle" "96" "height" "280" "sounds" "2" "model" "*2" } { "classname" "info_teleport_destination" "angle" "306" "targetname" "tele2" "origin" "-375 601 781" } { "classname" "info_teleport_destination" "angle" "318" "targetname" "tele3" "origin" "-222 668 270" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "419 -763 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "99 -889 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "-956 -465 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "-1088 -155 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "-691 815 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "-365 953 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "726 457 620" } { "classname" "light_flame_small_yellow" "light" "200" "style" "0" "origin" "856 149 620" } { "classname" "trigger_teleport" "angle" "110" "target" "tele2" "model" "*3" } { "classname" "light" "origin" "-1528 -376 586" } { "classname" "light" "origin" "-1384 -708 712" } { "classname" "light" "origin" "-1136 -512 716" } { "classname" "light" "origin" "-1208 -264 816" } { "classname" "light" "origin" "-1320 -448 640" } { "classname" "light" "origin" "168 -1048 668" } { "classname" "light" "origin" "480 -896 708" } { "classname" "light" "origin" "656 -1244 720" } { "classname" "light" "origin" "296 -1432 608" } { "classname" "light" "origin" "360 -1128 604" } { "classname" "light" "origin" "1176 712 586" } { "classname" "light" "origin" "1272 368 692" } { "classname" "light" "origin" "1056 448 656" } { "classname" "light" "origin" "840 568 644" } { "classname" "light" "origin" "984 212 724" } { "classname" "light" "origin" "-544 1372 720" } { "classname" "light" "origin" "-856 1240 616" } { "classname" "light" "origin" "-656 1160 672" } { "classname" "light" "origin" "-392 1092 724" } { "classname" "light" "origin" "-776 964 728" } { "classname" "light" "light" "500" "origin" "-192 -64 832" } { "classname" "light" "light" "500" "origin" "320 128 832" } { "classname" "light" "light" "500" "origin" "0 512 832" } { "classname" "light" "light" "500" "origin" "-704 64 832" } { "classname" "light" "light" "500" "origin" "-256 -448 832" } { "classname" "light" "light" "500" "origin" "192 -320 832" } { "classname" "light" "origin" "-704 -704 640" } { "classname" "light" "origin" "-256 -832 704" } { "classname" "light" "origin" "-64 -832 704" } { "classname" "light" "origin" "320 -704 704" } { "classname" "light" "origin" "576 -384 704" } { "classname" "light" "origin" "768 0 704" } { "classname" "light" "origin" "704 256 704" } { "classname" "light" "origin" "448 704 704" } { "classname" "light" "origin" "128 768 704" } { "classname" "light" "origin" "128 512 704" } { "classname" "light" "origin" "384 0 704" } { "classname" "light" "origin" "448 384 704" } { "classname" "light" "origin" "448 -320 704" } { "classname" "light" "origin" "-128 -576 704" } { "classname" "light" "origin" "-384 -192 704" } { "classname" "light" "origin" "-704 -128 704" } { "classname" "light" "origin" "-640 384 704" } { "classname" "light" "origin" "-448 192 704" } { "classname" "light" "origin" "64 320 704" } { "classname" "light" "origin" "192 -128 704" } { "classname" "light" "origin" "-128 704 704" } { "classname" "light" "origin" "384 -448 704" } { "classname" "light" "origin" "-426 510 780" } { "classname" "light" "origin" "-326 652 728" } { "classname" "light" "origin" "-438 720 860" } { "classname" "light" "light" "500" "origin" "-192 -72 416" } { "classname" "light" "light" "500" "origin" "320 128 432" } { "classname" "light" "light" "500" "origin" "192 -320 368" } { "classname" "light" "origin" "-384 -216 304" } { "classname" "light" "origin" "-704 -168 360" } { "classname" "light" "light" "500" "origin" "-704 48 384" } { "classname" "light" "origin" "-640 352 376" } { "classname" "light" "origin" "96 632 328" } { "classname" "light" "origin" "632 472 840" } { "classname" "light" "origin" "832 16 800" } { "classname" "light" "origin" "728 -304 824" } { "classname" "light" "origin" "592 -608 840" } { "classname" "light" "origin" "100 -808 808" } { "classname" "light" "origin" "-500 -800 792" } { "classname" "light" "origin" "-948 -368 744" } { "classname" "light" "origin" "-1036 -92 648" } { "classname" "light" "origin" "-844 -600 792" } { "classname" "light" "origin" "-1080 156 648" } { "classname" "light" "origin" "-976 424 840" } { "classname" "light" "origin" "-856 676 648" } { "classname" "light" "origin" "-624 792 824" } { "classname" "light" "origin" "-296 792 808" } { "classname" "light" "origin" "-120 984 752" } { "classname" "light" "origin" "220 880 824" } { "classname" "trigger_teleport" "angle" "110" "target" "tele2" "model" "*4" } { "classname" "light" "origin" "360 548 364" } { "classname" "light" "origin" "-668 -532 356" } { "classname" "light" "origin" "-132 632 328" } { "classname" "light" "origin" "-304 404 456" } { "classname" "light" "origin" "-368 -568 344" } { "classname" "item_health" "origin" "-400 -532 336" } { "classname" "item_health" "origin" "-296 -584 312" } { "classname" "item_health" "origin" "180 -1092 568" } { "classname" "item_health" "origin" "252 -1292 568" } { "classname" "weapon_supershotgun" "origin" "472 -908 592" } { "classname" "weapon_supershotgun" "origin" "-408 1086 592" } { "classname" "item_shells" "origin" "-446 1160 568" } { "classname" "item_shells" "origin" "-480 1240 568" } { "classname" "item_shells" "origin" "-652 288 318" } { "classname" "item_shells" "origin" "-688 216 312" } { "classname" "item_shells" "origin" "520 -992 568" } { "classname" "item_shells" "origin" "552 -1136 568" } { "classname" "item_spikes" "origin" "-632 -728 568" } { "classname" "item_spikes" "origin" "-528 -768 568" } { "classname" "item_spikes" "origin" "496 312 306" } { "classname" "item_spikes" "origin" "552 198 298" } { "classname" "weapon_rocketlauncher" "origin" "-152 48 320" } { "classname" "weapon_nailgun" "origin" "-300 566 786" } { "classname" "weapon_grenadelauncher" "origin" "860 584 562" } { "classname" "item_rockets" "origin" "936 616 556" } { "classname" "item_rockets" "origin" "194 734 576" } { "classname" "item_spikes" "origin" "-1460 -320 648" } { "classname" "item_spikes" "origin" "-1332 -264 648" } { "classname" "weapon_supernailgun" "origin" "-1256 -224 648" } { "classname" "item_health" "origin" "-884 468 648" } { "classname" "item_health" "origin" "-944 296 648" } { "classname" "trigger_teleport" "angle" "110" "target" "tele3" "model" "*5" } { "classname" "item_rockets" "origin" "0 -320 320" } { "classname" "item_rockets" "origin" "256 64 320" } { "classname" "item_rockets" "origin" "-64 448 320" } { "classname" "item_health" "origin" "-448 256 320" } { "classname" "info_monster_start" "origin" "-86.625 671.125 253" } { "classname" "info_monster_start" "origin" "-110.5 455.5 253" } { "classname" "info_monster_start" "origin" "188.5 422.375 253" } { "classname" "info_monster_start" "origin" "385.25 410.5 253" } { "classname" "info_monster_start" "origin" "415.125 259.375 253" } { "classname" "info_monster_start" "origin" "297 480 531" } { "classname" "info_monster_start" "origin" "612.625 502.25 535" } { "classname" "info_monster_start" "origin" "825.25 325.125 536" } { "classname" "info_monster_start" "origin" "923.125 375.75 536" } { "classname" "info_monster_start" "origin" "967.25 272.125 536" } { "classname" "info_monster_start" "origin" "885.25 464.75 536" } { "classname" "info_monster_start" "origin" "849.625 548.25 536" } { "classname" "info_monster_start" "origin" "576.25 579 535" } { "classname" "info_monster_start" "origin" "537.875 650.125 535" } { "classname" "info_monster_start" "origin" "463.5 680.5 535" } { "classname" "info_monster_start" "origin" "151 808.125 535" } { "classname" "info_monster_start" "origin" "65.75 843 535" } { "classname" "info_monster_start" "origin" "-18.75 877.5 535" } { "classname" "info_monster_start" "origin" "-164 31.25 264" } { "classname" "info_monster_start" "origin" "199.375 -739.625 535" } { "classname" "info_monster_start" "origin" "267.25 -854.125 536" } { "classname" "info_monster_start" "origin" "273.875 -949.875 536" } { "classname" "info_monster_start" "origin" "356.125 -918.625 536" } { "classname" "info_monster_start" "origin" "126 -764.5 535" } { "classname" "info_monster_start" "origin" "59.625 -787 535" } { "classname" "info_monster_start" "origin" "-14.375 -812.125 535" } { "classname" "info_monster_start" "origin" "-225.75 -785.625 535" } { "classname" "info_monster_start" "origin" "-314.125 -749.375 535" } { "classname" "info_monster_start" "origin" "-395.375 -716.125 535" } { "classname" "info_monster_start" "origin" "-470 -685.625 535" } { "classname" "info_monster_start" "origin" "-923.375 -266.75 535" } { "classname" "info_monster_start" "origin" "-1050.88 -328.875 536" } { "classname" "info_monster_start" "origin" "-1140.25 -366 536" } { "classname" "info_monster_start" "origin" "-1111.88 -449.125 536" } { "classname" "info_monster_start" "origin" "-961.875 -189.375 535" } { "classname" "info_monster_start" "origin" "-907 412.125 535" } { "classname" "info_monster_start" "origin" "-550.875 909 536" } { "classname" "info_monster_start" "origin" "-557.5 1030 536" } { "classname" "info_monster_start" "origin" "-394.5 839.75 535" } { "classname" "info_monster_start" "origin" "-313.125 870.875 535" } { "classname" "info_monster_start" "origin" "-238.875 899.375 535" } { "classname" "info_monster_start" "origin" "-449.625 1070 536" } { "classname" "info_monster_start" "origin" "-645.25 997.5 536" } { "classname" "info_monster_start" "origin" "-735.25 964.125 536" } { "classname" "info_monster_start" "origin" "-839 562.25 535" } { "classname" "info_monster_start" "origin" "-868.25 497.5 535" } { "classname" "info_monster_start" "origin" "-941.75 335.375 535" } { "classname" "info_monster_start" "origin" "-975.75 260 535" } { "classname" "info_monster_start" "origin" "-1010.12 184.125 535" } { "classname" "info_monster_start" "origin" "-1044.38 108.375 535" } { "classname" "info_monster_start" "origin" "-1071.25 29.75 535" } { "classname" "info_monster_start" "origin" "-1034 -44.75 535" } { "classname" "info_monster_start" "origin" "-1000.12 -112.75 535" } { "classname" "info_monster_start" "origin" "311.5 -669.875 535" } { "classname" "info_monster_start" "origin" "-820.875 1121.75 536" } { "classname" "info_monster_start" "origin" "-699.375 1166.75 536" } { "classname" "info_monster_start" "origin" "-594.625 1205.62 536" } { "classname" "info_monster_start" "origin" "-511.375 1236.5 536" } { "classname" "info_monster_start" "origin" "-164.875 927.625 535" } { "classname" "info_monster_start" "origin" "-99.375 910.5 535" } { "classname" "info_monster_start" "origin" "980.125 607.125 536" } { "classname" "info_monster_start" "origin" "1025.88 499.75 536" } { "classname" "info_monster_start" "origin" "1066.5 404.25 536" } { "classname" "info_monster_start" "origin" "1100.62 324.125 536" } { "classname" "info_monster_start" "origin" "449.125 -883.5 536" } { "classname" "info_monster_start" "origin" "570.75 -1046.5 536" } { "classname" "info_monster_start" "origin" "466.125 -1086.5 536" } { "classname" "info_monster_start" "origin" "355.5 -1128.38 536" } { "classname" "info_monster_start" "origin" "262.75 -1163.5 536" } { "classname" "info_monster_start" "origin" "193.875 -980.125 536" } { "classname" "info_monster_start" "origin" "-785.25 681 535" } { "classname" "info_monster_start" "origin" "-807.875 631.125 535" } { "classname" "info_monster_start" "origin" "-770.625 -562.5 535" } { "classname" "info_monster_start" "origin" "-804.25 -505.875 535" } { "classname" "info_monster_start" "origin" "-1086.75 -522.625 536" } { "classname" "info_monster_start" "origin" "-1213.12 -608.125 536" } { "classname" "info_monster_start" "origin" "-1249.38 -502 536" } { "classname" "info_monster_start" "origin" "-1284.25 -400 536" } { "classname" "info_monster_start" "origin" "-1313 -313.625 536" } { "classname" "info_monster_start" "origin" "-1173.5 -268.5 536" } { "classname" "info_monster_start" "origin" "-847.625 -418.875 535" } { "classname" "info_monster_start" "origin" "-885.75 -342.25 535" } { "classname" "info_monster_start" "origin" "-701.25 -590.875 535" } { "classname" "info_monster_start" "origin" "-632.75 -619 535" } { "classname" "info_monster_start" "origin" "-148.625 -817.125 535" } { "classname" "info_monster_start" "origin" "-85.5 -836.375 535" } { "classname" "info_monster_start" "origin" "-699.25 713.375 535" } { "classname" "info_monster_start" "origin" "-620.125 743.125 535" } { "classname" "info_monster_start" "origin" "-496.625 800.5 535" } { "classname" "info_monster_start" "origin" "369.125 -650.25 535" } { "classname" "info_monster_start" "origin" "447.75 -623.625 535" } { "classname" "info_monster_start" "origin" "506.5 -603.625 535" } { "classname" "info_monster_start" "origin" "510.25 -596.5 535" } { "classname" "info_monster_start" "origin" "552.5 -514.25 535" } { "classname" "info_monster_start" "origin" "589 -443.5 535" } { "classname" "info_monster_start" "origin" "620.75 -381.75 535" } { "classname" "info_monster_start" "origin" "650.625 -323.75 535" } { "classname" "info_monster_start" "origin" "691.375 -244.75 535" } { "classname" "info_monster_start" "origin" "730.625 -168.375 535" } { "classname" "info_monster_start" "origin" "768.375 -95.25 535" } { "classname" "info_monster_start" "origin" "802.5 -28.875 535" } { "classname" "info_monster_start" "origin" "831 41.75 535" } { "classname" "info_monster_start" "origin" "794.625 118.5 535" } { "classname" "info_monster_start" "origin" "759.625 192.125 535" } { "classname" "info_monster_start" "origin" "719.75 276.375 535" } { "classname" "info_monster_start" "origin" "644.75 434.625 535" } { "classname" "info_monster_start" "origin" "681.375 357.25 535" } { "classname" "info_monster_start" "origin" "-355.375 254.5 253" } { "classname" "info_monster_start" "origin" "-449.625 348.5 253" } { "classname" "info_monster_start" "origin" "-669.375 88.875 253" } { "classname" "info_monster_start" "origin" "-442.75 33.625 253" } { "classname" "info_monster_start" "origin" "-334.75 -139.75 258" } { "classname" "info_monster_start" "origin" "421.875 -61.375 253" } { "classname" "info_monster_start" "origin" "234.375 774.125 535" } { "classname" "info_monster_start" "origin" "316.125 740.75 535" } { "classname" "info_monster_start" "origin" "394.875 708.5 535" } { "classname" "info_monster_start" "origin" "-155 333.375 253" } { "classname" "info_monster_start" "origin" "283.5 -341.5 253" } { "classname" "info_monster_start" "origin" "-555.25 -650.75 535" } { "classname" "info_monster_start" "origin" "-487.875 -442.5 531" } { "classname" "info_monster_start" "origin" "-570.875 -357.25 253" } { "classname" "info_monster_start" "origin" "-492.375 -260.75 253" } { "classname" "info_monster_start" "origin" "-355.375 -399.375 253" } { "classname" "info_monster_start" "origin" "-116.625 -494.25 253" } { "classname" "info_monster_start" "origin" "-131.625 -251.5 253" } { "classname" "info_monster_start" "origin" "54.75 -150 253" } { "classname" "info_monster_start" "origin" "137.25 28.25 253" } { "classname" "info_monster_start" "origin" "41.125 246.625 253" } { "classname" "info_teleport_destination" "targetname" "bottom_1" "angle" "-157" "origin" "411 195 253" } { "classname" "trigger_custom_teleport" "origin" "870 340 535" "size" "50 50 50" "target" "bottom_1" } { "classname" "info_teleport_destination" "targetname" "bottom_2" "angle" "117" "origin" "76 -393 253" } { "classname" "trigger_custom_teleport" "origin" "295 -910 536" "size" "50 50 50" "target" "bottom_2" } { "classname" "info_teleport_destination" "targetname" "bottom_3" "angle" "18" "origin" "-638 -123 253" } { "classname" "trigger_custom_teleport" "origin" "-1100 -350 536" "size" "50 50 50" "target" "bottom_3" } { "classname" "info_teleport_destination" "targetname" "bottom_4" "angle" "-64" "origin" "-278 343 253" } { "classname" "trigger_custom_teleport" "origin" "-580 970 536" "size" "50 50 50" "target" "bottom_4" } { "classname" "info_teleport_destination" "targetname" "rl_center" "origin" "-159 54 270" } { "classname" "trigger_custom_teleport" "origin" "-375 566 746" "size" "100 100 100" "target" "rl_center" } { "classname" "info_player_deathmatch" "angle" "24" "origin" "724 268 535" } { "classname" "info_player_deathmatch" "angle" "-64" "origin" "210 -729 535" } { "classname" "info_player_deathmatch" "angle" "-153" "origin" "-935 -263 535" } { "classname" "info_player_deathmatch" "angle" "112" "origin" "-491 791 535" } { "classname" "info_player_deathmatch" "angle" "-109" "origin" "178 838 535" } { "classname" "info_player_deathmatch" "angle" "157" "origin" "648 -258 535" } { "classname" "info_player_deathmatch" "angle" "70" "origin" "-402 -695 535" } { "classname" "info_player_deathmatch" "angle" "-21" "origin" "-893 383 535" } { "classname" "trigger_custom_monsterjump" "origin" "350 -154 253" "size" "100 100 64" "angle" "-23" "speed" "300" "height" "800" } { "classname" "trigger_custom_monsterjump" "origin" "-560 213 253" "size" "100 100 64" "angle" "154" "speed" "300" "height" "800" } { "classname" "trigger_custom_monsterjump" "origin" "-302 -641 535" "size" "75 75 75" "angle" "70" "speed" "200" "height" "200" } { "classname" "trigger_custom_monsterjump" "origin" "102 689 535" "size" "75 75 75" "angle" "-112" "speed" "200" "height" "200" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/barrel.ent000066400000000000000000000476621475442401000251360ustar00rootroot00000000000000{ "message" "Da Barrello ..." "wad" "D:\GAMES\QUAKE\EDITORS\Qoole\work\barrel.wad" "classname" "worldspawn" } { "model" "*1" "height" "496" "speed" "300" "classname" "func_plat" } { "light" "200" "origin" "704 160 -128" "classname" "light" } { "light" "180" "origin" "720 80 -192" "classname" "light" } { "light" "120" "origin" "704 160 -16" "classname" "light" } { "light" "120" "origin" "704 160 96" "classname" "light" } { "light" "120" "origin" "704 160 192" "classname" "light" } { "light" "120" "origin" "704 160 304" "classname" "light" } { "light" "250" "origin" "544 0 304" "classname" "light" } { "light" "150" "origin" "-704 -160 48" "classname" "light" } { "light" "200" "origin" "-624 0 48" "classname" "light" } { "light" "150" "origin" "-528 -400 48" "classname" "light" } { "light" "150" "origin" "-608 -384 48" "classname" "light" } { "light" "150" "origin" "-704 -272 48" "classname" "light" } { "light" "150" "origin" "-688 -368 48" "classname" "light" } { "light" "150" "origin" "-704 -48 48" "classname" "light" } { "light" "200" "origin" "-448 -400 48" "classname" "light" } { "light" "100" "origin" "-560 -288 32" "classname" "light" } { "light" "250" "origin" "-368 -384 48" "classname" "light" } { "light" "100" "origin" "-608 -176 32" "classname" "light" } { "light" "250" "origin" "-528 0 48" "classname" "light" } { "light" "150" "origin" "-720 16 48" "classname" "light" } { "light" "150" "origin" "-448 608 176" "classname" "light" } { "light" "150" "origin" "-368 704 176" "classname" "light" } { "light" "150" "origin" "-240 720 176" "classname" "light" } { "light" "150" "origin" "-128 704 176" "classname" "light" } { "light" "200" "origin" "-432 480 176" "classname" "light" } { "light" "250" "origin" "-352 400 176" "classname" "light" } { "light" "250" "origin" "0 528 240" "classname" "light" } { "light" "200" "origin" "0 656 224" "classname" "light" } { "light" "150" "origin" "-32 736 208" "classname" "light" } { "light" "100" "origin" "-304 544 160" "classname" "light" } { "light" "100" "origin" "-176 592 160" "classname" "light" } { "light" "150" "origin" "656 32 304" "classname" "light" } { "light" "150" "origin" "656 -64 304" "classname" "light" } { "light" "150" "origin" "768 -32 304" "classname" "light" } { "light" "500" "origin" "-205 216 768" "classname" "light" } { "light" "500" "origin" "0 288 768" "classname" "light" } { "light" "500" "origin" "205 216 768" "classname" "light" } { "light" "500" "origin" "274 0 768" "classname" "light" } { "light" "500" "origin" "205 -216 768" "classname" "light" } { "light" "500" "origin" "0 -288 768" "classname" "light" } { "light" "500" "origin" "-205 -216 768" "classname" "light" } { "light" "500" "origin" "-274 0 768" "classname" "light" } { "light" "500" "origin" "-32 30 576" "classname" "light" } { "light" "500" "origin" "0 41 576" "classname" "light" } { "light" "500" "origin" "32 30 576" "classname" "light" } { "light" "500" "origin" "43 0 576" "classname" "light" } { "light" "500" "origin" "32 -30 576" "classname" "light" } { "light" "500" "origin" "0 -41 576" "classname" "light" } { "light" "500" "origin" "-32 -30 576" "classname" "light" } { "light" "500" "origin" "-43 0 576" "classname" "light" } { "light" "400" "origin" "-134 129 256" "classname" "light" } { "light" "400" "origin" "0 172 256" "classname" "light" } { "light" "400" "origin" "134 129 256" "classname" "light" } { "light" "400" "origin" "179 0 256" "classname" "light" } { "light" "400" "origin" "134 -129 256" "classname" "light" } { "light" "400" "origin" "0 -172 256" "classname" "light" } { "light" "400" "origin" "-134 -129 256" "classname" "light" } { "light" "400" "origin" "-179 0 256" "classname" "light" } { "light" "400" "origin" "-176 171 256" "classname" "light" } { "light" "400" "origin" "0 228 256" "classname" "light" } { "light" "400" "origin" "176 171 256" "classname" "light" } { "light" "400" "origin" "235 0 256" "classname" "light" } { "light" "400" "origin" "176 -171 256" "classname" "light" } { "light" "400" "origin" "0 -228 256" "classname" "light" } { "light" "400" "origin" "-176 -171 256" "classname" "light" } { "light" "400" "origin" "-235 0 256" "classname" "light" } { "light" "500" "origin" "-96 96 384" "classname" "light" } { "light" "500" "origin" "0 128 384" "classname" "light" } { "light" "500" "origin" "96 96 384" "classname" "light" } { "light" "500" "origin" "128 0 384" "classname" "light" } { "light" "500" "origin" "96 -96 384" "classname" "light" } { "light" "500" "origin" "0 -128 384" "classname" "light" } { "light" "500" "origin" "-96 -96 384" "classname" "light" } { "light" "500" "origin" "-128 0 384" "classname" "light" } { "light" "200" "origin" "-383 196 64" "classname" "light" } { "light" "200" "origin" "-143 394 64" "classname" "light" } { "light" "200" "origin" "167 396 64" "classname" "light" } { "light" "200" "origin" "367 133 64" "classname" "light" } { "light" "200" "origin" "383 -196 64" "classname" "light" } { "light" "200" "origin" "143 -394 64" "classname" "light" } { "light" "200" "origin" "-167 -396 64" "classname" "light" } { "light" "200" "origin" "-367 -133 64" "classname" "light" } { "light" "200" "origin" "-315 315 64" "classname" "light" } { "light" "200" "origin" "0 419 64" "classname" "light" } { "light" "200" "origin" "315 315 64" "classname" "light" } { "light" "200" "origin" "419 0 64" "classname" "light" } { "light" "200" "origin" "315 -315 64" "classname" "light" } { "light" "200" "origin" "0 -419 64" "classname" "light" } { "light" "200" "origin" "-315 -315 64" "classname" "light" } { "light" "200" "origin" "-419 0 64" "classname" "light" } { "light" "200" "origin" "-394 106 -80" "classname" "light" } { "light" "200" "origin" "-201 329 -80" "classname" "light" } { "light" "200" "origin" "92 388 -80" "classname" "light" } { "light" "200" "origin" "324 188 -80" "classname" "light" } { "light" "200" "origin" "394 -106 -80" "classname" "light" } { "light" "200" "origin" "201 -329 -80" "classname" "light" } { "light" "200" "origin" "-92 -388 -80" "classname" "light" } { "light" "200" "origin" "-324 -188 -80" "classname" "light" } { "light" "200" "origin" "-283 287 -80" "classname" "light" } { "light" "200" "origin" "0 383 -80" "classname" "light" } { "light" "200" "origin" "283 287 -80" "classname" "light" } { "light" "200" "origin" "377 0 -80" "classname" "light" } { "light" "200" "origin" "283 -287 -80" "classname" "light" } { "light" "200" "origin" "0 -383 -80" "classname" "light" } { "light" "200" "origin" "-283 -287 -80" "classname" "light" } { "light" "200" "origin" "-377 0 -80" "classname" "light" } { "light" "200" "origin" "-393 -105 -80" "classname" "light" } { "light" "200" "origin" "-343 184 -80" "classname" "light" } { "light" "200" "origin" "-122 381 -80" "classname" "light" } { "light" "200" "origin" "181 324 -80" "classname" "light" } { "light" "200" "origin" "393 105 -80" "classname" "light" } { "light" "200" "origin" "343 -184 -80" "classname" "light" } { "light" "200" "origin" "122 -381 -80" "classname" "light" } { "light" "200" "origin" "-181 -324 -80" "classname" "light" } { "light" "200" "origin" "-91 94 -64" "classname" "light" } { "light" "200" "origin" "0 126 -64" "classname" "light" } { "light" "200" "origin" "91 94 -64" "classname" "light" } { "light" "200" "origin" "121 0 -64" "classname" "light" } { "light" "200" "origin" "91 -94 -64" "classname" "light" } { "light" "200" "origin" "0 -126 -64" "classname" "light" } { "light" "200" "origin" "-91 -94 -64" "classname" "light" } { "light" "200" "origin" "-121 0 -64" "classname" "light" } { "light" "200" "origin" "-110 224 -80" "classname" "light" } { "light" "200" "origin" "79 216 -80" "classname" "light" } { "light" "200" "origin" "228 101 -80" "classname" "light" } { "light" "200" "origin" "225 -82 -80" "classname" "light" } { "light" "200" "origin" "110 -224 -80" "classname" "light" } { "light" "200" "origin" "-79 -216 -80" "classname" "light" } { "light" "200" "origin" "-228 -101 -80" "classname" "light" } { "light" "200" "origin" "-225 82 -80" "classname" "light" } { "light" "180" "origin" "736 -96 -192" "classname" "light" } { "light" "180" "origin" "720 -272 -192" "classname" "light" } { "light" "180" "origin" "576 -368 -192" "classname" "light" } { "light" "200" "origin" "400 -384 -192" "classname" "light" } { "angle" "90" "origin" "0 0 32" "classname" "info_player_start" } { "origin" "-384 192 -96" "classname" "item_armor2" } { "spawnflags" "1" "angle" "90" "origin" "-448 80 -112" "classname" "item_health" } { "spawnflags" "1" "angle" "90" "origin" "-448 32 -112" "classname" "item_health" } { "spawnflags" "1" "angle" "90" "origin" "-221 -307 -112" "classname" "item_cells" } { "spawnflags" "1" "angle" "90" "origin" "-285 -307 -112" "classname" "item_cells" } { "origin" "-368 -272 -96" "classname" "weapon_lightning" } { "spawnflags" "1" "angle" "90" "origin" "-720 -304 16" "classname" "item_health" } { "angle" "45" "origin" "-704 -384 48" "classname" "info_player_deathmatch" } { "spawnflags" "1" "angle" "90" "origin" "-720 -352 16" "classname" "item_health" } { "angle" "90" "origin" "-744 -232 16" "classname" "item_rockets" } { "angle" "225" "origin" "-560 -272 48" "classname" "info_player_deathmatch" } { "origin" "-640 -256 16" "classname" "weapon_grenadelauncher" } { "spawnflags" "1" "angle" "90" "origin" "-84 452 -112" "classname" "item_spikes" } { "spawnflags" "1" "angle" "90" "origin" "-36 452 -112" "classname" "item_spikes" } { "origin" "-96 352 -96" "classname" "weapon_supernailgun" } { "angle" "225" "origin" "80 448 -96" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "-240 560 160" "classname" "info_player_deathmatch" } { "origin" "-304 640 144" "classname" "weapon_rocketlauncher" } { "angle" "90" "origin" "-184 728 144" "classname" "item_rockets" } { "angle" "315" "origin" "-384 720 160" "classname" "info_player_deathmatch" } { "spawnflags" "1" "angle" "90" "origin" "-288 720 144" "classname" "item_health" } { "spawnflags" "1" "angle" "90" "origin" "-240 720 144" "classname" "item_health" } { "angle" "315" "origin" "-256 400 -96" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "368 144 -96" "classname" "item_health" } { "angle" "90" "origin" "368 16 -96" "classname" "item_health" } { "origin" "656 -320 -240" "classname" "item_armor1" } { "angle" "140" "origin" "800 -240 -224" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "664 -40 -224" "classname" "item_rockets" } { "origin" "736 -96 -224" "classname" "weapon_rocketlauncher" } { "angle" "220" "origin" "784 64 -224" "classname" "info_player_deathmatch" } { "origin" "128 320 224" "classname" "item_armorInv" } { "spawnflags" "1" "angle" "90" "origin" "688 -96 -224" "classname" "item_health" } { "spawnflags" "1" "angle" "90" "origin" "688 -144 -224" "classname" "item_health" } { "origin" "352 -80 -96" "classname" "weapon_supershotgun" } { "angle" "90" "origin" "428 -124 -96" "classname" "item_shells" } { "angle" "90" "origin" "428 -76 -96" "classname" "item_shells" } { "angle" "90" "origin" "-180 52 96" "classname" "item_shells" } { "mangle" "45 90 0" "origin" "0 -496 528" "classname" "info_intermission" } { "classname" "info_monster_start" "origin" "-109.625 -151.625 -103.875" } { "classname" "info_monster_start" "origin" "-15.875 -124.75 -103.875" } { "classname" "info_monster_start" "origin" "-12 -29.375 -103.875" } { "classname" "info_monster_start" "origin" "-251.25 -256.5 -95.875" } { "classname" "info_monster_start" "origin" "-301.5 -135.875 -103.875" } { "classname" "info_monster_start" "origin" "-309 -254.25 -95.875" } { "classname" "info_monster_start" "origin" "-369.25 -15 -103.875" } { "classname" "info_monster_start" "origin" "-456.75 -163.75 -95.875" } { "classname" "info_monster_start" "origin" "-495.875 -53.875 -103.875" } { "classname" "info_monster_start" "origin" "-313 81.25 -103.875" } { "classname" "info_monster_start" "origin" "-245.875 128.875 -103.875" } { "classname" "info_monster_start" "origin" "-148.5 153 -103.875" } { "classname" "info_monster_start" "origin" "-80.25 214.125 -103.875" } { "classname" "info_monster_start" "origin" "-3.875 164.5 -103.875" } { "classname" "info_monster_start" "origin" "1.125 287.125 -103.875" } { "classname" "info_monster_start" "origin" "-8 65.5 -103.875" } { "classname" "info_monster_start" "origin" "-20.875 -242.125 -103.875" } { "classname" "info_monster_start" "origin" "66.375 -242.5 -103.875" } { "classname" "info_monster_start" "origin" "208.875 -241.75 -95.875" } { "classname" "info_monster_start" "origin" "136.75 -77.625 -103.875" } { "classname" "info_monster_start" "origin" "137.875 16.5 -103.875" } { "classname" "info_monster_start" "origin" "138.875 102 -103.875" } { "classname" "info_monster_start" "origin" "175.125 203.875 -103.875" } { "classname" "info_monster_start" "origin" "176 297.125 -103.875" } { "classname" "info_monster_start" "origin" "212.75 389.875 -103.875" } { "classname" "info_monster_start" "origin" "366.75 321.125 -95.875" } { "classname" "info_monster_start" "origin" "271.5 169.75 -95.875" } { "classname" "info_monster_start" "origin" "126.25 369.5 216" } { "classname" "info_monster_start" "origin" "138.625 309.625 216" } { "classname" "info_monster_start" "origin" "405.75 5 280" } { "classname" "info_monster_start" "origin" "476 1.25 280" } { "classname" "info_monster_start" "origin" "555.625 -3 280" } { "classname" "info_monster_start" "origin" "615.5 -6.25 280" } { "classname" "info_monster_start" "origin" "675.25 -9.625 280" } { "classname" "info_monster_start" "origin" "741.625 -13.25 280" } { "classname" "info_monster_start" "origin" "799.875 -16.5 280" } { "classname" "info_monster_start" "origin" "85 431.25 216" } { "classname" "info_monster_start" "origin" "58.125 470.125 216" } { "classname" "info_monster_start" "origin" "12.125 536.875 216" } { "classname" "info_monster_start" "origin" "0.875 602.5 216" } { "classname" "info_monster_start" "origin" "-41.875 688 184" } { "classname" "info_monster_start" "origin" "-166.75 607.75 152" } { "classname" "info_monster_start" "origin" "-267.75 600.25 152" } { "classname" "info_monster_start" "origin" "-167.875 690.625 152" } { "classname" "info_monster_start" "origin" "-269.625 704.875 152" } { "classname" "info_monster_start" "origin" "-371.875 704.125 152" } { "classname" "info_monster_start" "origin" "-487.125 596.875 152" } { "classname" "info_monster_start" "origin" "-490.375 499.375 152" } { "classname" "info_monster_start" "origin" "-373.5 599.875 152" } { "classname" "info_monster_start" "origin" "-350.5 491.375 152" } { "classname" "info_monster_start" "origin" "-392.125 428.125 152" } { "classname" "info_monster_start" "origin" "-338.625 376 152" } { "classname" "info_monster_start" "origin" "-286.625 325.5 152" } { "classname" "info_monster_start" "origin" "-208.375 292.5 152" } { "classname" "info_monster_start" "origin" "-206 245 152" } { "classname" "info_monster_start" "origin" "-205 171.375 131.25" } { "classname" "info_monster_start" "origin" "-204 102 88" } { "classname" "info_monster_start" "origin" "-203.125 41.375 88" } { "classname" "info_monster_start" "origin" "-274.5 35.25 88" } { "classname" "info_monster_start" "origin" "-356.375 28.125 56" } { "classname" "info_monster_start" "origin" "-723.25 7.5 24" } { "classname" "info_monster_start" "origin" "-659.375 -424 24" } { "classname" "info_monster_start" "origin" "-732 -305.625 24" } { "classname" "info_monster_start" "origin" "-648.625 -310.625 24" } { "classname" "info_monster_start" "origin" "-723.5 -214 24" } { "classname" "info_monster_start" "origin" "-732 -84.5 24" } { "classname" "info_monster_start" "origin" "-656.375 2.5 24" } { "classname" "info_monster_start" "origin" "-667.75 -56.25 24" } { "classname" "info_monster_start" "origin" "-592 -114.25 24" } { "classname" "info_monster_start" "origin" "-649.5 -168.375 24" } { "classname" "info_monster_start" "origin" "-553.875 -226.875 24" } { "classname" "info_monster_start" "origin" "-502.125 -349.875 24" } { "classname" "info_monster_start" "origin" "-386.375 -373.375 24" } { "classname" "info_monster_start" "origin" "-279.375 -378.375 24" } { "classname" "info_monster_start" "origin" "-235.625 -382.375 8" } { "classname" "info_monster_start" "origin" "-150 -390.25 -23.875" } { "classname" "info_monster_start" "origin" "398.25 -396.125 -231.875" } { "classname" "info_monster_start" "origin" "477.375 -376.75 -231.875" } { "classname" "info_monster_start" "origin" "568.625 -379.75 -231.875" } { "classname" "info_monster_start" "origin" "635 -337.75 -231.875" } { "classname" "info_monster_start" "origin" "689.875 -292.125 -231.875" } { "classname" "info_monster_start" "origin" "751.125 -241.125 -231.875" } { "classname" "info_monster_start" "origin" "756.75 -151.5 -231.875" } { "classname" "info_monster_start" "origin" "752.75 -75 -231.875" } { "classname" "info_monster_start" "origin" "748 15.25 -231.875" } { "classname" "info_monster_start" "origin" "745.125 68.5 -231.875" } { "classname" "info_monster_start" "origin" "304.25 -387.5 -199.875" } { "classname" "info_monster_start" "origin" "212 -379 -151.875" } { "classname" "info_monster_start" "origin" "410 -245.25 -95.875" } { "classname" "info_monster_start" "origin" "336 -244 -95.875" } { "classname" "info_monster_start" "origin" "330.875 265.875 -95.875" } { "classname" "info_monster_start" "origin" "422.125 193.125 -87.875" } { "classname" "info_monster_start" "origin" "407 181.875 -87.875" } { "classname" "info_monster_start" "origin" "408.875 122.125 -87.875" } { "classname" "info_monster_start" "origin" "417.75 119.5 -87.875" } { "classname" "info_monster_start" "origin" "410.625 67.875 -87.875" } { "classname" "info_monster_start" "origin" "413.75 51.375 -87.875" } { "classname" "info_monster_start" "origin" "412.375 11.375 -87.875" } { "classname" "info_monster_start" "origin" "414 -40.375 -87.875" } { "classname" "info_monster_start" "origin" "437 -37.625 -87.875" } { "classname" "info_monster_start" "origin" "441.625 -133.375 -87.875" } { "classname" "info_monster_start" "origin" "437.875 -132.25 -87.875" } { "classname" "info_monster_start" "origin" "273.25 110.875 -95.875" } { "classname" "info_monster_start" "origin" "275.25 44 -95.875" } { "classname" "info_monster_start" "origin" "277.75 -36.75 -95.875" } { "classname" "info_monster_start" "origin" "279.625 -96.75 -95.875" } { "classname" "info_monster_start" "origin" "281.375 -152.5 -95.875" } { "classname" "info_monster_start" "origin" "273.75 -242.875 -95.875" } { "classname" "info_monster_start" "origin" "69.375 -393.25 -95.875" } { "classname" "info_monster_start" "origin" "-17.125 -402.5 -79" } { "classname" "info_monster_start" "origin" "-101.625 -394.75 -55.875" } { "classname" "info_monster_start" "origin" "-148.5 -260.625 -95.875" } { "classname" "info_monster_start" "origin" "-195.375 -258.75 -95.875" } { "classname" "info_monster_start" "origin" "-374.625 -251.625 -95.875" } { "classname" "info_monster_start" "origin" "-422.5 -249.75 -95.875" } { "classname" "info_monster_start" "origin" "-586.25 8.5 24" } { "classname" "info_monster_start" "origin" "-514 14.625 24" } { "classname" "info_monster_start" "origin" "-442.125 20.875 24" } { "classname" "info_monster_start" "origin" "-447.875 70.75 -95.875" } { "classname" "info_monster_start" "origin" "-419 132.875 -95.875" } { "classname" "info_monster_start" "origin" "-389.875 195.875 -95.875" } { "classname" "info_monster_start" "origin" "-358.75 263.125 -95.875" } { "classname" "info_monster_start" "origin" "-145.125 422 -95.875" } { "classname" "info_monster_start" "origin" "-75 404.625 -95.875" } { "classname" "info_monster_start" "origin" "-119.25 327.5 -95.875" } { "classname" "info_monster_start" "origin" "-233.5 379.875 -95.875" } { "classname" "info_monster_start" "origin" "-299.125 331.125 -95.875" } { "classname" "info_monster_start" "origin" "-262.75 248.375 -95.875" } { "classname" "info_teleport_destination" "targetname" "lame_place" "origin" "48 42 -104" "angle" "0" } { "classname" "trigger_custom_teleport" "origin" "540 -2.5 280" "size" "50 50 50" "target" "lame_place" } { "classname" "trigger_custom_teleport" "origin" "391 -384 -232" "size" "50 50 50" "target" "lame_place" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/bloodfest.ent000066400000000000000000000412611475442401000256350ustar00rootroot00000000000000{ "classname" "worldspawn" "message" "Blood fest!" } { "origin" "0 64 1408" "classname" "info_player_deathmatch" } { "origin" "1343 -1345 -1479" "angle" "132" "classname" "info_player_deathmatch" } { "origin" "1133 -1487 -1479" "angle" "131" "classname" "info_player_deathmatch" } { "origin" "1210 -1150 -1479" "angle" "135" "classname" "info_player_deathmatch" } { "origin" "1463 -919 -1479" "angle" "140" "classname" "info_player_deathmatch" } { "origin" "1488 -1112 -1479" "angle" "180" "classname" "info_player_deathmatch" } { "origin" "1275 -1487 -1479" "angle" "100" "classname" "info_player_deathmatch" } { "origin" "1467 -1467 -1479" "angle" "135" "classname" "info_player_deathmatch" } { "origin" "964 -1487 -1479" "angle" "96" "classname" "info_player_deathmatch" } { "origin" "1459 -754 -1479" "angle" "180" "classname" "info_player_deathmatch" } { "classname" "info_monster_start" "origin" "309 -439.25 -1479.88" } { "classname" "info_monster_start" "origin" "222.5 -439.375 -1479.88" } { "classname" "info_monster_start" "origin" "123.125 -439.375 -1479.88" } { "classname" "info_monster_start" "origin" "27 -439.5 -1479.88" } { "classname" "info_monster_start" "origin" "-86.125 -439.625 -1479.88" } { "classname" "info_monster_start" "origin" "-182.125 -439.625 -1479.88" } { "classname" "info_monster_start" "origin" "-271.375 -396.5 -1479.88" } { "classname" "info_monster_start" "origin" "-269.5 -290.75 -1479.88" } { "classname" "info_monster_start" "origin" "-267.5 -173.875 -1479.88" } { "classname" "info_monster_start" "origin" "-265.5 -64.125 -1479.88" } { "classname" "info_monster_start" "origin" "-263.5 45.25 -1479.88" } { "classname" "info_monster_start" "origin" "-261.375 166.875 -1479.88" } { "classname" "info_monster_start" "origin" "-259.75 262.375 -1479.88" } { "classname" "info_monster_start" "origin" "-139 341.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1.875 339.375 -1479.88" } { "classname" "info_monster_start" "origin" "103.25 337.75 -1479.88" } { "classname" "info_monster_start" "origin" "217.375 336 -1479.88" } { "classname" "info_monster_start" "origin" "323.125 334.375 -1479.88" } { "classname" "info_monster_start" "origin" "399.5 280.5 -1479.88" } { "classname" "info_monster_start" "origin" "401.75 210.125 -1479.88" } { "classname" "info_monster_start" "origin" "406 82.75 -1479.88" } { "classname" "info_monster_start" "origin" "410.25 -47.125 -1479.88" } { "classname" "info_monster_start" "origin" "414.25 -169.625 -1479.88" } { "classname" "info_monster_start" "origin" "417.875 -278.875 -1479.88" } { "classname" "info_monster_start" "origin" "421.125 -378.5 -1479.88" } { "classname" "info_monster_start" "origin" "413.875 -611.75 -1479.88" } { "classname" "info_monster_start" "origin" "690.75 -380.125 -1479.88" } { "classname" "info_monster_start" "origin" "691.5 -558.25 -1479.88" } { "classname" "info_monster_start" "origin" "254.25 -612.625 -1479.88" } { "classname" "info_monster_start" "origin" "692.25 -715.75 -1479.88" } { "classname" "info_monster_start" "origin" "270.125 -988.5 -1479.88" } { "classname" "info_monster_start" "origin" "798.125 -993.125 -1479.88" } { "classname" "info_monster_start" "origin" "83.25 -986.875 -1479.88" } { "classname" "info_monster_start" "origin" "-112.125 -985.125 -1479.88" } { "classname" "info_monster_start" "origin" "-294.875 -983.5 -1479.88" } { "classname" "info_monster_start" "origin" "-485.875 -981.75 -1479.88" } { "classname" "info_monster_start" "origin" "-673.125 -980.125 -1479.88" } { "classname" "info_monster_start" "origin" "-860 -978.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1005.75 -977.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1105.38 -971 -1479.88" } { "classname" "info_monster_start" "origin" "-1107.5 -847 -1479.88" } { "classname" "info_monster_start" "origin" "-1109.75 -707.625 -1479.88" } { "classname" "info_monster_start" "origin" "-1110.62 -589.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1097.75 -433.375 -1479.88" } { "classname" "info_monster_start" "origin" "-1095.12 -290.375 -1479.88" } { "classname" "info_monster_start" "origin" "-1097.88 -131.125 -1479.88" } { "classname" "info_monster_start" "origin" "-1100.62 27.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1103.75 204.875 -1479.88" } { "classname" "info_monster_start" "origin" "-1106.38 360.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1109.25 526.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1112.25 698.125 -1479.88" } { "classname" "info_monster_start" "origin" "-1115.38 878.125 -1479.88" } { "classname" "info_monster_start" "origin" "-1117.75 1017.12 -1479.88" } { "classname" "info_monster_start" "origin" "-1018.25 1124.25 -1479.88" } { "classname" "info_monster_start" "origin" "-760.75 1117.75 -1479.88" } { "classname" "info_monster_start" "origin" "-574 1113 -1479.88" } { "classname" "info_monster_start" "origin" "-357.75 1107.62 -1479.88" } { "classname" "info_monster_start" "origin" "-145.875 1102.38 -1479.88" } { "classname" "info_monster_start" "origin" "57.5 1098.88 -1479.88" } { "classname" "info_monster_start" "origin" "266.625 1116.25 -1479.88" } { "classname" "info_monster_start" "origin" "431.375 1115.38 -1479.88" } { "classname" "info_monster_start" "origin" "612.75 1135.5 -1479.88" } { "classname" "info_monster_start" "origin" "792.75 1134.5 -1479.88" } { "classname" "info_monster_start" "origin" "944.625 1130.62 -1479.88" } { "classname" "info_monster_start" "origin" "1061.75 1127.75 -1479.88" } { "classname" "info_monster_start" "origin" "1163.88 992.125 -1479.88" } { "classname" "info_monster_start" "origin" "1172.62 845.625 -1479.88" } { "classname" "info_monster_start" "origin" "1181 702.625 -1479.88" } { "classname" "info_monster_start" "origin" "1187.38 571 -1479.88" } { "classname" "info_monster_start" "origin" "1173.5 407.25 -1479.88" } { "classname" "info_monster_start" "origin" "1170.75 295.875 -1479.88" } { "classname" "info_monster_start" "origin" "1179.25 151.625 -1479.88" } { "classname" "info_monster_start" "origin" "1187.5 5.25 -1479.88" } { "classname" "info_monster_start" "origin" "1181.12 -143.375 -1479.88" } { "classname" "info_monster_start" "origin" "1159.75 -281 -1479.88" } { "classname" "info_monster_start" "origin" "1168.75 -434.25 -1479.88" } { "classname" "info_monster_start" "origin" "1177.38 -593.875 -1479.88" } { "classname" "info_monster_start" "origin" "1139.25 -1434.12 -1479.88" } { "classname" "info_monster_start" "origin" "1029.88 -1435.12 -1479.88" } { "classname" "info_monster_start" "origin" "1457.62 -1253 -1479.88" } { "classname" "info_monster_start" "origin" "1457.5 -1363.12 -1479.88" } { "classname" "info_monster_start" "origin" "1457.38 -1449 -1479.88" } { "classname" "info_monster_start" "origin" "1457.75 -1148.5 -1479.88" } { "classname" "info_monster_start" "origin" "1457.75 -1051.75 -1479.88" } { "classname" "info_monster_start" "origin" "1457.88 -945.375 -1479.88" } { "classname" "info_monster_start" "origin" "1458 -833.75 -1479.88" } { "classname" "info_monster_start" "origin" "1458.12 -725.75 -1479.88" } { "classname" "info_monster_start" "origin" "1458.25 -621 -1479.88" } { "classname" "info_monster_start" "origin" "1458.38 -515.125 -1479.88" } { "classname" "info_monster_start" "origin" "1458.38 -413.125 -1479.88" } { "classname" "info_monster_start" "origin" "1458.5 -299.375 -1479.88" } { "classname" "info_monster_start" "origin" "1458.62 -189.875 -1479.88" } { "classname" "info_monster_start" "origin" "1458.75 -95.625 -1479.88" } { "classname" "info_monster_start" "origin" "1458.88 10.5 -1479.88" } { "classname" "info_monster_start" "origin" "1458.88 120.375 -1479.88" } { "classname" "info_monster_start" "origin" "1459 229.125 -1479.88" } { "classname" "info_monster_start" "origin" "1459.12 337.75 -1479.88" } { "classname" "info_monster_start" "origin" "1459.25 449 -1479.88" } { "classname" "info_monster_start" "origin" "1459.38 562.25 -1479.88" } { "classname" "info_monster_start" "origin" "1459.5 666.5 -1479.88" } { "classname" "info_monster_start" "origin" "1459.5 772.75 -1479.88" } { "classname" "info_monster_start" "origin" "1459.62 881.625 -1479.88" } { "classname" "info_monster_start" "origin" "1459.75 974.25 -1479.88" } { "classname" "info_monster_start" "origin" "1459.88 1077.5 -1479.88" } { "classname" "info_monster_start" "origin" "1460 1174.75 -1479.88" } { "classname" "info_monster_start" "origin" "1460 1270.5 -1479.88" } { "classname" "info_monster_start" "origin" "1460.12 1389 -1479.88" } { "classname" "info_monster_start" "origin" "1460.25 1451.38 -1479.88" } { "classname" "info_monster_start" "origin" "1377.75 1451.62 -1479.88" } { "classname" "info_monster_start" "origin" "1298.5 1450 -1479.88" } { "classname" "info_monster_start" "origin" "1189 1447.75 -1479.88" } { "classname" "info_monster_start" "origin" "1091.25 1445.75 -1479.88" } { "classname" "info_monster_start" "origin" "1002.75 1443.88 -1479.88" } { "classname" "info_monster_start" "origin" "900.25 1441.75 -1479.88" } { "classname" "info_monster_start" "origin" "789.75 1439.5 -1479.88" } { "classname" "info_monster_start" "origin" "687.5 1437.38 -1479.88" } { "classname" "info_monster_start" "origin" "579.625 1435.12 -1479.88" } { "classname" "info_monster_start" "origin" "481.5 1433 -1479.88" } { "classname" "info_monster_start" "origin" "391.125 1431.25 -1479.88" } { "classname" "info_monster_start" "origin" "284.875 1446.38 -1479.88" } { "classname" "info_monster_start" "origin" "198.125 1446.25 -1479.88" } { "classname" "info_monster_start" "origin" "96.125 1444.12 -1479.88" } { "classname" "info_monster_start" "origin" "2.375 1442.12 -1479.88" } { "classname" "info_monster_start" "origin" "-105.75 1440 -1479.88" } { "classname" "info_monster_start" "origin" "-199.625 1438 -1479.88" } { "classname" "info_monster_start" "origin" "-300 1435.88 -1479.88" } { "classname" "info_monster_start" "origin" "-404.75 1433.75 -1479.88" } { "classname" "info_monster_start" "origin" "-481.875 1432.12 -1479.88" } { "classname" "info_monster_start" "origin" "-582.5 1430.12 -1479.88" } { "classname" "info_monster_start" "origin" "-752.25 1468.38 -1479.88" } { "classname" "info_monster_start" "origin" "-830 1471.5 -1479.88" } { "classname" "info_monster_start" "origin" "-917.875 1469.62 -1479.88" } { "classname" "info_monster_start" "origin" "-1009.62 1467.75 -1479.88" } { "classname" "info_monster_start" "origin" "-1102.88 1465.88 -1479.88" } { "classname" "info_monster_start" "origin" "-1181.12 1464.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1273 1462.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1350.88 1460.62 -1479.88" } { "classname" "info_monster_start" "origin" "-1435.38 1458.88 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.75 1371.75 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.62 1281.88 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.5 1168.62 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.38 1055 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.25 935.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1434.12 816.625 -1479.88" } { "classname" "info_monster_start" "origin" "-1434 707.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.88 600.75 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.75 499.625 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.62 390.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.5 283.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.38 172.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.25 61.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1433.12 -51.375 -1479.88" } { "classname" "info_monster_start" "origin" "-1433 -162.75 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.88 -276.375 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.75 -385.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.62 -476.75 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.5 -579.375 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.38 -683 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.25 -801.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1432.12 -906.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1432 -1014.38 -1479.88" } { "classname" "info_monster_start" "origin" "-1431.88 -1120.25 -1479.88" } { "classname" "info_monster_start" "origin" "-1431.75 -1232.88 -1479.88" } { "classname" "info_monster_start" "origin" "-1431.62 -1321.88 -1479.88" } { "classname" "info_monster_start" "origin" "-1431.5 -1436.62 -1479.88" } { "classname" "info_monster_start" "origin" "-1324.25 -1456.12 -1479.88" } { "classname" "info_monster_start" "origin" "-1249.5 -1455.5 -1479.88" } { "classname" "info_monster_start" "origin" "-1127.25 -1454.38 -1479.88" } { "classname" "info_monster_start" "origin" "-1024.38 -1453.5 -1479.88" } { "classname" "info_monster_start" "origin" "-912.75 -1452.5 -1479.88" } { "classname" "info_monster_start" "origin" "-812 -1451.62 -1479.88" } { "classname" "info_monster_start" "origin" "-705.875 -1450.62 -1479.88" } { "classname" "info_monster_start" "origin" "-590.75 -1449.62 -1479.88" } { "classname" "info_monster_start" "origin" "-470.125 -1448.5 -1479.88" } { "classname" "info_monster_start" "origin" "-368.75 -1447.62 -1479.88" } { "classname" "info_monster_start" "origin" "-242.125 -1446.5 -1479.88" } { "classname" "info_monster_start" "origin" "-125.5 -1445.5 -1479.88" } { "classname" "info_monster_start" "origin" "-30.375 -1444.62 -1479.88" } { "classname" "info_monster_start" "origin" "99.625 -1443.5 -1479.88" } { "classname" "info_monster_start" "origin" "219.125 -1442.38 -1479.88" } { "classname" "info_monster_start" "origin" "342.375 -1441.25 -1479.88" } { "classname" "info_monster_start" "origin" "462.25 -1440.25 -1479.88" } { "classname" "info_monster_start" "origin" "583.875 -1439.12 -1479.88" } { "classname" "info_monster_start" "origin" "1346.5 -1432.38 -1479.88" } { "classname" "info_monster_start" "origin" "1239.88 -1433.25 -1479.88" } { "classname" "info_monster_start" "origin" "904.875 -1436.25 -1479.88" } { "classname" "info_monster_start" "origin" "818.375 -1437 -1479.88" } { "classname" "info_monster_start" "origin" "699.25 -1438.12 -1479.88" } { "classname" "info_monster_start" "origin" "1183.38 -1217.75 -1479.88" } { "classname" "info_monster_start" "origin" "1174.38 -1065.25 -1479.88" } { "classname" "info_monster_start" "origin" "1165.62 -916.75 -1479.88" } { "classname" "info_monster_start" "origin" "1170.5 -740.375 -1479.88" } { "classname" "info_monster_start" "origin" "453.125 -990.125 -1479.88" } { "classname" "info_monster_start" "origin" "640 -991.75 -1479.88" } { "classname" "info_monster_start" "origin" "689.75 -194.625 -1479.88" } { "classname" "info_monster_start" "origin" "689 -27.625 -1479.88" } { "classname" "info_monster_start" "origin" "688.25 118.25 -1479.88" } { "classname" "info_monster_start" "origin" "687.5 276 -1479.88" } { "classname" "info_monster_start" "origin" "686.875 416.125 -1479.88" } { "classname" "info_monster_start" "origin" "685.75 641.75 -1479.88" } { "classname" "info_monster_start" "origin" "590.625 660.875 -1479.88" } { "classname" "info_monster_start" "origin" "447.25 663.75 -1479.88" } { "classname" "info_monster_start" "origin" "285.625 667 -1479.88" } { "classname" "info_monster_start" "origin" "135.125 670 -1479.88" } { "classname" "info_monster_start" "origin" "-19.125 673.125 -1479.88" } { "classname" "info_monster_start" "origin" "-151.5 675.75 -1479.88" } { "classname" "info_monster_start" "origin" "-286 678.5 -1479.88" } { "classname" "info_monster_start" "origin" "-416.25 681.125 -1479.88" } { "classname" "info_monster_start" "origin" "-616.625 685.125 -1479.88" } { "classname" "info_monster_start" "origin" "-657.5 579 -1479.88" } { "classname" "info_monster_start" "origin" "-658.125 434.5 -1479.88" } { "classname" "info_monster_start" "origin" "-658.875 277.375 -1479.88" } { "classname" "info_monster_start" "origin" "-659.625 134.125 -1479.88" } { "classname" "info_monster_start" "origin" "-660.25 -13.625 -1479.88" } { "classname" "info_monster_start" "origin" "-661 -158.75 -1479.88" } { "classname" "info_monster_start" "origin" "-661.5 -284.5 -1479.88" } { "classname" "info_monster_start" "origin" "-662.125 -403.875 -1479.88" } { "classname" "info_monster_start" "origin" "-662.875 -561.625 -1479.88" } { "classname" "info_monster_start" "origin" "-584.625 -617.5 -1479.88" } { "classname" "info_monster_start" "origin" "-447.875 -616.75 -1479.88" } { "classname" "info_monster_start" "origin" "-287.875 -615.75 -1479.88" } { "classname" "info_monster_start" "origin" "-157.625 -615 -1479.88" } { "classname" "info_monster_start" "origin" "-14.875 -614.25 -1479.88" } { "classname" "info_monster_start" "origin" "119.25 -613.375 -1479.88" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/000077500000000000000000000000001475442401000237145ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm1.ent000066400000000000000000000233561475442401000251160ustar00rootroot00000000000000{ "sounds" "5" "worldtype" "0" "wad" "gfx/medieval.wad" "classname" "worldspawn" "message" "Place of Two Deaths" } { "classname" "light" "origin" "220 1308 128" "angle" "0" "light" "200" } { "classname" "light" "origin" "28 1308 128" "angle" "0" "light" "200" } { "classname" "light" "origin" "36 996 128" "angle" "0" "light" "200" } { "classname" "light" "origin" "132 1156 296" "angle" "0" "light" "200" } { "classname" "light" "origin" "4 1148 296" "angle" "0" "light" "200" } { "classname" "light" "origin" "72 1152 112" "angle" "0" "light" "200" } { "classname" "light" "origin" "-56 1252 120" "angle" "0" "light" "150" } { "classname" "light" "origin" "-48 1060 120" "angle" "0" "light" "150" } { "classname" "info_player_start" "origin" "324 1156 24" "angle" "180" } { "classname" "light" "light" "250" "origin" "444 1348 84" "angle" "0" } { "classname" "light" "light" "250" "origin" "448 1528 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "292 1556 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "92 1556 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "-108 1548 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "36 1396 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "196 1404 88" "angle" "0" } { "classname" "light" "light" "200" "origin" "0 1504 224" "angle" "0" } { "classname" "light" "light" "200" "origin" "132 1500 224" "angle" "0" } { "classname" "light" "origin" "-224 1496 -72" "light" "200" } { "classname" "light" "origin" "224 1600 -80" "style" "2" } //{ //"angle" "-2" //"classname" "func_door" //"targetname" "t2" //"model" "*1" //} //{ //"sounds" "4" //"angle" "-2" //"classname" "func_door" //"targetname" "t2" //"model" "*2" //} { "classname" "light" "origin" "-128 1432 136" "light" "200" } { "classname" "light" "origin" "-416 1420 84" "light" "200" } { "classname" "light" "origin" "-520 736 136" } { "targetname" "t1" //"angle" "90" "origin" "178 1174 -120" //Q-Man "classname" "info_teleport_destination" "light" "250" } { "target" "t1" "classname" "trigger_teleport" "model" "*3" } { "classname" "light" "origin" "-320 1216 136" } { "classname" "func_door_secret" "angle" "180" "model" "*4" } //{ //"classname" "func_button" //"target" "t2" //"model" "*5" //} { "classname" "light_flame_large_yellow" "origin" "494 1582 220" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "494 1454 220" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "494 1326 220" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "494 1198 220" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "494 1070 220" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "238 1646 220" } { "classname" "light_flame_large_yellow" "origin" "-178 1646 220" } { "classname" "light_flame_large_yellow" "origin" "-178 1374 220" } { "classname" "light_flame_large_yellow" "origin" "238 1378 220" } { "classname" "light_torch_small_walltorch" "origin" "1146 1322 108" } { "classname" "light_torch_small_walltorch" "origin" "1146 1054 108" } { "classname" "light_torch_small_walltorch" "origin" "606 794 60" } { "classname" "light_torch_small_walltorch" "origin" "750 1442 60" } { "classname" "light" "origin" "1000 1320 116" "light" "200" } { "classname" "light" "origin" "1016 1012 136" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "1146 682 108" } { "classname" "light" "origin" "748 1284 260" } { "classname" "light" "origin" "748 1056 260" } { "classname" "light" "origin" "560 1208 112" "light" "250" } { "classname" "light" "origin" "560 1056 112" "light" "250" } { "classname" "light" "origin" "640 856 112" "light" "250" } { "classname" "light" "origin" "856 928 112" } { "classname" "light" "origin" "560 896 112" "light" "250" } { "classname" "light" "origin" "896 1232 72" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "610 542 60" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "410 542 60" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "274 542 60" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "138 542 60" "light" "225" } { "classname" "light" "origin" "224 992 128" "light" "250" } { "classname" "light" "origin" "304 1128 128" } { "classname" "light" "origin" "880 728 128" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "494 814 188" } { "classname" "light" "origin" "424 816 88" "light" "200" } { "classname" "light" "origin" "280 808 208" } { "classname" "light" "origin" "0 808 208" } { "classname" "light" "origin" "-304 816 208" } { "classname" "light" "origin" "-304 1056 208" } { "classname" "light_torch_small_walltorch" "origin" "386 990 -92" } { "classname" "light_torch_small_walltorch" "origin" "114 990 -92" } { "classname" "light_torch_small_walltorch" "origin" "-126 990 -92" } { "classname" "light_torch_small_walltorch" "origin" "274 1338 -92" } { "classname" "light" "origin" "488 1248 -92" "light" "200" } { "classname" "light" "origin" "-96 940 -116" "light" "225" } { "classname" "light" "origin" "48 976 -116" "light" "175" } { "classname" "light" "origin" "180 932 -116" "light" "225" } { "classname" "light" "origin" "452 928 -116" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "502 1654 -92" } { "classname" "light_torch_small_walltorch" "origin" "-114 1298 -92" } { "classname" "light_torch_small_walltorch" "origin" "314 1410 -92" } { "classname" "light" "origin" "-348 1076 -68" "light" "250" } { "classname" "light" "origin" "-348 768 -68" "light" "200" } { "classname" "light" "origin" "0 756 -68" "light" "200" } { "classname" "light" "origin" "488 720 -68" "light" "150" } { "classname" "light" "origin" "372 1328 -68" "light" "100" } { "classname" "light_torch_small_walltorch" "origin" "-518 1058 52" } { "classname" "light_torch_small_walltorch" "origin" "-658 934 60" } { "sounds" "4" "classname" "func_door" "angle" "180" "spawnflags" "1" "targetname" "t3" "speed" "175" "wait" "8" "model" "*6" } { "classname" "func_button" "target" "t3" "angle" "-2" "lip" "4" "wait" "10" "model" "*7" } { "classname" "light" "origin" "-16 1608 -24" "light" "200" } { "classname" "item_health" "origin" "440 808 0" "spawnflags" "2" } { "classname" "item_health" "origin" "-300 692 -144" } { "classname" "item_health" "origin" "-248 692 -144" } { "classname" "item_shells" "origin" "-116 1160 -144" } { "classname" "item_rockets" "origin" "584 856 0" "spawnflags" "1" } { "classname" "item_shells" "origin" "632 856 0" } { "classname" "item_health" "origin" "904 1096 0" } { "classname" "item_health" "origin" "904 1032 0" } { "classname" "item_spikes" "origin" "-224 748 0" } { "classname" "item_health" "origin" "-672 1412 0" } { "classname" "item_health" "origin" "-672 1372 0" } { "classname" "item_health" "origin" "152 1272 0" } { "classname" "item_health" "origin" "200 1272 0" } { "classname" "item_shells" "origin" "304 1016 0" } { "angle" "0" "origin" "576 752 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-560 768 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-656 976 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-432 1596 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "104 1392 24" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "1128 1424 72" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "280 1416 -120" "classname" "info_player_deathmatch" } { "origin" "-494 1398 60" "classname" "light_torch_small_walltorch" } { "origin" "48 1152 0" "classname" "weapon_supershotgun" } { "classname" "light" "origin" "482 658 16" "light" "150" } { "classname" "light" "origin" "-272 1592 -120" "light" "250" } { "light" "250" "origin" "-264 1424 -120" "classname" "light" } { "classname" "light" "origin" "-120 1496 -48" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "-694 1658 60" } { "classname" "light" "origin" "-368 1592 88" "light" "200" } //{ //"classname" "item_armor1" //"origin" "-400 1112 -144" //} { "classname" "item_armor1" //Q-Man "origin" "-392 1416 0" } //{ //"classname" "weapon_nailgun" //"origin" "1088 704 48" //} { "classname" "weapon_grenadelauncher" "origin" "-312 1088 48" "angle" "180" } { "classname" "item_shells" "origin" "-536 1000 0" "spawnflags" "1" } { "classname" "weapon_supernailgun" //Q-Man "origin" "-560 1384 0" } { "classname" "item_spikes" "origin" "472 1408 -144" } { "origin" "472 1464 -144" "classname" "item_spikes" } { "spawnflags" "1" "origin" "432 1624 -144" "classname" "item_health" } { "classname" "item_health" "origin" "384 1624 -144" "spawnflags" "1" } { "light" "200" "origin" "-30 1466 -92" "classname" "light_torch_small_walltorch" } { "classname" "trigger_changelevel" "map" "dm2" "model" "*8" } { "classname" "info_intermission" "origin" "296 1152 200" "mangle" "15 180 0" "angle" "180" } { "mangle" "20 210 0" "origin" "432 896 120" "classname" "info_intermission" } //Q-Man { "classname" "item_flag_team1" "origin" "432 1456 -120" } { "classname" "info_player_team1" "origin" "347 1290 -120" } { "classname" "info_player_team1" "origin" "54 1290 -120" } { "classname" "info_player_team1" "origin" "54 1157 -120" } { "classname" "info_player_team1" "origin" "347 1157 -120" } { "classname" "item_flag_team2" "origin" "1088 704 74" } { "classname" "info_player_team2" "origin" "1088 845 74" "angle" "270" } { "classname" "info_player_team2" "origin" "1088 1009 74" "angle" "270" } { "classname" "info_player_team2" "origin" "952 704 74" "angle" "0" } { "classname" "info_player_team2" "origin" "749 704 42" "angle" "0" } { "origin" "-400 1112 -144" "classname" "weapon_supershotgun" } { "origin" "636 572 24" "classname" "weapon_grenadelauncher" } { "origin" "793 1013 24" "classname" "weapon_supernailgun" } { "classname" "item_health" "spawnflags" "1" "origin" "1088 734 74" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm2.ent000066400000000000000000000446541475442401000251230ustar00rootroot00000000000000{ "message" "Claustrophobopolis" "classname" "worldspawn" "wad" "gfx/metal.wad" } { "angle" "90" "origin" "1696 -1456 24" "classname" "info_player_start" } { "targetname" "t1" "angle" "180" "classname" "func_door" "model" "*1" } { "angle" "0" "classname" "func_door" "model" "*2" } { "target" "t1" "angle" "90" "classname" "func_button" "model" "*3" } { "wait" "4" "angle" "270" "classname" "func_door" "targetname" "t1" "spawnflags" "4" "model" "*4" } { "wait" "4" "lip" "0" "targetname" "t1" "angle" "90" "spawnflags" "4" "classname" "func_door" "model" "*5" } { "light" "650" "origin" "1696 -1024 568" "classname" "light" } { "light" "600" "origin" "1424 -984 568" "classname" "light" } { "light" "600" "origin" "1424 -1064 568" "classname" "light" } { "light" "600" "origin" "1424 -1136 568" "classname" "light" } { "light" "600" "origin" "1424 -912 568" "classname" "light" } { "origin" "1696 -1008 360" "classname" "light" } { "light" "600" "origin" "1936 -1064 568" "classname" "light" } { "light" "600" "origin" "1936 -1136 568" "classname" "light" } { "light" "600" "origin" "1936 -984 568" "classname" "light" } { "light" "600" "origin" "1936 -912 568" "classname" "light" } { "light" "200" "origin" "2016 -928 64" "classname" "light" } { "light" "200" "origin" "1344 -928 64" "classname" "light" } { "light" "400" "origin" "2176 -928 136" "classname" "light" } { "light" "400" "origin" "1184 -928 136" "classname" "light" } { "light" "500" "origin" "1496 -1376 392" "classname" "light" } { "light" "500" "origin" "1616 -1376 392" "classname" "light" } { "light" "500" "origin" "1872 -1376 392" "classname" "light" } { "light" "500" "origin" "1744 -1384 392" "classname" "light" } { "light" "200" "origin" "1992 -1312 248" "classname" "light" } { "light" "200" "origin" "1384 -1304 248" "classname" "light" } { "light" "200" "origin" "1696 -1304 248" "classname" "light" } { "light" "200" "origin" "1968 -1136 208" "classname" "light" } { "light" "200" "origin" "1392 -1136 208" "classname" "light" } { "light" "200" "origin" "1312 -1040 60" "classname" "light" } { "target" "t2" "classname" "trigger_teleport" "model" "*6" } { "targetname" "t2" "angle" "270" "origin" "1696 -896 8" "classname" "info_teleport_destination" } { "dmg" "1000" "spawnflags" "4" "targetname" "t3" "angle" "0" "classname" "func_door" "speed" "200" "model" "*7" } { "light" "200" "origin" "1312 -928 280" "classname" "light" } { "light" "200" "origin" "1312 -976 280" "classname" "light" } { "classname" "func_button" "angle" "90" "target" "t1" "model" "*8" } { "classname" "func_door" "spawnflags" "4" "angle" "180" "targetname" "t3" "dmg" "1000" "speed" "200" "model" "*9" } { "classname" "trigger_teleport" "target" "t2" "model" "*10" } { "light" "200" "classname" "light" "origin" "2048 -1048 56" } { "classname" "func_train" "target" "t4" "model" "*11" } { "classname" "path_corner" "origin" "1792 -1064 304" "targetname" "t4" "target" "t5" } { "origin" "1472 -1064 304" "classname" "path_corner" "targetname" "t5" "target" "t4" } { "light" "400" "origin" "2240 -416 232" "classname" "light" } { "light" "400" "origin" "2368 -424 232" "classname" "light" } { "angle" "0" "origin" "2136 -64 24" "classname" "info_player_start" } { "light" "200" "origin" "2200 -344 16" "classname" "light" } { "light" "200" "origin" "2144 -496 16" "classname" "light" } { "light" "200" "origin" "2464 -512 16" "classname" "light" } { "light" "200" "origin" "2480 -328 16" "classname" "light" } { "light" "400" "origin" "2472 -192 304" "classname" "light" } { "light" "400" "origin" "2376 -192 304" "classname" "light" } { "light" "300" "origin" "2592 -152 304" "classname" "light" } { "light" "300" "origin" "2592 -248 304" "classname" "light" } { "light" "300" "origin" "2592 -344 304" "classname" "light" } { "light" "300" "origin" "2592 -440 304" "classname" "light" } { "light" "400" "origin" "1984 -64 232" "classname" "light" } { "origin" "2256 168 -112" "classname" "light" } { "origin" "2296 88 -112" "classname" "light" } { "origin" "2464 160 -112" "classname" "light" } { "origin" "2512 96 -112" "classname" "light" } { "origin" "2384 136 -112" "classname" "light" } { "light" "400" "origin" "2144 128 240" "classname" "light" } { "light" "400" "origin" "2144 192 240" "classname" "light" } { "light" "400" "origin" "2272 288 240" "classname" "light" } { "light" "400" "origin" "2464 288 240" "classname" "light" } { "light" "400" "origin" "2336 288 240" "classname" "light" } { "light" "400" "origin" "2400 288 240" "classname" "light" } { "light" "400" "origin" "2624 128 240" "classname" "light" } { "light" "400" "origin" "2624 192 240" "classname" "light" } { "classname" "light" "origin" "2144 152 -144" } { "classname" "light" "origin" "2152 -24 -144" } { "classname" "light" "origin" "2152 -168 -144" } { "classname" "light" "origin" "2424 -32 304" "light" "400" } { "classname" "light" "origin" "2520 -32 304" "light" "400" } { "classname" "func_door" "angle" "-1" "speed" "200" "wait" "6" "targetname" "t6" "model" "*12" } { "classname" "func_door" "speed" "200" "angle" "-1" "wait" "6" "targetname" "t6" "model" "*13" } { "classname" "trigger_teleport" "target" "t7" "model" "*14" } { "classname" "light" "origin" "2872 -32 -48" "light" "200" } { "classname" "info_teleport_destination" "origin" "1920 -740 500" "angle" "90" //Q-Man "targetname" "t7" } { "classname" "func_button" "spawnflags" "1" "angle" "270" "target" "t6" "model" "*15" } { "classname" "item_armor2" "origin" "2800 -32 -96" } { "classname" "item_rockets" "origin" "2232 -112 -160" "spawnflags" "1" } { "classname" "info_player_deathmatch" "origin" "2560 -192 32" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "2544 -32 -64" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "2624 -488 32" "angle" "180" } { "classname" "item_spikes" "origin" "2584 -352 0" } { "classname" "item_health" "origin" "2528 -184 96" "spawnflags" "1" } { "classname" "item_health" "origin" "2528 -224 96" } { "classname" "item_health" "origin" "2584 248 -96" } { "classname" "item_rockets" "origin" "2040 -1032 320" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "2480 -192 0" } { "classname" "weapon_rocketlauncher" "origin" "1472 -704 160" } { "origin" "1904 -240 0" "classname" "item_spikes" } { "classname" "light" "origin" "2552 -1312 272" "light" "500" } { "classname" "light" "origin" "2408 -1320 272" "light" "500" } { "classname" "light" "origin" "2552 -1896 272" "light" "500" } { "classname" "light" "origin" "2408 -1888 272" "light" "500" } { "classname" "light" "origin" "2480 -1600 272" "light" "400" } { "classname" "light" "origin" "2760 -1416 400" "light" "400" } { "classname" "light" "origin" "2768 -1544 400" "light" "400" } { "classname" "light" "origin" "2768 -1672 400" "light" "400" } { "classname" "light" "origin" "2768 -1800 400" "light" "400" } { "speed" "200" "wait" "-1" "angle" "270" //"spawnflags" "1" "classname" "func_door" "targetname" "t10" "model" "*16" } { "angle" "270" "spawnflags" "1" "classname" "func_button" //"target" "t10" "model" "*17" } { "light" "200" "origin" "2592 -2048 80" "classname" "light" } { "light" "200" "origin" "2304 -2048 80" "classname" "light" } { "light" "200" "origin" "2560 -2312 80" "classname" "light" } { "light" "200" "origin" "2304 -2304 80" "classname" "light" } { "origin" "2544 -2048 336" "classname" "light" "light" "500" } { "origin" "2544 -2176 336" "classname" "light" "light" "400" } { "origin" "2544 -2296 336" "classname" "light" "light" "300" } { "origin" "2352 -2296 336" "classname" "light" "light" "300" } { "origin" "2352 -2176 336" "classname" "light" "light" "500" } { "origin" "2352 -2048 336" "classname" "light" "light" "400" } { "light" "400" "origin" "2760 -2056 400" "classname" "light" } { "light" "400" "origin" "2760 -2184 400" "classname" "light" } { "light" "400" "origin" "2760 -2312 400" "classname" "light" } { "origin" "2176 -2072 0" "classname" "light" } { "origin" "2176 -2168 0" "classname" "light" } { "origin" "2176 -2232 0" "classname" "light" } { "origin" "2176 -2296 0" "classname" "light" } { "light" "400" "origin" "2176 -1856 272" "classname" "light" } { "light" "100" "origin" "2176 -2032 120" "classname" "light" } { "light" "150" "origin" "2176 -2344 96" "classname" "light" } { "light" "100" "origin" "2176 -2184 120" "classname" "light" } { "classname" "light" "origin" "2184 -1648 272" "light" "400" } { "classname" "light" "origin" "2056 -1744 272" "light" "400" } { "classname" "light" "origin" "1928 -1648 272" "light" "400" } { "classname" "light" "origin" "1800 -1744 272" "light" "400" } { "classname" "light" "origin" "1736 -1648 272" "light" "400" } { "classname" "item_armorInv" "origin" "2480 -1992 96" } { "classname" "item_health" "origin" "2384 -1992 96" "spawnflags" "2" } { "classname" "item_health" "origin" "2344 -1320 0" } { "classname" "item_health" "origin" "2392 -1320 0" } { "classname" "func_door" "angle" "-1" "speed" "300" "wait" "5" "lip" "64" "targetname" "t11" "model" "*18" } { "classname" "func_button" "angle" "180" "target" "t11" "model" "*19" } { "classname" "light" "origin" "2448 -2024 336" "light" "300" } { "classname" "light" "origin" "2440 -2320 336" "light" "300" } { "classname" "item_spikes" "origin" "2168 -1872 0" } { "classname" "info_player_deathmatch" "origin" "2176 -2176 88" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "2576 -1328 24" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "2704 -2048 128" "angle" "270" } { "classname" "func_door" "angle" "90" "spawnflags" "1" "lip" "-8" "speed" "200" "targetname" "t9" "model" "*20" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "lip" "-8" "speed" "200" "model" "*21" } { "classname" "func_button" "angle" "270" "target" "t9" "model" "*22" } { "classname" "light" "origin" "2944 -1936 160" } { "classname" "light" "origin" "2440 -2464 400" "light" "400" } { "classname" "light" "origin" "2344 -2464 400" "light" "400" } { "classname" "light" "origin" "2248 -2464 400" "light" "400" } { "classname" "light" "origin" "2200 -2464 400" "light" "400" } { "classname" "light" "origin" "2176 -2040 400" "light" "500" } { "classname" "light" "origin" "2176 -2136 400" "light" "500" } { "classname" "light" "origin" "2176 -2232 400" "light" "300" } { "classname" "weapon_supershotgun" "origin" "2736 -2304 96" } { "classname" "item_rockets" "origin" "2184 -2480 176" "spawnflags" "1" } { "classname" "path_corner" "origin" "1984 -1768 -16" "targetname" "t12" "target" "t13" } { "classname" "path_corner" "origin" "1936 -1768 -16" "targetname" "t13" "target" "t12" } { "classname" "func_train" "speed" "75" "target" "t12" "model" "*23" } { "classname" "light" "origin" "2024 -408 160" } { "classname" "light" "origin" "2512 -1168 304" } { "classname" "light" "origin" "2608 -704 304" } { "classname" "info_player_deathmatch" "origin" "1712 -504 24" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "2048 -1352 136" "angle" "180" } //{ //"classname" "info_teleport_destination" //"origin" "1312 -1376 128" //"angle" "0" //"targetname" "t14" //} //{ //"classname" "trigger_teleport" //"target" "t14" //"model" "*24" //} { "classname" "func_door" "angle" "180" "targetname" "t15" "model" "*25" } { "classname" "func_door" "model" "*26" } { "classname" "trigger_multiple" "target" "t15" "model" "*27" } { "classname" "item_armorInv" "origin" "2392 -648 32" } { "classname" "weapon_rocketlauncher" "origin" "2480 -1712 0" } { "classname" "item_health" "origin" "2008 -552 80" } { "classname" "item_health" "origin" "2008 -504 80" } { "classname" "item_armor2" "origin" "2056 -936 16" } { "classname" "item_armor2" "origin" "1312 -952 16" } { "classname" "func_train" "target" "t16" "speed" "75" "model" "*28" } { "classname" "path_corner" "origin" "1792 -1768 -16" "targetname" "t16" "target" "t17" } { "classname" "path_corner" "origin" "1840 -1768 -16" "targetname" "t17" "target" "t16" } { "classname" "light" "origin" "2416 -656 296" } { "classname" "func_door" "angle" "270" "targetname" "t18" "lip" "-8" "model" "*29" } { "health" "1" "classname" "func_button" "target" "t18" "angle" "270" "model" "*30" } { "classname" "light" "origin" "2512 -984 304" } { "classname" "light" "origin" "2560 -832 304" } { "classname" "light" "origin" "2608 -640 208" "light" "150" } { "classname" "light" "origin" "2512 -816 208" "light" "150" } { "classname" "light" "origin" "2504 -1056 208" "light" "150" } { "classname" "light" "origin" "2512 -1224 208" "light" "150" } { "classname" "light" "origin" "2368 -848 -16" } { "classname" "light" "origin" "2368 -704 -16" } { "classname" "light" "origin" "2512 -704 -16" } { "classname" "light" "origin" "2464 -608 -16" } { "classname" "func_plat" "model" "*31" } { "classname" "light" "origin" "1328 -528 408" } { "light" "200" "classname" "light" "origin" "1296 -912 408" } { "classname" "weapon_grenadelauncher" "origin" "2056 -936 320" } { "classname" "item_health" "origin" "2040 -992 320" "spawnflags" "2" } { "classname" "light" "origin" "1312 -512 480" } { "classname" "item_rockets" "origin" "1520 -720 160" } { "classname" "func_button" "angle" "0" "target" "t3" "wait" "5" "model" "*32" } { "angle" "0" "classname" "func_button" "target" "t3" "wait" "5" "model" "*33" } { "classname" "light" "origin" "1704 -704 272" } { "classname" "light" "origin" "1784 -736 48" "light" "150" } { "classname" "light" "origin" "1784 -1504 48" "light" "150" } { "classname" "light" "origin" "1936 -1688 -24" } { "classname" "light" "origin" "2704 -1896 144" "light" "150" } { "classname" "light" "origin" "2248 -192 -112" "light" "150" } { "classname" "func_plat" "model" "*34" } { "origin" "1944 -40 0" "classname" "item_health" } { "angle" "0" "origin" "2248 -16 -136" "classname" "info_player_deathmatch" } { "light" "200" "origin" "2488 -1104 64" "classname" "light" } { "style" "11" "target" "t19" "origin" "1760 -736 48" "classname" "light" } { "targetname" "t19" "origin" "1804 -736 44" "classname" "info_null" } { "targetname" "t20" "origin" "2048 -836 56" "classname" "info_null" } { "style" "11" "target" "t20" "origin" "2052 -892 60" "classname" "light" } { "targetname" "t21" "origin" "1312 -836 56" "classname" "info_null" } { "target" "t21" "classname" "light" "origin" "1312 -892 60" "style" "11" } { "light" "200" "origin" "1456 -896 64" "classname" "light" } { "classname" "light" "origin" "1456 -1088 64" "light" "200" } { "light" "200" "origin" "1872 -1088 64" "classname" "light" } { "classname" "light" "origin" "1872 -896 64" "light" "200" } { "targetname" "t22" "origin" "2256 -220 -112" "classname" "info_null" } { "style" "11" "target" "t22" "origin" "2256 -152 -108" "classname" "light" } { "targetname" "t23" "origin" "2704 -1916 140" "classname" "info_null" } { "style" "11" "target" "t23" "origin" "2704 -1832 144" "classname" "light" } { "targetname" "t24" "origin" "2176 -2364 112" "classname" "info_null" } { "style" "11" "target" "t24" "origin" "2176 -2284 116" "classname" "light" } { "light" "150" "origin" "2432 -664 152" "classname" "light" } { "origin" "2410 -694 40" "classname" "ambient_drip" } { "classname" "trigger_changelevel" "map" "dm3" "model" "*35" } { "light" "400" "origin" "1888 -504 448" "classname" "light" } { "classname" "light" "origin" "1920 -640 448" "light" "400" } { "light" "400" "origin" "1536 -704 448" "classname" "light" } { "classname" "light" "origin" "1496 -512 448" "light" "400" } { "light" "200" "origin" "1520 -552 -40" "classname" "light" } { "light" "200" "classname" "light" "origin" "1560 -472 -40" } { "light" "200" "origin" "1480 -456 -40" "classname" "light" } { "light" "200" "classname" "light" "origin" "1592 -568 -40" } { "light" "150" "origin" "1528 -520 32" "classname" "light" } { "light" "150" "origin" "1696 -544 248" "classname" "light" } { "light" "150" "origin" "1792 -512 64" "classname" "light" } { "light" "150" "origin" "1408 -384 232" "classname" "light" } { "classname" "light" "origin" "1512 -344 232" "light" "150" } { "light" "150" "origin" "1600 -384 232" "classname" "light" } { "classname" "light" "origin" "1720 -344 232" "light" "150" } { "light" "150" "origin" "1848 -384 232" "classname" "light" } { "origin" "1920 -704 184" "classname" "item_artifact_super_damage" } { "origin" "1840 -656 160" "classname" "item_health" } { "classname" "item_health" "origin" "1904 -656 160" } { "light" "150" "origin" "2688 -1984 264" "classname" "light" } { "classname" "light" "origin" "2688 -2080 264" "light" "150" } { "light" "150" "origin" "2688 -2176 264" "classname" "light" } { "classname" "light" "origin" "2688 -2272 264" "light" "150" } { "style" "11" "target" "t25" "origin" "1752 -1504 64" "classname" "light" } { "targetname" "t25" "origin" "1804 -1504 44" "classname" "info_null" } { "light" "150" "origin" "1696 -1544 96" "classname" "light" } { "light" "150" "origin" "2304 -32 -72" "classname" "light" } { "classname" "light" "origin" "2400 -32 -72" "light" "150" } { "light" "150" "origin" "2512 0 -72" "classname" "light" } { "classname" "light" "origin" "2600 -40 -72" "light" "150" } { "light" "150" "origin" "2240 -128 -72" "classname" "light" } { "classname" "light" "origin" "2208 -8 -72" "light" "150" } { "light" "150" "origin" "2080 -928 400" "classname" "light" } { "classname" "light" "origin" "2048 -1088 400" "light" "150" } { "light" "100" "origin" "2576 -192 40" "classname" "light" } { "style" "11" "target" "t26" "origin" "2560 -1984 136" "classname" "light" } { "targetname" "t26" "origin" "2612 -1984 132" "classname" "info_null" } { "light" "150" "origin" "2672 -2192 128" "classname" "light" } { "classname" "light" "origin" "2672 -2048 128" "light" "150" } { "light" "150" "origin" "2704 -2344 128" "classname" "light" } { "light" "200" "origin" "2432 -2528 128" "classname" "light" } { "classname" "info_intermission" "origin" "1696 -1424 64" "mangle" "-30 90 0" } //Q-Man { "classname" "item_flag_team1" "origin" "1980 -1026 344" } { "classname" "info_player_team1" "origin" "1844 -1078 48" "angle" "270" } { "classname" "info_player_team1" "origin" "1531 -1078 48" "angle" "270" } { "classname" "info_player_team1" "origin" "2071 -1110 344" "angle" "135" } { "classname" "info_player_team1" "origin" "1280 -1024 352" } { "classname" "item_flag_team2" "origin" "2433 -2120 112" } { "classname" "info_player_team2" "origin" "2704 -2049 128" "angle" "270" } { "classname" "info_player_team2" "origin" "2430 -2288 120" "angle" "180" } { "classname" "info_player_team2" "origin" "2316 -1985 120" "angle" "270" } { "classname" "info_player_team2" "origin" "2184 -2480 200" "angle" "90" } { "classname" "weapon_supershotgun" "origin" "2051 -1313 136" } { "classname" "weapon_supernailgun" "origin" "1313 -1316 136" } { "classname" "weapon_supernailgun" "origin" "2430 -2288 120" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm3.ent000066400000000000000000000341121475442401000251100ustar00rootroot00000000000000{ "wad" "gfx/base.wad" "classname" "worldspawn" "worldtype" "2" "sounds" "6" "message" "The Abandoned Base" } { "classname" "light_fluoro" "origin" "264 -32 88" } { "classname" "info_player_start" "origin" "632 -648 88" "angle" "0" } { "classname" "light_fluoro" "origin" "888 -32 88" } { "classname" "light" "origin" "580 -32 160" "light" "550" } { "classname" "light" "origin" "200 280 88" "light" "200" } { "classname" "light" "origin" "200 -344 88" "light" "200" } { "classname" "light" "origin" "952 280 88" "light" "200" } { "classname" "light" "origin" "952 -344 88" "light" "200" } { "classname" "light_fluoro" "origin" "784 448 88" } { "classname" "light" "origin" "632 288 88" "light" "200" } { "light" "350" "classname" "light" "origin" "1152 504 128" } { "classname" "light" "origin" "1544 -216 152" "light" "500" } { "classname" "light" "origin" "1808 -416 -120" "light" "200" } { "classname" "light_fluoro" "origin" "1984 536 -56" } { "classname" "light" "origin" "1352 456 112" "light" "200" } { "classname" "light" "origin" "1632 208 72" } { "classname" "light" "origin" "1760 208 72" } { "classname" "light" "origin" "1152 208 72" } { "classname" "light" "origin" "1360 72 56" "light" "200" } { "classname" "light" "origin" "1864 8 56" "light" "200" } { "classname" "light" "origin" "1864 -144 56" "light" "200" } { "classname" "light" "origin" "1864 -272 56" "light" "200" } { "classname" "light" "origin" "1544 -440 56" "light" "200" } { "classname" "light" "origin" "1224 -208 56" "light" "200" } { "classname" "light" "origin" "1864 -432 56" "light" "200" } { "classname" "light" "origin" "1224 -424 56" "light" "200" } { "origin" "1520 496 -112" "classname" "weapon_rocketlauncher" } { "light" "250" "origin" "1976 -8 -96" "classname" "light" } { "origin" "1536 536 -104" "classname" "light_fluoro" } { "light" "200" "origin" "1984 256 -56" "classname" "light" } { "light" "200" "origin" "1760 480 -56" "classname" "light" } { "origin" "1096 -208 -120" "classname" "light" } { "origin" "1088 152 -120" "classname" "light" } { "light" "200" "origin" "1360 -24 -136" "classname" "light" } { "origin" "1992 -240 40" "classname" "light_fluoro" } { "origin" "1448 -152 -320" "classname" "light" "light" "250" } { "origin" "1728 -152 -320" "classname" "light" "light" "250" } { "origin" "1568 160 -320" "classname" "light" "light" "250" } { "light" "150" "origin" "1296 -392 -152" "classname" "light" } { "light" "200" "origin" "1448 -360 -152" "classname" "light" } { "origin" "1160 -224 -320" "classname" "light" "light" "250" } { "origin" "1160 136 -320" "classname" "light" "light" "250" } { "origin" "1696 208 -320" "classname" "light" "light" "250" } { "origin" "1824 -448 -328" "classname" "light" "light" "200" } { "origin" "1360 240 -384" "classname" "light" "light" "200" } { "origin" "1360 424 -384" "classname" "light" "light" "200" } { "origin" "1368 24 -312" "classname" "light" "light" "200" } { "light" "600" "origin" "1072 888 -56" "classname" "light" } { "light" "600" "origin" "1664 824 -16" "classname" "light" } { "light" "600" "origin" "1360 888 -56" "classname" "light" } { "light" "200" "origin" "1368 656 -312" "classname" "light" } { "light" "200" "origin" "1536 -616 8" "classname" "light_fluoro" } { "light" "200" "origin" "1744 -616 8" "classname" "light_fluoro" } { "light" "200" "origin" "1856 -616 8" "classname" "light_fluoro" } { "light" "200" "origin" "1744 -736 8" "classname" "light" } { "light" "200" "origin" "1856 -736 8" "classname" "light" } { "light" "200" "origin" "1536 -736 8" "classname" "light" } { "light" "200" "origin" "1536 -896 96" "classname" "light" } { "light" "200" "origin" "1744 -896 80" "classname" "light" } { "light" "200" "origin" "1856 -896 80" "classname" "light" } { "light" "150" "origin" "1240 -904 0" "classname" "light" } { "origin" "1472 -912 -48" "classname" "item_health" } { "light" "150" "origin" "1472 -872 -8" "classname" "light" } { "light" "200" "origin" "1216 -576 32" "classname" "light" } { "light" "200" "origin" "1152 -640 112" "classname" "light" } { "light" "200" "origin" "1360 -776 24" "classname" "light" } { "light" "200" "origin" "1232 -776 24" "classname" "light" } { "light" "200" "origin" "1088 -704 24" "classname" "light" } { "light" "150" "origin" "1360 -904 112" "classname" "light" } { "light" "150" "origin" "1232 -904 112" "classname" "light" } { "light" "150" "origin" "1056 -880 112" "classname" "light" } { "origin" "952 -776 120" "classname" "light" } { "light" "200" "origin" "656 -352 96" "classname" "light" } { "light" "200" "origin" "656 -648 96" "classname" "light" } { "light" "200" "origin" "840 -656 96" "classname" "light" } { "origin" "928 -280 -152" "classname" "light_fluoro" } { "origin" "928 216 -152" "classname" "light_fluoro" } { "origin" "856 -32 -168" "classname" "light_fluoro" } { "spawnflags" "2" "origin" "564 -48 -192" "classname" "item_health" } { "classname" "light" "origin" "480 624 96" "light" "200" } { "classname" "light_fluoro" "origin" "304 592 136" "light" "250" } { "classname" "light_fluoro" "origin" "512 368 136" "light" "250" } { "classname" "light" "origin" "-120 560 208" } { "classname" "light" "origin" "-272 784 32" } { "light" "350" "origin" "-224 664 248" "classname" "light_fluoro" } { "light" "350" "origin" "-224 416 248" "classname" "light_fluoro" } { "origin" "-416 672 248" "classname" "light_fluoro" "light" "350" } { "origin" "-416 352 248" "classname" "light_fluoro" "light" "350" } { "origin" "-416 512 248" "classname" "light" "light" "350" } { "origin" "-400 248 -40" "classname" "item_health" } { "spawnflags" "1" "origin" "-336 240 -40" "classname" "item_health" } { "light" "350" "origin" "-608 512 248" "classname" "light" } { "light" "350" "origin" "-608 672 248" "classname" "light" } { "light" "350" "origin" "-608 352 248" "classname" "light" } { "light" "350" "origin" "-800 672 248" "classname" "light" } { "light" "350" "origin" "-800 352 248" "classname" "light" } { "light" "350" "origin" "-800 512 248" "classname" "light" } { "classname" "light" "origin" "-800 704 8" "light" "250" } { "classname" "light" "origin" "-800 384 24" "light" "100" } { "classname" "light" "origin" "-888 64 104" } { "classname" "light_fluoro" "origin" "-704 96 232" "light" "150" } { "classname" "item_health" "origin" "-720 80 160" "spawnflags" "2" } { "classname" "light_fluoro" "origin" "-952 -256 16" "light" "250" } { "classname" "light_fluoro" "origin" "-640 -216 16" "light" "250" } { "classname" "light" "origin" "-640 -448 16" "light" "200" } { "classname" "light_fluoro" "origin" "-680 -704 16" "light" "250" } { "classname" "light_fluoro" "origin" "200 -704 128" } { "classname" "light_fluoro" "origin" "312 -704 128" } { "classname" "light_fluoro" "origin" "-304 -872 64" } { "classname" "light" "origin" "-320 -560 64" "light" "200" } { "classname" "light" "origin" "-160 -840 64" "light" "225" } { "classname" "light" "origin" "480 -472 88" "light" "200" } { "classname" "light_fluoro" "origin" "-208 -704 472" } { "classname" "light" "origin" "-48 -704 472" } { "classname" "light_fluoro" "origin" "112 -704 472" } { "classname" "light_fluoro" "origin" "272 -704 472" } { "classname" "light" "origin" "-168 -656 208" "light" "225" } { "classname" "light" "origin" "-168 -752 200" "light" "200" } { "classname" "light" "origin" "320 -584 296" "light" "200" } { "classname" "light" "origin" "320 -824 296" "light" "200" } { "classname" "light" "origin" "112 -840 224" "light" "150" } { "classname" "light" "origin" "224 -32 -144" "light" "200" } { "classname" "light" "origin" "32 -192 -112" "light" "200" } { "classname" "light" "origin" "-176 -304 -96" "light" "200" } { "classname" "light" "origin" "-16 -432 8" "light" "200" } { "classname" "func_plat" "angle" "0" "spawnflags" "1" "sounds" "1" "model" "*1" } { "classname" "func_plat" "sounds" "1" "model" "*2" } { "classname" "light" "origin" "760 888 8" "light" "600" } { "classname" "light" "origin" "592 1032 64" "light" "200" } { "classname" "light" "origin" "656 864 40" } { "classname" "light" "origin" "688 688 -88" } { "classname" "func_plat" "spawnflags" "1" "angle" "90" "sounds" "1" "model" "*3" } { "classname" "light" "origin" "512 752 240" "light" "200" } { "classname" "light" "origin" "512 952 120" "light" "200" } { "classname" "light" "origin" "512 864 232" "light" "100" } { "classname" "item_armor2" "origin" "1232 -904 -48" } { "classname" "item_health" "origin" "1840 624 -204" "spawnflags" "2" } { "classname" "item_rockets" "origin" "-680 232 -40" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-752 464 96" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-352 304 96" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-432 440 -40" } { "classname" "item_shells" "origin" "-576 744 -40" } { "classname" "item_health" "origin" "-712 592 -40" } { "classname" "item_health" "origin" "-712 632 -40" "spawnflags" "1" } { "classname" "item_shells" "origin" "-904 792 96" } { "classname" "item_health" "origin" "-624 -240 -40" } { "classname" "item_spikes" "origin" "-680 -752 -40" } { "classname" "item_rockets" "origin" "-360 -888 -40" } { "classname" "item_spikes" "origin" "-232 -872 128" "spawnflags" "1" } { "classname" "item_shells" "origin" "312 -560 240" "spawnflags" "1" } { "classname" "item_rockets" "origin" "192 -256 32" } { "classname" "item_shells" "origin" "176 32 32" } { "classname" "item_spikes" "origin" "336 248 32" } { "classname" "item_spikes" "origin" "728 248 32" } { "classname" "item_shells" "origin" "920 -8 32" } { "classname" "item_rockets" "origin" "760 -360 32" } { "classname" "item_shells" "origin" "344 -720 -40" "spawnflags" "1" } { "classname" "item_shells" "origin" "-192 -448 -136" } { "classname" "item_spikes" "origin" "64 -208 -136" } { "classname" "item_shells" "origin" "968 -776 64" "spawnflags" "1" } { "classname" "item_health" "origin" "1608 -640 -48" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1848 -864 -48" } { "classname" "item_spikes" "origin" "1384 -40 -192" } { "classname" "item_shells" "origin" "1368 -360 -48" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1744 -496 -416" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1504 320 -416" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1840 320 -416" "spawnflags" "1" } { "classname" "info_player_deathmatch" "origin" "-880 -232 -16" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "192 -208 -176" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "1472 -928 -24" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "1520 432 -88" "angle" "0" } { "classname" "item_spikes" "origin" "1600 520 -112" } { "classname" "trigger_teleport" "target" "t1" "model" "*4" } { "classname" "info_teleport_destination" "origin" "1328 544 44" "angle" "270" "targetname" "t1" } { "target" "t2" "classname" "trigger_teleport" "model" "*5" } { "targetname" "t2" "angle" "45" "origin" "224 -320 48" "classname" "info_teleport_destination" } { "light" "250" "origin" "-544 -448 72" "classname" "light" } { "angle" "90" "origin" "-632 -680 -16" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "512 768 216" "classname" "info_player_deathmatch" } { "classname" "weapon_supernailgun" "origin" "1216 240 -416" } { "classname" "item_artifact_super_damage" "origin" "256 -700 328" } { "classname" "weapon_grenadelauncher" "origin" "-64 -704 -40" } { "light" "150" "origin" "-592 240 48" "classname" "light" } { "classname" "ambient_comp_hum" "origin" "-846 218 72" } { "classname" "ambient_comp_hum" "origin" "-750 658 72" } { "classname" "ambient_comp_hum" "origin" "-422 626 72" } { "classname" "ambient_comp_hum" "origin" "-278 266 72" } { "classname" "ambient_comp_hum" "origin" "-494 522 168" } { "classname" "ambient_comp_hum" "origin" "-742 338 176" } { "classname" "light_fluoro" "origin" "264 -640 128" "light" "150" } { "light" "150" "origin" "264 -768 128" "classname" "light_fluoro" } { "classname" "light_fluoro" "origin" "-96 -704 192" "light" "150" } { "classname" "light" "origin" "-64 -704 32" "light" "150" } { "classname" "light_fluoro" "origin" "-256 -712 232" } { "light" "250" "origin" "1552 -264 -328" "classname" "light" } { "light" "150" "origin" "1568 -352 -328" "classname" "light" } { "map" "dm4" "classname" "trigger_changelevel" "model" "*6" } { "classname" "weapon_lightning" "origin" "1544 -192 -416" } { "classname" "item_cells" "origin" "1088 -232 -416" } { "origin" "1832 -424 -416" "classname" "item_cells" } { "classname" "item_cells" "origin" "-952 -296 -40" "spawnflags" "1" } { "classname" "info_intermission" "origin" "-272 -800 336" "mangle" "20 45 0" } { "classname" "info_intermission" "origin" "352 -296 -192" "mangle" "-20 45 0" } { "classname" "info_intermission" "origin" "-736 376 240" "mangle" "20 30 0" } { "classname" "info_intermission" "origin" "1840 256 64" "mangle" "20 240 0" } { "classname" "item_armor2" "origin" "-536 240 -16" } // team 1 stuff { "classname" "item_flag_team1" "origin" "-490 482 120" } { "classname" "weapon_supernailgun" "origin" "-458 332 120" } // player starts { "classname" "info_player_team1" "origin" "-792 704 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-740 546 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-866 478 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-740 358 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-464 228 176" "angle" "0" } { "classname" "info_player_team1" "origin" "-348 396 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-334 640 184" "angle" "0" } { "classname" "info_player_team1" "origin" "-482 698 184" "angle" "0" } // team 2 { "origin" "1836 -672 -24" "classname" "item_flag_team2" } { "classname" "weapon_supershotgun" "origin" "1530 -898 88" } // team2 starts { "classname" "info_player_team2" "origin" "1166 -730 -24" "angle" "0" } { "classname" "info_player_team2" "origin" "1290 -742 -24" "angle" "0" } { "classname" "info_player_team2" "origin" "1418 -742 -24" "angle" "0" } { "classname" "info_player_team2" "origin" "1540 -742 -24" "angle" "0" } { "classname" "info_player_team2" "origin" "1660 -742 -24" "angle" "0" } { "classname" "info_player_team2" "origin" "1120 -892 88" "angle" "0" } { "classname" "info_player_team2" "origin" "1277 -897 88" "angle" "0" } { "classname" "info_player_team2" "origin" "1432 -908 88" "angle" "0" }QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm4.ent000066400000000000000000000220511475442401000251100ustar00rootroot00000000000000{ "worldtype" "1" "classname" "worldspawn" "wad" "gfx/metal.wad" "spawnflags" "1" "sounds" "2" "message" "The Bad Place" } { "angle" "90" "classname" "info_player_start" "origin" "384 -960 32" } { "classname" "light" "origin" "136 -72 -376" } { "classname" "light" "origin" "432 -128 -376" } { "classname" "light" "origin" "136 -344 -376" } { "classname" "light" "origin" "392 -344 -376" } { "classname" "light" "origin" "272 -272 -376" } { "classname" "light" "origin" "272 -136 -376" } { "classname" "light" "origin" "304 -624 64" "light" "200" } { "classname" "light" "origin" "480 -864 64" } { "classname" "light" "origin" "208 -880 64" "light" "200" } { "classname" "light" "origin" "664 -208 -248" "light" "225" } { "classname" "light" "origin" "624 112 -248" "light" "200" } { "classname" "light" "origin" "432 -528 64" "light" "200" } { "classname" "light" "origin" "240 -528 64" "light" "200" } { "classname" "light" "origin" "272 -48 -8" } { "classname" "light" "origin" "504 -40 -8" } { "classname" "light" "origin" "184 -240 -296" "light" "200" } { "classname" "light" "origin" "360 -240 -296" "light" "200" } { "classname" "trigger_teleport" "target" "t1" "model" "*1" } { "classname" "info_teleport_destination" "origin" "456 -864 16" "targetname" "t1" "angle" "180" } { "classname" "trigger_teleport" "target" "t2" "model" "*2" } { "classname" "info_teleport_destination" "origin" "624 96 -296" "angle" "270" "targetname" "t2" } { "classname" "light" "origin" "120 -392 16" "light" "200" } { "classname" "light" "origin" "152 -432 -80" "light" "200" } { "classname" "light" "origin" "16 -240 -40" "light" "200" } { "classname" "light" "origin" "368 72 -224" "light" "200" } { "classname" "light" "origin" "-240 -528 -40" } { "classname" "light" "origin" "-128 -592 -32" "light" "200" } { "classname" "trigger_teleport" "target" "t3" "model" "*3" } { "classname" "light" "origin" "832 -528 208" "light" "450" } { "classname" "light" "origin" "1152 -584 40" } { "classname" "light" "origin" "984 -472 -72" } { "light" "200" "classname" "light" "origin" "880 -208 64" } { "classname" "info_teleport_destination" "origin" "720 -176 32" "targetname" "t3" "angle" "0" } { "classname" "light" "origin" "992 -536 208" "light" "450" } { "classname" "light" "origin" "784 -904 -184" "light" "250" } { "classname" "light" "origin" "328 -480 -72" "light" "200" } { "classname" "trigger_teleport" "target" "t4" "model" "*4" } { "classname" "info_teleport_destination" "origin" "376 -240 -296" "angle" "0" "targetname" "t4" } { "classname" "light" "origin" "648 -480 -112" "light" "200" } { "classname" "light" "origin" "496 -432 -88" "light" "200" } { "classname" "light" "origin" "248 -1192 -8" } { "classname" "light" "origin" "472 -912 -88" "light" "200" } { "classname" "light" "origin" "120 -904 128" "light" "400" } { "classname" "light" "origin" "336 -656 -48" } { "classname" "trigger_teleport" "target" "t5" "model" "*5" } { "classname" "info_teleport_destination" "origin" "849 -591 24" "angle" "90" //Q-Man "targetname" "t5" } { "classname" "light" "origin" "824 -656 -160" "light" "200" } { "classname" "light" "origin" "-216 184 -360" "light" "200" } { "classname" "light" "origin" "-208 320 -360" "light" "200" } { "classname" "light" "origin" "80 320 -360" "light" "200" } { "classname" "light" "origin" "88 176 -360" "light" "200" } { "classname" "light" "origin" "-80 376 -360" "light" "200" } { "classname" "light" "origin" "-72 160 -360" "light" "200" } { "light" "400" "origin" "-72 304 -72" "classname" "light" } { "light" "400" "origin" "-72 224 -72" "classname" "light" } { "light" "400" "origin" "-64 136 -72" "classname" "light" } { "light" "200" "origin" "-128 560 -256" "classname" "light" } { "light" "200" "origin" "0 560 -256" "classname" "light" } { "light" "200" "origin" "-48 -280 -256" "classname" "light" } { "light" "200" "origin" "-48 -80 -264" "classname" "light" } { "classname" "item_health" "origin" "-40 584 -320" "spawnflags" "2" } { "classname" "item_rockets" "origin" "-104 568 -320" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-136 -528 -96" } { "classname" "item_shells" "origin" "360 -136 -320" } { "classname" "item_health" "origin" "-208 -456 -96" } { "classname" "item_health" "origin" "-208 -504 -96" } { "classname" "item_armor2" //Q-Man "origin" "712 72 -320" } { "classname" "item_health" "origin" "528 72 -320" } { "classname" "item_rockets" "origin" "440 -784 -128" } { "classname" "item_rockets" "origin" "440 -832 -128" } { "classname" "item_health" "origin" "440 -1008 -120" "spawnflags" "1" } { "classname" "item_health" "origin" "440 -968 -120" "spawnflags" "1" } { "classname" "item_health" "origin" "400 -1008 -120" "spawnflags" "1" } { "classname" "item_spikes" "origin" "256 -832 0" "spawnflags" "1" } { "classname" "item_armor1" //Q-Man "origin" "1136 -592 0" } { "classname" "item_shells" "origin" "712 -864 -256" "spawnflags" "1" } { "classname" "item_spikes" "origin" "984 -624 -128" } { "classname" "item_health" "origin" "960 -464 -128" "spawnflags" "1" } { "classname" "item_health" "origin" "928 -464 -128" "spawnflags" "1" } { "classname" "item_armorInv" "origin" "824 -848 -256" } { "classname" "item_spikes" "origin" "840 -584 0" } { "classname" "item_health" "origin" "496 -488 0" } { "classname" "info_player_deathmatch" "origin" "-64 512 -296" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "-64 -232 -72" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "272 -952 24" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "112 -1136 -104" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "776 -808 -232" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "784 -176 24" "angle" "180" } { "origin" "512 -96 -128" "classname" "item_armor1" } { "origin" "88 -776 -128" "classname" "item_rockets" } { "origin" "88 -824 -128" "classname" "item_shells" } { "origin" "88 -872 -128" "classname" "item_spikes" } { "origin" "200 -32 -128" "classname" "weapon_supernailgun" } { "origin" "112 -432 -128" "classname" "weapon_grenadelauncher" } { "origin" "80 64 -320" "classname" "weapon_rocketlauncher" } { "origin" "352 -8 -320" "classname" "weapon_nailgun" } { "origin" "328 -1032 -128" "classname" "weapon_supershotgun" } { "origin" "768 -880 -256" "classname" "weapon_rocketlauncher" } { "origin" "200 72 -104" "classname" "item_artifact_super_damage" } { "light" "175" "origin" "200 56 -40" "classname" "light" } { "light" "150" "origin" "440 -776 64" "classname" "light" } { "classname" "light" "origin" "448 -976 64" "light" "150" } { "light" "100" "origin" "264 -1024 64" "classname" "light" } { "light" "100" "origin" "104 -912 -64" "classname" "light" } { "classname" "light" "origin" "312 -1024 -64" "light" "125" } { "light" "125" "origin" "440 -1024 -64" "classname" "light" } { "classname" "light" "origin" "408 -768 -64" "light" "125" } { "classname" "light" "origin" "224 -768 -64" "light" "100" } { "light" "125" "origin" "640 -448 -48" "classname" "light" } { "light" "150" "origin" "-112 -384 -40" "classname" "light" } { "classname" "light" "origin" "-112 -248 -40" "light" "125" } { "light" "125" "origin" "136 -336 -24" "classname" "light" } { "light" "125" "origin" "544 -240 -248" "classname" "light" } { "light" "125" "origin" "624 -48 -248" "classname" "light" } { "light" "125" "origin" "696 64 -248" "classname" "light" } { "classname" "light" "origin" "544 64 -248" "light" "125" } { "light" "125" "origin" "552 -72 40" "classname" "light" } { "classname" "light" "origin" "608 -176 40" "light" "150" } { "light" "150" "origin" "544 -312 40" "classname" "light" } { "classname" "light" "origin" "496 -448 40" "light" "150" } { "light" "125" "origin" "744 -176 40" "classname" "light" } { "light" "125" "origin" "840 -328 40" "classname" "light" } { "light" "125" "origin" "784 -736 -208" "classname" "light" } { "light" "125" "origin" "40 424 -256" "classname" "light" } { "classname" "light" "origin" "-168 424 -256" "light" "125" } { "light" "125" "origin" "-136 72 -256" "classname" "light" } { "classname" "light" "origin" "8 72 -256" "light" "125" } { "map" "dm5" "classname" "trigger_changelevel" "model" "*6" } { "classname" "info_intermission" "origin" "464 -112 48" "mangle" "20 225 0" } { "classname" "weapon_lightning" "origin" "528 -304 -128" } { "classname" "item_cells" "origin" "816 -192 0" "spawnflags" "1" } { "classname" "item_cells" "origin" "320 -448 -128" "spawnflags" "1" } { "classname" "item_cells" "origin" "320 -616 0" } //Q-Man { "classname" "item_flag_team1" "origin" "-58 524 -296" } { "classname" "info_player_team1" "origin" "-64 512 -296" "angle" "270" } { "classname" "info_player_team1" "origin" "-197 59 -296" } { "classname" "info_player_team1" "origin" "-40 -241 -296" } { "classname" "item_flag_team2" "origin" "996 -542 -104" } { "classname" "info_player_team2" "origin" "996 -542 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "795 -490 -104" "angle" "270" } { "classname" "info_player_team2" "origin" "849 -591 24" } { "origin" "-237 52 -296" "classname" "item_health" "spawnflags" "1" } { "origin" "-197 52 -296" "classname" "item_health" "spawnflags" "1" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm5.ent000066400000000000000000000245731475442401000251240ustar00rootroot00000000000000{ "sounds" "5" "worldtype" "0" "light" "150" "classname" "worldspawn" "wad" "gfx/medieval.wad" "message" "The Cistern" } { "angle" "0" "origin" "-72 376 232" "classname" "info_player_start" } { "light" "400" "origin" "744 -440 376" "classname" "light" } { "light" "400" "origin" "432 -440 376" "classname" "light" } { "light" "250" "origin" "506 -286 148" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "650 -286 148" "classname" "light_torch_small_walltorch" } { "origin" "858 -826 244" "classname" "light_torch_small_walltorch" } { "origin" "178 -320 68" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-176 -824 68" "classname" "light_torch_small_walltorch" } { "light" "300" "origin" "116 -224 344" "classname" "light" } { "light" "300" "origin" "-104 -644 344" "classname" "light" } { "light" "300" "origin" "88 -644 344" "classname" "light" } { "light" "200" "origin" "8 -640 296" "classname" "light" } { "light" "200" "origin" "522 -718 244" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "344 -640 176" "classname" "light" } { "origin" "-24 -222 68" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "80 -592 -8" "classname" "light" } { "origin" "792 372 344" "classname" "light" } { "origin" "-176 482 68" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "132 792 148" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "426 792 148" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "122 586 20" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "442 586 20" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "280 -224 256" "classname" "light" } { "light" "250" "origin" "288 574 304" "classname" "light_flame_small_yellow" } { "light" "250" "origin" "288 234 304" "classname" "light_flame_small_yellow" } { "origin" "288 416 280" "classname" "light" } { "light" "200" "origin" "288 392 152" "classname" "light" } { "light" "200" "origin" "-112 368 272" "classname" "light" } { "origin" "616 224 244" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "528 280 296" "classname" "light" } { "light" "200" "origin" "-104 -224 272" "classname" "light" } { "classname" "light" "origin" "288 248 -8" "light" "200" } { "classname" "light" "origin" "224 -120 -16" "light" "150" } { "classname" "light" "origin" "544 -640 -16" "light" "150" } { "classname" "light" "origin" "216 -408 -16" "light" "150" } { "classname" "light" "origin" "528 -128 -16" "light" "150" } { "classname" "light" "origin" "280 -664 -16" "light" "150" } { "classname" "light" "origin" "568 -376 -16" "light" "100" } { "classname" "light" "origin" "616 -552 264" "light" "200" } { "classname" "info_player_deathmatch" "origin" "144 -344 40" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "160 -224 232" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "296 704 120" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "720 368 248" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "640 -776 216" "angle" "90" } { "spawnflags" "2" "mdl" "grenade" "origin" "8 -640 -120" "classname" "item_weapon" } { "spawnflags" "2" "mdl" "grenade" "origin" "288 368 192" "classname" "item_weapon" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "1146 -646 244" } { "classname" "light_torch_small_walltorch" "origin" "952 -176 244" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "1146 -890 244" } //{ //"targetname" "t2" //"angle" "180" //"origin" "1072 -768 204" //"classname" "info_teleport_destination" //} //{ //"angle" "180" //"target" "t2" //"classname" "trigger_teleport" //"model" "*1" //} //{ //"angle" "180" //"classname" "trigger_teleport" //"target" "t3" //"model" "*2" //} //{ //"classname" "info_teleport_destination" //"origin" "848 376 200" //"angle" "180" //"targetname" "t3" //} { "light" "200" "origin" "362 1032 164" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "214 1032 164" "classname" "light_torch_small_walltorch" } { "wait" "2" "spawnflags" "1" "target" "t4" "classname" "func_button" "angle" "270" "model" "*3" } { "light" "150" "origin" "288 760 176" "classname" "light" } { "light" "250" "origin" "242 -286 148" "classname" "light_torch_small_walltorch" } { "classname" "info_player_deathmatch" "origin" "880 -256 216" "angle" "225" } { "light" "150" "origin" "288 224 168" "classname" "light" } { "spawnflags" "2" "origin" "272 1000 96" "classname" "item_health" } { //"spawnflags" "1" "origin" "736 504 192" "classname" "item_health" } { "spawnflags" "1" "origin" "792 504 192" "classname" "item_health" } { "origin" "-120 376 192" "classname" "item_health" } { "origin" "80 -432 16" "classname" "item_health" } { "spawnflags" "1" "origin" "200 -256 192" "classname" "item_health" } { "spawnflags" "1" "origin" "256 -256 192" "classname" "item_health" } { "origin" "1016 -680 192" "classname" "item_health" } { "spawnflags" "1" "origin" "512 -240 -136" "classname" "item_health" } { "classname" "item_weapon" "origin" "920 -544 208" "spawnflags" "1" } { "classname" "item_weapon" "origin" "920 -600 208" "spawnflags" "1" } { "classname" "item_weapon" "origin" "-160 -48 16" "spawnflags" "4" } { "spawnflags" "9" "classname" "item_weapon" "origin" "-160 -104 16" } { "classname" "item_weapon" "origin" "-112 -792 192" "spawnflags" "12" } { "classname" "item_weapon" "origin" "504 -16 -136" "spawnflags" "9" } { "classname" "item_weapon" "origin" "372 -320 96" "spawnflags" "4" } { "spawnflags" "1" "classname" "item_weapon" "origin" "768 240 192" } { "origin" "416 -808 100" "classname" "item_rockets" } { "classname" "func_door" "angle" "180" "targetname" "t4" "model" "*4" } { "classname" "trigger_multiple" "target" "t4" "model" "*5" } { "spawnflags" "1" //Q-Man "classname" "item_cells" "origin" "904 -208 208" } { "classname" "weapon_lightning" //Q-Man "origin" "832 -208 208" } { "classname" "item_spikes" "origin" "520 288 -32" } { "classname" "weapon_supernailgun" //Q-Man "origin" "536 360 -32" } //{ //"classname" "weapon_rocketlauncher" //"origin" "272 944 96" //"angle" "180" //} { "classname" "weapon_grenadelauncher" "origin" "112 -400 16" } { "origin" "656 -320 96" "classname" "item_armor2" } { "sounds" "1" "angle" "0" "classname" "func_door" "model" "*6" } { "light" "250" "origin" "714 58 28" "classname" "light_torch_small_walltorch" } { "origin" "648 -72 -32" "classname" "weapon_rocketlauncher" //Q-Man } { //"spawnflags" "1" "origin" "680 -120 -32" //Q-Man "classname" "item_rockets" } { "light" "150" "origin" "288 72 -88" "classname" "light" } { "classname" "light" "origin" "504 48 -88" "light" "150" } { "light" "150" "origin" "496 -128 -88" "classname" "light" } { "classname" "light" "origin" "336 -200 -88" "light" "150" } { "light" "150" "origin" "528 -432 -88" "classname" "light" } { "classname" "light" "origin" "296 -568 -88" "light" "150" } { "light" "150" "origin" "520 -584 -88" "classname" "light" } { "light" "150" "origin" "400 -360 -88" "classname" "light" } { "light" "150" "origin" "512 280 72" "classname" "light" } { "light" "200" "origin" "88 328 72" "classname" "light" } { "light" "150" "origin" "288 544 32" "classname" "light" } { "light" "200" "origin" "928 376 248" "classname" "light" } { "light" "150" "origin" "632 520 232" "classname" "light" } { "light" "150" "origin" "-64 -648 96" "classname" "light" } { "light" "125" "origin" "40 -760 120" "classname" "light" } { "light" "125" "origin" "216 -768 136" "classname" "light" } { "classname" "light" "origin" "384 -768 136" "light" "125" } { "light" "150" "origin" "272 -320 -80" "classname" "light" } { "light" "175" "origin" "-104 248 272" "classname" "light" } { "light" "125" "origin" "-104 96 272" "classname" "light" } { "light" "125" "origin" "-96 -424 272" "classname" "light" } { "classname" "light" "origin" "-96 -536 272" "light" "125" } { "light" "150" "origin" "280 864 192" "classname" "light" } { "classname" "light" "origin" "528 440 264" "light" "150" } { "classname" "light" "origin" "592 368 240" "light" "100" } { "classname" "light" "origin" "-96 -480 88" "light" "100" } { "classname" "light" "origin" "-144 -640 232" "light" "125" } { "light" "125" "origin" "88 -800 232" "classname" "light" } { "classname" "light" "origin" "-48 -800 232" "light" "125" } { "classname" "light" "origin" "744 -392 232" "light" "150" } { "origin" "584 -224 248" "classname" "light" "light" "125" } { "classname" "light" "origin" "736 -224 248" "light" "125" } { "origin" "440 -224 248" "classname" "light" "light" "125" } { "classname" "light" "origin" "536 360 -16" "light" "125" } { "classname" "light" "origin" "120 -224 248" "light" "150" } { "classname" "light" "origin" "-96 -536 112" "light" "150" } { "classname" "light" "origin" "-96 128 104" "light" "200" } { "light" "150" "origin" "440 -776 296" "classname" "light" } { "light" "100" "origin" "8 -376 80" "classname" "light" } { "spawnflags" "1" "origin" "-176 -704 16" "classname" "item_cells" } { "classname" "item_cells" "origin" "-176 -752 16" "spawnflags" "1" } { "classname" "light" "origin" "136 -640 232" "light" "125" } { "light" "125" "origin" "776 512 272" "classname" "light" } { "light" "125" "origin" "552 600 256" "classname" "light" } { "light" "125" "origin" "8 592 168" "classname" "light" } //{ //"classname" "item_artifact_invulnerability" //"origin" "648 8 -8" //} { "map" "dm6" "classname" "trigger_changelevel" "model" "*7" } { "mangle" "20 315 0" "origin" "112 552 232" "classname" "info_intermission" } { "classname" "info_intermission" "origin" "-72 248 312" "mangle" "20 45 0" } //Q-Man { "classname" "item_flag_team1" "origin" "292 960 120" } { "classname" "info_player_team1" "origin" "290 295 120" "angle" "90" } { "classname" "info_player_team1" "origin" "292 960 120" "angle" "270" } { "classname" "info_player_team1" "origin" "289 368 216" "angle" "90" } { "classname" "info_player_team1" "origin" "764 377 216" "angle" "180" } { "classname" "item_flag_team2" "origin" "1075 -769 216" } { "classname" "info_player_team2" "origin" "1075 -769 216" "angle" "180" } { "classname" "info_player_team2" "origin" "897 -387 216" "angle" "180" } { "classname" "info_player_team2" "origin" "607 -768 216" } { "classname" "info_player_team2" "origin" "248 -784 120" } { "origin" "700 -740 216" "spawnflags" "1" "classname" "item_health" } { "origin" "745 -740 216" "spawnflags" "1" "classname" "item_health" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/dm6.ent000066400000000000000000000267561475442401000251320ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/tim.wad" "message" "The Dark Zone" "worldtype" "0" "sounds" "5" } { "classname" "info_player_start" "origin" "760 -1080 256" "angle" "0" } { "origin" "1392 -1088 208" "classname" "light" "light" "250" } { "classname" "light" "origin" "448 -1504 312" "light" "150" } { "classname" "light" "origin" "440 -1640 344" "light" "225" } { "classname" "light" "origin" "184 -1736 400" "light" "300" } { "classname" "light" "origin" "328 -1736 400" } { "classname" "light" "origin" "336 -1912 400" } { "classname" "light" "origin" "184 -1912 400" } { "classname" "light" "origin" "656 -1088 80" "light" "250" } { "classname" "light" "origin" "360 -1088 152" "light" "250" } { "origin" "1496 -408 480" "classname" "light" "light" "400" } { "classname" "light" "origin" "200 -816 184" "light" "350" } { "classname" "info_teleport_destination" "origin" "308 -1788 44" "angle" "45" "targetname" "t1" } { "classname" "trigger_teleport" "target" "t1" "model" "*1" } { "classname" "info_teleport_destination" "origin" "200 -892 119" "angle" "270" "targetname" "t2" } { "classname" "trigger_teleport" "target" "t2" "model" "*2" } { "classname" "light_torch_small_walltorch" "origin" "1230 -626 196" } { "classname" "light_torch_small_walltorch" "origin" "1286 -294 196" } { "classname" "light_torch_small_walltorch" "origin" "1818 -1174 76" } { "classname" "light" "origin" "1656 -472 248" } { "classname" "light" "origin" "1656 -544 80" "light" "200" } { "classname" "light" "origin" "1744 -544 80" "light" "200" } { "classname" "light" "origin" "1500 -576 120" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "1642 -870 76" } { "classname" "light" "origin" "1432 -1088 64" } { "classname" "light" "origin" "1744 -1088 216" "light" "200" } { "light" "250" "classname" "light" "origin" "944 -1080 320" } { "light" "250" "classname" "light" "origin" "1104 -1080 320" } { "classname" "light" "origin" "1184 -1088 184" "light" "200" } { "classname" "light" "origin" "1016 -920 104" } { "classname" "light" "origin" "1016 -1256 104" } { "classname" "light" "origin" "1400 -336 104" "light" "200" } { "classname" "light" "origin" "1224 -888 16" "light" "200" } { "classname" "light" "origin" "824 -888 16" "light" "200" } { "classname" "light" "origin" "1224 -1296 16" "light" "200" } { "classname" "light" "origin" "824 -1288 16" "light" "200" } { "classname" "light" "origin" "728 -1088 168" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "978 -382 68" } { "classname" "light" "origin" "1024 -720 56" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "1074 -1718 68" } { "classname" "light" "origin" "1024 -1464 56" "light" "150" } { "classname" "light" "origin" "1304 -440 56" "light" "150" } { "classname" "light" "origin" "832 -1272 344" "light" "250" } { "classname" "light" "origin" "1208 -904 344" "light" "250" } { "classname" "light" "origin" "840 -904 344" "light" "250" } { "classname" "light" "origin" "1216 -1280 344" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "394 -1038 284" } { "classname" "light" "origin" "704 -1088 296" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "506 -1966 236" } { "classname" "light_torch_small_walltorch" "origin" "10 -1590 76" } { "classname" "light_torch_small_walltorch" "origin" "10 -2054 124" } { "classname" "light" "origin" "224 -1784 72" "light" "150" } { "classname" "light" "origin" "272 -1784 72" "light" "150" } { "classname" "light" "origin" "552 -1664 72" "light" "150" } { "classname" "light" "origin" "448 -1912 72" "light" "150" } { "classname" "light" "origin" "312 -1616 120" "light" "150" } { "classname" "light" "origin" "80 -1824 96" "light" "125" } { "classname" "light" "origin" "272 -2000 184" "light" "125" } { "classname" "light" "origin" "1744 -832 256" "light" "200" } { "classname" "light" "origin" "200 -880 144" "light" "250" } { "light" "200" "origin" "204 -944 336" "classname" "light" } { "origin" "192 -1348 240" "classname" "light_flame_small_yellow" } { "light" "150" "origin" "232 -1936 72" "classname" "light" } { "angle" "180" "origin" "232 -1512 40" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "1016 -416 40" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "0 -1088 264" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "456 -1504 256" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "408 -1088 256" "classname" "info_player_deathmatch" } { "spawnflags" "1" "origin" "928 -864 232" "classname" "item_health" } { "spawnflags" "1" "origin" "984 -864 232" "classname" "item_health" } { "spawnflags" "2" "origin" "192 -1264 88" "classname" "item_health" } { "origin" "1696 -1160 16" "classname" "item_health" } { "origin" "1224 -608 144" "classname" "item_health" } { "spawnflags" "4" "origin" "1264 -344 144" "classname" "item_weapon" } { "spawnflags" "1" "origin" "1048 -520 16" "classname" "item_health" } { "spawnflags" "1" "origin" "1048 -568 16" "classname" "item_health" } { "spawnflags" "1" "origin" "752 -1640 16" "classname" "item_weapon" } { "spawnflags" "9" "origin" "456 -2048 16" "classname" "item_weapon" } { "spawnflags" "1" "origin" "232 -1912 16" "classname" "item_health" } { "origin" "408 -1064 232" "classname" "item_health" } { "target" "t1" "classname" "trigger_teleport" "model" "*3" } { "spawnflags" "1" "origin" "872 -960 -64" "classname" "item_health" } { "spawnflags" "1" "origin" "1244 -1316 -64" "classname" "item_weapon" } { "classname" "light" "origin" "1488 -1088 240" } { "light" "200" "classname" "light" "origin" "1024 -840 368" } { "light" "200" "classname" "light" "origin" "1024 -1344 368" } { "origin" "1758 -298 196" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "1680 -344 104" "classname" "light" } { "spawnflags" "4" "origin" "1328 -280 144" "classname" "item_weapon" } { "spawnflags" "1" "origin" "304 -1944 16" "classname" "item_health" } { "light" "150" "origin" "1520 -280 80" "classname" "light" } { "spawnflags" "1" "origin" "1280 -1272 -64" "classname" "item_weapon" } { "classname" "item_weapon" "origin" "816 -1640 16" "spawnflags" "1" } { "classname" "item_health" "origin" "920 -1008 -64" "spawnflags" "1" } { "classname" "light" "origin" "168 -1512 56" "light" "150" } { "classname" "light" "origin" "968 -1460 272" "light" "150" } { "classname" "info_player_deathmatch" "origin" "896 -1464 256" "angle" "0" } { "classname" "light" "origin" "1696 -168 192" "light" "150" } { "classname" "light" "origin" "1872 -320 192" "light" "150" } { "classname" "light" "origin" "1880 -192 192" "light" "150" } { "classname" "info_player_deathmatch" "origin" "1892 -160 168" "angle" "225" } { "light" "100" "origin" "16 -1088 280" "classname" "light" } { "origin" "1224 -1088 -64" "classname" "weapon_nailgun" } { "origin" "1224 -1088 232" "classname" "weapon_grenadelauncher" } { "angle" "45" "origin" "424 -2008 144" "classname" "weapon_supernailgun" } { "angle" "180" "origin" "200 -1112 88" "classname" "weapon_rocketlauncher" } { "classname" "weapon_supershotgun" "origin" "1392 -584 16" } { "origin" "1736 -1112 144" "classname" "item_shells" } { "classname" "item_rockets" "origin" "264 -1632 36" } { "classname" "weapon_rocketlauncher" "origin" "1512 -432 36" } { "light" "125" "origin" "376 -2016 80" "classname" "light" } { "light" "100" "origin" "240 -2016 56" "classname" "light" } { "light" "125" "origin" "1224 -1088 -40" "classname" "light" } { "light" "125" "origin" "1392 -584 80" "classname" "light" } { "light" "150" "origin" "1024 -616 80" "classname" "light" } { "light" "150" "origin" "344 -1784 80" "classname" "light" } { "light" "150" "origin" "440 -1640 112" "classname" "light" } { "light" "150" "origin" "776 -1672 96" "classname" "light" } { "light" "150" "origin" "448 -1360 280" "classname" "light" } { "origin" "56 -2008 64" "classname" "item_armor1" } { "light" "125" "origin" "728 -1088 -8" "classname" "light" } { "angle" "180" "spawnflags" "4" "classname" "func_door_secret" "model" "*4" } { "light" "150" "origin" "840 -1088 -32" "classname" "light" } { "light" "150" "origin" "840 -1088 -120" "classname" "light" } { "target" "t3" "classname" "trigger_teleport" "model" "*5" } { "light" "200" "origin" "498 -984 -244" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "498 -1184 -244" "light" "200" } { "light" "200" "origin" "896 -1086 -244" "classname" "light_torch_small_walltorch" } { "targetname" "t3" "angle" "0" "origin" "1072 -1096 -32" "classname" "info_teleport_destination" } { "light" "150" "origin" "600 -1088 -264" "classname" "light" } { "origin" "760 -1080 -296" "classname" "weapon_lightning" } { "spawnflags" "1" "origin" "600 -1064 -296" "classname" "item_cells" } { "classname" "item_cells" "origin" "656 -1064 -296" "spawnflags" "1" } { "origin" "512 -1088 -272" "classname" "item_artifact_invisibility" } { "origin" "472 -1400 232" "classname" "item_cells" } { "classname" "item_cells" "origin" "472 -1352 232" } { "light" "125" "origin" "760 -1080 -272" "classname" "light" } { "classname" "info_intermission" "origin" "864 -1088 336" "mangle" "30 0 0" } { "map" "dm1" "classname" "trigger_changelevel" "model" "*6" } { "classname" "item_armorInv" "origin" "1736 -344 144" } /////////////////////////////////////////////// // Capture the flag mods { "origin" "200 -1304 130" "classname" "item_flag_team1" } /////// { "classname" "info_player_team1" "origin" "150 -1290 112" "angle" "90" } { "classname" "info_player_team1" "origin" "150 -1190 112" "angle" "90" } { "classname" "info_player_team1" "origin" "150 -1090 112" "angle" "90" } { "classname" "info_player_team1" "origin" "250 -1290 112" "angle" "90" } { "classname" "info_player_team1" "origin" "250 -1190 112" "angle" "90" } { "classname" "info_player_team1" "origin" "250 -1090 112" "angle" "90" } /////// { "origin" "1880 -168 168" "classname" "item_flag_team2" "angle" "90" } /////// { "angle" "180" "origin" "1764 -400 168" "classname" "info_player_team2" } { "angle" "180" "origin" "1764 -500 168" "classname" "info_player_team2" } { "angle" "180" "origin" "1764 -600 168" "classname" "info_player_team2" } { "angle" "180" "origin" "1764 -700 168" "classname" "info_player_team2" } { "angle" "180" "origin" "1764 -800 168" "classname" "info_player_team2" } { "angle" "180" "origin" "1764 -900 168" "classname" "info_player_team2" } /////// // base one weapons upgrade { "origin" "150 -1290 130" "classname" "item_shells" } { "origin" "200 -1290 130" "classname" "item_shells" } { "origin" "250 -1290 130" "classname" "item_shells" } { "origin" "150 -1240 130" "classname" "item_spikes" } { "origin" "200 -1240 130" "classname" "item_spikes" } { "origin" "250 -1240 130" "classname" "item_spikes" } { "origin" "150 -1190 130" "classname" "weapon_supershotgun" } { "origin" "200 -1190 130" "classname" "item_armor2" } { "origin" "250 -1190 130" "classname" "weapon_supernailgun" } { "classname" "item_health" "origin" "150 -1140 130" } { "classname" "item_health" "origin" "200 -1140 130" } { "classname" "item_health" "origin" "250 -1140 130" } // base two weapons upgrade { "classname" "item_shells" "origin" "1880 -218 168" } { "classname" "item_shells" "origin" "1880 -268 168" } { "classname" "item_shells" "origin" "1880 -318 168" } { "origin" "1880 -368 168" "classname" "weapon_supershotgun" } { "classname" "item_health" "origin" "1880 -418 168" } { "classname" "item_spikes" "origin" "1830 -168 168" } { "classname" "item_spikes" "origin" "1780 -168 168" } { "classname" "item_spikes" "origin" "1730 -168 168" } { "classname" "weapon_supernailgun" "origin" "1680 -168 168" } { "classname" "item_health" "origin" "1630 -168 168" } // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m1.ent000066400000000000000000000700251475442401000251730ustar00rootroot00000000000000{ "worldtype" "2" "sounds" "6" "classname" "worldspawn" "wad" "gfx/base.wad" "message" "the Slipgate Complex" } { "classname" "info_player_start" "origin" "480 -352 88" "angle" "90" } { "classname" "light" "origin" "480 96 168" "light" "250" } { "classname" "light" "origin" "480 288 168" "light" "250" } { "classname" "light" "origin" "272 96 80" } { "origin" "272 288 80" "classname" "light" } { "classname" "light" "origin" "272 192 80" } { "origin" "688 192 80" "classname" "light_fluorospark" "style" "10" } { "style" "10" "classname" "light" "origin" "688 288 80" } { "origin" "688 96 80" "classname" "light" "style" "10" } { "classname" "light" "origin" "480 -280 168" "light" "200" } { "origin" "480 -144 168" "classname" "light" "light" "200" } { "classname" "light" "origin" "480 -376 120" "light" "200" } { "light" "160" "origin" "480 -40 168" "classname" "light" } { "speed" "400" "sounds" "2" "angle" "270" "classname" "func_door" "model" "*1" } { "speed" "400" "angle" "90" "classname" "func_door" "model" "*2" } { "light" "250" "origin" "592 544 88" "classname" "light_fluoro" } { "origin" "456 600 104" "classname" "light" } { "light" "180" "origin" "688 648 136" "classname" "light" } { "classname" "light" "origin" "688 520 136" "light" "180" } { "origin" "688 480 80" "classname" "item_armor1" } { "angle" "180" "spawnflags" "768" "origin" "616 72 40" "classname" "monster_army" } { "light" "250" "origin" "0 576 120" "classname" "light" } { "light" "180" "origin" "160 576 72" "classname" "light" } { "light" "200" "origin" "560 -32 72" "classname" "light" } { "light" "200" "classname" "light" "origin" "400 -32 72" } { "light" "200" "origin" "0 712 72" "classname" "light" } { "classname" "light" "origin" "0 728 -136" "light" "200" } { "light" "200" "origin" "0 592 -136" "classname" "light" } { "wait" "5" "angle" "-2" "sounds" "2" "targetname" "t1" "classname" "func_door" "dmg" "10" "model" "*3" } { "sounds" "1" "target" "t1" "angle" "180" "classname" "func_button" "model" "*4" } { "light" "200" "origin" "412 780 136" "classname" "light" } { "light" "200" "classname" "light" "origin" "328 904 72" } { "light" "200" "origin" "168 800 72" "classname" "light" } { "light" "200" "classname" "light" "origin" "-72 864 72" } { "origin" "264 888 -136" "classname" "light" } { "classname" "light" "origin" "-8 992 -136" "light" "200" } { "light" "250" "classname" "light" "origin" "272 1064 -136" } { "light" "250" "origin" "-8 1232 -136" "classname" "light" } { "light" "250" "classname" "light" "origin" "256 1272 -136" } { "light" "250" "origin" "312 1464 -136" "classname" "light" } { "light" "200" "origin" "128 968 72" "classname" "light" } { "light" "250" "classname" "light" "origin" "-48 1168 72" } { "light" "250" "origin" "312 1168 72" "classname" "light" } { "light" "220" "classname" "light" "origin" "128 1504 -120" } { "light" "250" "classname" "light" "origin" "-56 1464 -136" } { "sounds" "2" "classname" "func_door" "angle" "180" "speed" "400" "model" "*5" } { "classname" "func_door" "angle" "0" "speed" "400" "model" "*6" } { "classname" "light_fluoro" "origin" "176 1744 -152" } { "origin" "80 1744 -152" "classname" "light_fluoro" } { "light" "250" "origin" "-232 1600 -136" "classname" "light" } { "light" "250" "classname" "light" "origin" "488 1600 -136" } { "origin" "-56 1448 72" "classname" "light" "light" "250" } { "light" "250" "classname" "light" "origin" "312 1448 72" } { "light" "260" "classname" "light_fluoro" "origin" "416 2064 -112" } { "light" "260" "origin" "416 1968 -112" "classname" "light_fluoro" } { "light" "250" "origin" "128 1880 -112" "classname" "light" } { "origin" "616 1944 -88" "classname" "light" } { "style" "10" "classname" "light_fluorospark" "origin" "344 2216 -88" } { "light" "180" "origin" "352 2016 -112" "classname" "light" } { "classname" "light" "origin" "128 2056 -112" "light" "250" } { "light" "250" "origin" "-112 1984 -112" "classname" "light" } { "light" "350" "origin" "-472 2064 -88" "classname" "light_fluoro" } { "classname" "light" "origin" "-192 2208 8" "light" "250" } { "light" "250" "origin" "-424 2208 8" "classname" "light" } { "light" "250" "origin" "-248 2088 -96" "classname" "light" } { "origin" "-200 2384 -72" "classname" "light" } { "classname" "light" "origin" "-424 2384 -72" } { "light" "200" "origin" "-448 2408 -128" "classname" "light" } { "classname" "light" "origin" "-176 2408 -128" "light" "200" } { "sounds" "1" "classname" "func_plat" "model" "*7" } { "light" "350" "origin" "-352 2656 184" "classname" "light" } { "light" "350" "classname" "light" "origin" "-352 2464 184" } { "origin" "-576 2800 -40" "classname" "light" } { "light" "500" "origin" "160 2920 232" "classname" "light" } { "classname" "light" "origin" "160 2720 232" "light" "500" } { "origin" "-288 2992 8" "classname" "light" } { "classname" "light" "origin" "-168 2776 -40" } { "classname" "light" "origin" "160 2824 104" "light" "200" } { "light" "150" "origin" "-64 2760 136" "classname" "light" } { "light" "200" "origin" "16 2832 -152" "classname" "light" } { "classname" "light" "origin" "304 2832 -152" "light" "200" } { "origin" "504 2816 16" "classname" "light" } { "sounds" "3" "wait" "-1" "speed" "600" "targetname" "t2" "spawnflags" "1" "angle" "270" "classname" "func_door" "model" "*8" } { "classname" "light" "origin" "160 2840 -152" "light" "200" } { "light" "80" "origin" "16 2904 -88" "classname" "light" } { "classname" "light" "origin" "304 2904 -88" "light" "80" } { "classname" "light" "origin" "160 2904 -88" "light" "80" } { "wait" "-1" "sounds" "1" "target" "t2" "speed" "50" "angle" "270" "classname" "func_button" "model" "*9" } { "light" "100" "origin" "0 1800 -32" "classname" "light" } { "classname" "light" "origin" "248 1800 -32" "light" "100" } { "style" "32" "targetname" "t3" "origin" "8 2352 200" "classname" "light" } { "style" "32" "targetname" "t3" "classname" "light" "origin" "32 2392 200" } { "style" "32" "targetname" "t3" "origin" "56 2352 200" "classname" "light" } { "style" "32" "targetname" "t3" "classname" "light" "origin" "32 2312 200" } { "style" "32" "targetname" "t3" "light" "200" "origin" "32 2352 88" "classname" "light" } { "spawnflags" "2048" "origin" "112 2352 16" "classname" "weapon_nailgun" } { "sounds" "3" "targetname" "t3" "spawnflags" "3" "angle" "270" "classname" "func_door_secret" "model" "*10" } { "style" "32" "sounds" "3" "target" "t3" "classname" "trigger_once" "model" "*11" } { "origin" "304 2368 96" "classname" "light" } { "angle" "180" "origin" "248 2392 40" "classname" "monster_army" } { "origin" "272 2352 64" "classname" "item_spikes" } { "style" "32" "sounds" "3" "target" "t3" "classname" "trigger_once" "model" "*12" } { "origin" "832 2608 16" "classname" "light" "light" "220" } { "light" "220" "classname" "light" "origin" "832 2480 0" } { "light" "240" "origin" "800 2816 24" "classname" "light" } { "style" "33" "targetname" "t11" "spawnflags" "1" "classname" "light" "origin" "752 2000 -88" "light" "400" } { "style" "34" "spawnflags" "1" "targetname" "t12" "origin" "1280 2000 -152" "classname" "light" "light" "400" } { "style" "35" "spawnflags" "1" "targetname" "t13" "classname" "light" "origin" "1280 2496 -216" "light" "400" } { "style" "36" "spawnflags" "1" "targetname" "t14" "origin" "784 2496 -280" "classname" "light" } { "classname" "light" "origin" "1368 2584 -488" "light" "200" } { "origin" "1368 1944 -488" "classname" "light" "light" "200" } { "classname" "light" "origin" "696 2584 -488" "light" "150" } { "origin" "1016 2584 -488" "classname" "light" "light" "200" } { "classname" "light" "origin" "1016 1944 -488" "light" "200" } { "origin" "1368 2272 -488" "classname" "light" "light" "200" } { "classname" "light" "origin" "696 2272 -488" "light" "200" } { "classname" "light" "origin" "960 2296 -488" "light" "200" } { "light" "200" "origin" "1032 2352 -488" "classname" "light" } { "classname" "light" "origin" "888 2352 -488" "light" "200" } { "light" "200" "origin" "960 2408 -488" "classname" "light" } { "light" "100" "classname" "light" "origin" "984 2448 -304" } { "classname" "light" "origin" "832 2360 112" "light" "400" } { "classname" "light" "origin" "1144 2448 -488" } { "origin" "1232 2360 -488" "classname" "light" } { "classname" "light" "origin" "1320 2448 -488" "light" "200" } { "light" "200" "origin" "1232 2536 -488" "classname" "light" } { "classname" "light" "origin" "1232 2136 -488" } { "origin" "1144 2048 -488" "classname" "light" } { "classname" "light" "origin" "1232 1960 -488" "light" "200" } { "light" "200" "origin" "1320 2048 -488" "classname" "light" } { "classname" "light" "origin" "832 2336 -200" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2" "sounds" "3" "model" "*13" } { "classname" "func_door_secret" "angle" "180" "sounds" "3" "model" "*14" } { "classname" "light" "origin" "552 2480 -56" "light" "200" } { "light" "200" "origin" "544 2296 -56" "classname" "light" } { "classname" "light" "origin" "664 2480 -56" "light" "200" } { "classname" "func_door" "targetname" "t4" "angle" "-2" "spawnflags" "1" "sounds" "2" "model" "*15" } { "classname" "trigger_multiple" "target" "t4" "health" "1" "model" "*16" } { "spawnflags" "2048" "classname" "func_door" "angle" "90" "targetname" "t5" "wait" "-1" "sounds" "2" "model" "*17" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t5" "model" "*18" } { "classname" "item_artifact_super_damage" "origin" "544 2480 -88" } { "classname" "light" "origin" "832 2104 -208" } { "classname" "light" "origin" "832 2048 -368" "light" "150" } { "classname" "light" "origin" "1120 2464 112" } { "origin" "1120 2080 112" "classname" "light" } { "classname" "light" "origin" "752 2080 112" "light" "200" } { "classname" "light" "origin" "1048 2280 -72" } { "classname" "func_button" "angle" "270" "target" "t1" "model" "*19" } { "classname" "light" "origin" "1136 1848 -504" "light" "220" } { "origin" "1136 1672 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1008 1672 -504" "light" "220" } { "origin" "1008 1848 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1288 1848 -504" "light" "220" } { "origin" "1400 1584 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1224 1584 -504" "light" "220" } { "origin" "1400 1736 -504" "classname" "light" "light" "220" } { "origin" "880 1672 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "744 1672 -504" "light" "220" } { "classname" "light" "origin" "1312 1648 -392" "light" "220" } { "light" "170" "origin" "1312 1520 -392" "classname" "light" } { "classname" "light" "origin" "1200 1760 -392" "light" "220" } { "light" "170" "origin" "1072 1760 -392" "classname" "light" } { "classname" "light" "origin" "944 1760 -392" "light" "170" } { "origin" "832 1992 -208" "classname" "light" "light" "220" } { "origin" "744 1832 -504" "classname" "light" } { "light" "170" "origin" "832 1760 -392" "classname" "light" } { "light" "220" "origin" "680 1936 -504" "classname" "light" } { "classname" "light" "origin" "1312 1392 -352" "light" "170" } { "light" "170" "origin" "1312 1264 -288" "classname" "light" } { "classname" "light" "origin" "1312 1136 -232" } { "origin" "1224 1456 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1400 1456 -504" "light" "220" } { "origin" "1400 1328 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1224 1328 -504" "light" "220" } { "origin" "1224 1200 -504" "classname" "light" "light" "220" } { "classname" "light" "origin" "1400 1200 -504" "light" "220" } { "origin" "1312 960 -208" "classname" "light" } { "classname" "trigger_teleport" "target" "t6" "model" "*20" } { "classname" "light" "origin" "1312 912 -472" } { "classname" "light" "origin" "1312 1080 -368" } { "classname" "light" "origin" "1128 1064 -504" "light" "170" } { "origin" "1128 856 -504" "classname" "light" "light" "170" } { "classname" "light" "origin" "1496 856 -504" "light" "170" } { "origin" "1496 1064 -504" "classname" "light" "light" "170" } { "classname" "light" "origin" "1312 776 -504" "light" "170" } //remove the door? { //"spawnflags" "2" // this was it, we must lock "spawnflags" "34" "angle" "90" "classname" "func_door_secret" "model" "*21" } { "origin" "1072 1024 -168" "classname" "light" } { "spawnflags" "1" "height" "400" "angle" "-1" "sounds" "1" "classname" "func_plat" "model" "*22" } { "targetname" "t8" "spawnflags" "2" "angle" "90" "classname" "func_door_secret" "model" "*23" } { "target" "t8" "classname" "trigger_multiple" "model" "*24" } { "light" "220" "origin" "792 888 -248" "classname" "light" } { "light" "180" "classname" "light" "origin" "944 608 -248" } { "light" "150" "origin" "792 512 -248" "classname" "light" } { "classname" "light" "origin" "792 512 -56" "light" "150" } { "classname" "light" "origin" "624 928 -240" "light" "220" } { "light" "220" "origin" "504 1200 -248" "classname" "light" } { "origin" "936 800 -248" "classname" "light" "light" "180" } { "light" "180" "classname" "light" "origin" "960 984 -208" } { "classname" "light" "origin" "792 512 128" "light" "150" } { "spawnflags" "2" "origin" "944 1008 -272" "classname" "item_health" } { "spawnflags" "1792" "origin" "144 2352 16" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "1216 1040 -432" "classname" "weapon_grenadelauncher" } { "spawnflags" "1793" "origin" "1392 1024 -432" "classname" "item_rockets" } { "targetname" "t6" "origin" "-32 1800 -56" "classname" "info_teleport_destination" } { "spawnflags" "1792" "origin" "832 2448 -368" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "128 1216 -208" "classname" "weapon_supershotgun" } { "origin" "296 2136 -192" "classname" "item_shells" } { "spawnflags" "1" "origin" "1424 904 -432" "classname" "item_health" } { "classname" "item_health" "origin" "1376 808 -432" } { "origin" "1176 936 -432" "classname" "item_health" } { "spawnflags" "2048" "target" "t9" "wait" "-1" "angle" "0" "classname" "func_button" "model" "*25" } { "spawnflags" "2048" "target" "t9" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*26" } { "spawnflags" "2048" "target" "t9" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*27" } { "target" "t10" "targetname" "t9" "count" "3" "classname" "trigger_counter" "model" "*28" } { "message" "You must press the three buttons..." "spawnflags" "2048" "sounds" "2" "wait" "-1" "targetname" "t10" "angle" "180" "classname" "func_door" "model" "*29" } { "light" "150" "origin" "832 1928 -384" "classname" "light" } { "style" "33" "sounds" "3" "target" "t11" "classname" "trigger_once" "model" "*30" } { "style" "34" "sounds" "3" "target" "t12" "classname" "trigger_once" "model" "*31" } { "style" "35" "sounds" "3" "target" "t13" "classname" "trigger_once" "model" "*32" } { "style" "36" "sounds" "3" "target" "t14" "classname" "trigger_once" "model" "*33" } { "sounds" "1" "wait" "-1" "targetname" "t11" "spawnflags" "1" "angle" "-2" "classname" "func_door" "model" "*34" } { "targetname" "t12" "classname" "func_door" "angle" "-2" "spawnflags" "1" "wait" "-1" "sounds" "1" "model" "*35" } { "targetname" "t13" "sounds" "1" "wait" "-1" "spawnflags" "1" "angle" "-2" "classname" "func_door" "model" "*36" } { "targetname" "t14" "classname" "func_door" "angle" "-2" "spawnflags" "1" "wait" "-1" "sounds" "1" "model" "*37" } { "angle" "90" "origin" "1312 880 -248" "classname" "info_player_deathmatch" } { "spawnflags" "1" "origin" "1376 1024 -272" "classname" "item_spikes" } { "origin" "1184 992 -272" "classname" "item_health" } { "spawnflags" "1" "origin" "1376 856 -272" "classname" "item_health" } { "spawnflags" "1" "origin" "1256 1704 -432" "classname" "item_health" } { "angle" "90" "origin" "480 48 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "528 1888 -168" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-272 2928 -56" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "832 2048 -152" "classname" "info_player_deathmatch" } { "speed" "300" "message" "This door opens elsewhere..." "spawnflags" "2048" "targetname" "t15" "angle" "270" "classname" "func_door" "wait" "-1" "model" "*38" } { "spawnflags" "2048" "target" "t15" "classname" "trigger_once" "model" "*39" } { "spawnflags" "1792" "origin" "480 576 0" "classname" "weapon_nailgun" } { "spawnflags" "1793" "origin" "464 728 64" "classname" "item_spikes" } { "origin" "328 848 -224" "classname" "item_health" } { "classname" "item_health" "origin" "344 920 -224" } { "spawnflags" "1" "origin" "-16 2064 -208" "classname" "item_health" } { "spawnflags" "1792" "origin" "-480 2240 -160" "classname" "item_rockets" } { "spawnflags" "1793" "origin" "-96 2456 16" "classname" "item_shells" } { "classname" "item_rockets" "origin" "-104 2216 16" "spawnflags" "1793" } { "classname" "item_artifact_invulnerability" "origin" "256 1808 -40" "spawnflags" "1792" } { "classname" "monster_army" "origin" "0 576 24" "angle" "0" "spawnflags" "256" } { "classname" "monster_army" "origin" "8 1520 -200" "angle" "270" } { "classname" "monster_dog" "origin" "88 1520 -200" "angle" "270" } { "classname" "monster_army" "origin" "224 1552 -200" "angle" "270" "spawnflags" "768" } { "spawnflags" "768" "angle" "270" "origin" "-8 936 -200" "classname" "monster_army" } { "classname" "monster_army" "origin" "648 736 104" "spawnflags" "768" "angle" "180" } { "classname" "item_artifact_envirosuit" "origin" "712 2040 -408" "angle" "90" } { "classname" "light" "origin" "712 2040 -360" "light" "100" } { "classname" "item_rockets" "origin" "1328 2536 -528" "spawnflags" "1793" } { "classname" "item_health" "origin" "916 2416 -136" "spawnflags" "2" } { "spawnflags" "1" "classname" "monster_army" "origin" "1312 936 -248" "angle" "90" } { "classname" "monster_dog" "origin" "1336 1784 -408" "angle" "180" "spawnflags" "257" } { "spawnflags" "257" "angle" "90" "origin" "1392 928 -248" "classname" "monster_army" } { "classname" "monster_army" "origin" "1384 1008 -248" "angle" "90" "spawnflags" "768" } { "spawnflags" "768" "angle" "90" "origin" "1240 1008 -248" "classname" "monster_army" } { "classname" "monster_army" "origin" "1256 1760 -408" "angle" "180" "spawnflags" "257" } { "classname" "monster_army" "origin" "824 1784 -408" "spawnflags" "257" "angle" "90" } { "classname" "monster_dog" "origin" "1128 1760 -408" "angle" "180" "spawnflags" "769" } { "classname" "path_corner" "origin" "880 2048 -168" "target" "t16" "targetname" "t17" } { "origin" "1232 2048 -232" "classname" "path_corner" "targetname" "t16" "target" "t17" } { "classname" "monster_army" "origin" "1232 2088 -216" "target" "t16" } { "classname" "monster_army" "origin" "1232 2448 -280" "angle" "270" "spawnflags" "256" } { "classname" "monster_army" "origin" "832 2464 -344" "angle" "0" "spawnflags" "256" } { "classname" "monster_army" "origin" "832 2072 -408" "angle" "90" } { "classname" "monster_dog" "origin" "840 1960 -408" "angle" "90" "spawnflags" "768" } { "classname" "trigger_multiple" "target" "t18" "health" "1" "model" "*40" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2" "targetname" "t18" "model" "*41" } { "classname" "weapon_supershotgun" "origin" "-360 2912 -80" } { "classname" "trigger_multiple" "target" "t18" "model" "*42" } { "classname" "light" "origin" "-352 2912 -24" "light" "120" } { "classname" "light" "origin" "160 3024 0" "light" "120" } { "classname" "item_shells" "origin" "528 720 80" } { "classname" "monster_army" "origin" "416 1912 -168" "angle" "180" "spawnflags" "768" } { "classname" "monster_dog" "origin" "432 2120 -168" "angle" "180" "spawnflags" "256" } { "classname" "path_corner" "origin" "248 1992 -200" "targetname" "t19" "target" "t20" } { "origin" "-200 1992 -200" "classname" "path_corner" "targetname" "t20" "target" "t21" } { "classname" "path_corner" "origin" "-136 1912 -200" "targetname" "t21" "target" "t22" } { "origin" "248 1912 -200" "classname" "path_corner" "target" "t19" "targetname" "t22" } { "classname" "monster_army" "origin" "80 2024 -184" "target" "t20" } { "classname" "monster_army" "origin" "-16 1888 -184" "spawnflags" "256" "target" "t22" } { "classname" "monster_dog" "origin" "-248 2144 -136" "spawnflags" "768" "angle" "315" } { "classname" "path_corner" "origin" "-560 2352 40" "targetname" "t23" "target" "t24" } { "origin" "-104 2352 40" "classname" "path_corner" "target" "t23" "targetname" "t24" } { "classname" "monster_army" "origin" "-432 2352 56" "spawnflags" "768" "target" "t23" } { "angle" "0" "classname" "monster_dog" "origin" "-544 2584 56" "spawnflags" "256" } { "classname" "monster_army" "origin" "-344 2656 -104" "angle" "270" } { "classname" "monster_dog" "origin" "-72 2896 -56" "spawnflags" "256" "angle" "225" } { "classname" "monster_army" "origin" "432 2920 -56" "target" "t25" } { "classname" "monster_army" "origin" "424 2832 -56" "spawnflags" "256" "angle" "180" } { "classname" "path_corner" "origin" "368 2936 -72" "targetname" "t25" "target" "t26" } { "origin" "368 2696 -72" "classname" "path_corner" "targetname" "t26" "target" "t27" } { "classname" "path_corner" "origin" "480 2696 -72" "targetname" "t27" "target" "t28" } { "origin" "480 2936 -72" "classname" "path_corner" "target" "t25" "targetname" "t28" } { "classname" "monster_army" "origin" "424 2672 -56" "target" "t27" } { "classname" "monster_army" "origin" "424 2880 -56" "angle" "180" "spawnflags" "768" } { "classname" "monster_army" "origin" "424 2760 -56" "spawnflags" "768" "angle" "180" } { "classname" "path_corner" "origin" "832 2712 -88" "targetname" "t29" "target" "t30" } { "origin" "832 2416 -104" "classname" "path_corner" "target" "t29" "targetname" "t30" } { "classname" "monster_army" "origin" "848 2584 -72" "spawnflags" "257" "target" "t29" } { "classname" "monster_army" "origin" "824 2008 -152" "angle" "90" "spawnflags" "768" } { "classname" "item_health" "origin" "-376 1704 -224" "spawnflags" "1" } { "angle" "180" "spawnflags" "768" "origin" "248 2352 40" "classname" "monster_army" } { "spawnflags" "768" "angle" "270" "origin" "-72 2464 40" "classname" "monster_army" } { "spawnflags" "768" "angle" "225" "origin" "904 1024 -248" "classname" "monster_army" } { "light" "100" "style" "10" "classname" "light" "origin" "688 0 80" } { "message" "Shoot this secret door..." "spawnflags" "1" "angle" "0" "classname" "func_door_secret" "model" "*43" } { "origin" "672 -40 48" "classname" "item_shells" } { "classname" "trigger_secret" "model" "*44" } { "classname" "trigger_secret" "model" "*45" } { "classname" "trigger_secret" "model" "*46" } { "classname" "trigger_secret" "model" "*47" } { "classname" "trigger_secret" "model" "*48" } { "classname" "trigger_secret" "model" "*49" } { "light" "100" "origin" "0 632 -88" "classname" "light" } { "classname" "item_health" "origin" "600 2200 -128" "spawnflags" "1" } { "light" "220" "classname" "light" "origin" "832 1880 -504" } { "origin" "72 2056 -208" "classname" "misc_explobox" } { "light" "200" "origin" "-128 584 72" "classname" "light" } { "light" "200" "origin" "-128 568 -136" "classname" "light" } { "light" "100" "origin" "-56 632 -168" "classname" "light" } { "light" "200" "origin" "-56 864 -136" "classname" "light" } { "light" "200" "origin" "40 1672 -40" "classname" "light" } { "classname" "light" "origin" "216 1672 -40" "light" "200" } { "classname" "light" "origin" "128 1080 -152" "light" "200" } { "light" "200" "origin" "128 1096 72" "classname" "light" } { "light" "250" "classname" "light" "origin" "-352 1656 72" } { "origin" "608 1640 72" "classname" "light" "light" "250" } { "origin" "-48 1144 -320" "classname" "light" "light" "170" } { "light" "170" "classname" "light" "origin" "-48 1256 -320" } { "origin" "320 1256 -320" "classname" "light" "light" "170" } { "light" "170" "classname" "light" "origin" "312 1128 -320" } { "origin" "136 1128 -320" "classname" "light" "light" "170" } { "light" "170" "classname" "light" "origin" "136 1272 -320" } { "spawnflags" "3072" "wait" "5" "sounds" "2" "message" "You can jump across..." "classname" "trigger_multiple" "targetname" "t32" "model" "*50" } { "spawnflags" "3072" "wait" "5" "message" "You can jump up here..." "sounds" "2" "classname" "trigger_multiple" "targetname" "t31" "model" "*51" } { "light" "150" "origin" "1008 2128 -408" "classname" "light" } { "light" "250" "origin" "1312 544 -184" "classname" "light" } { "light" "200" "classname" "light" "origin" "1208 456 -184" } { "origin" "1416 456 -184" "classname" "light" "light" "200" } { "light" "170" "origin" "1312 728 -56" "classname" "light" } { "map" "e1m2" "classname" "trigger_changelevel" "model" "*52" } { "classname" "item_health" "origin" "1224 2464 -304" "spawnflags" "1" } { "classname" "light" "origin" "688 1680 -160" "light" "160" } { "light" "160" "origin" "-392 1688 -160" "classname" "light" } { "spawnflags" "768" "angle" "270" "origin" "288 1536 -200" "classname" "monster_army" } { "spawnflags" "768" "origin" "968 2432 -112" "classname" "monster_army" } { "wait" "5" "message" "Walk into the slipgate to exit." "classname" "trigger_multiple" "sounds" "2" "angle" "270" "model" "*53" } { "classname" "trigger_once" "killtarget" "t31" "target" "t31" "spawnflags" "3072" "model" "*54" } { "classname" "trigger_once" "spawnflags" "3072" "target" "t32" "killtarget" "t32" "model" "*55" } { "classname" "item_armor2" "origin" "1312 1048 -432" } { "classname" "ambient_comp_hum" "origin" "250 194 72" } { "origin" "714 194 72" "classname" "ambient_comp_hum" } { "classname" "ambient_comp_hum" "origin" "626 2058 -104" } { "origin" "466 2226 -104" "classname" "ambient_comp_hum" } { "classname" "info_intermission" "origin" "-112 704 56" "mangle" "20 45 0" } { "classname" "info_intermission" "origin" "-208 2736 192" "mangle" "20 225 0" } { "classname" "info_intermission" "origin" "240 2664 104" "mangle" "20 120 0" } { "classname" "info_intermission" "origin" "1376 1936 64" "mangle" "20 135 0" } { "angle" "90" "origin" "528 -296 72" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "432 -296 72" "angle" "90" } { "angle" "90" "origin" "480 -240 72" "classname" "info_player_coop" } { "classname" "func_wall" "spawnflags" "1792" "model" "*56" } { "classname" "func_wall" "spawnflags" "1792" "model" "*57" } { "classname" "ambient_drone" "origin" "1314 450 -200" } // // Capture the flag map mods // // capture spawns // team1 { "origin" "480 -52 40" "classname" "item_flag_team1" } { "angle" "90" "origin" "540 128 24" "classname" "info_player_team1" } { "angle" "90" "origin" "420 128 24" "classname" "info_player_team1" } { "angle" "90" "origin" "540 188 24" "classname" "info_player_team1" } { "angle" "90" "origin" "420 188 24" "classname" "info_player_team1" } { "angle" "90" "origin" "540 268 24" "classname" "info_player_team1" } { "angle" "90" "origin" "420 268 24" "classname" "info_player_team1" } // team2 { "origin" "1312 640 -256" "classname" "item_flag_team2" } { "angle" "90" "origin" "1232 920 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1312 920 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1392 920 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1232 1000 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1312 1000 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1392 1000 -256" "classname" "info_player_team2" } { "angle" "90" "origin" "1312 920 -256" "classname" "info_player_team2" } // base one weapons upgrade { "origin" "432 528 0" "classname" "item_shells" } { "origin" "480 528 0" "classname" "item_shells" } { "origin" "528 528 0" "classname" "item_shells" } { "origin" "432 480 0" "classname" "item_spikes" } { "origin" "480 480 0" "classname" "item_spikes" } { "origin" "528 480 0" "classname" "item_spikes" } { "origin" "432 432 0" "classname" "weapon_supershotgun" } { "origin" "480 432 0" "classname" "item_armor2" } { "origin" "528 432 0" "classname" "weapon_supernailgun" } { "classname" "item_health" "origin" "432 384 0" } { "classname" "item_health" "origin" "480 384 0" } { "classname" "item_health" "origin" "528 384 0" } // base two weapons upgrade { "classname" "item_shells" "origin" "1264 700 -272" } { "classname" "item_shells" "origin" "1312 700 -272" } { "classname" "item_shells" "origin" "1360 700 -272" } { "classname" "item_spikes" "origin" "1264 748 -272" } { "classname" "item_spikes" "origin" "1312 748 -272" } { "classname" "item_spikes" "origin" "1360 748 -272" } { "origin" "1264 792 -272" "classname" "weapon_supershotgun" } { "classname" "item_armor2" "origin" "1312 792 -272" } { "classname" "weapon_supernailgun" "origin" "1360 792 -272" } // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m2.ent000066400000000000000000001250531475442401000251760ustar00rootroot00000000000000{ "message" "Castle of the Damned" "wad" "gfx/wizard.wad" "classname" "worldspawn" "worldtype" "0" "sounds" "8" } { "angle" "270" "origin" "1496 1664 296" "classname" "info_player_start" } { "origin" "1432 672 336" "classname" "light" "light" "250" } { "light" "200" "origin" "1496 888 272" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "932 640 340" } { "classname" "light_torch_small_walltorch" "origin" "1104 812 340" } { "classname" "light" "origin" "1104 640 544" "light" "300" } { "light" "175" "origin" "1216 536 353" "classname" "light" } { "light" "250" "origin" "1816 328 448" "classname" "light" } { "light" "200" "origin" "1632 472 208" "classname" "light" } { "light" "200" "origin" "1792 -392 240" "classname" "light" } { "light" "200" "origin" "1452 -124 508" "classname" "light" } { "light" "150" "origin" "1196 -124 508" "classname" "light" } { "light" "150" "origin" "1044 -124 508" "classname" "light" } { "light" "200" "origin" "756 -124 508" "classname" "light" } { "light" "250" "origin" "744 336 145" "classname" "light" } { "light" "200" "origin" "1176 -912 672" "classname" "light" } { "origin" "1328 -544 552" "classname" "light" } { "classname" "light" "origin" "1528 -912 640" "light" "200" } { "light" "200" "classname" "light" "origin" "880 -648 672" } { "origin" "240 -264 392" "classname" "light" "light" "250" } { "classname" "light" "origin" "-352 -504 464" "light" "200" } { "origin" "-448 -608 804" "classname" "light" "light" "450" } { "light" "250" "origin" "776 -912 472" "classname" "light" } { "light" "300" "origin" "1630 -806 428" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "1528 -912 464" "classname" "light" } { "classname" "light" "origin" "1180 -484 560" } { "classname" "light" "origin" "1184 -612 560" } { "classname" "light" "origin" "1016 -368 472" "light" "100" } { "classname" "light" "origin" "1016 -464 472" "light" "100" } { "classname" "light" "origin" "1020 -560 472" "light" "100" } { "classname" "light" "origin" "1208 -776 472" "light" "100" } { "classname" "light" "origin" "1288 -776 472" "light" "100" } { "classname" "light" "origin" "1360 -776 472" "light" "100" } { "light" "200" "origin" "1792 120 376" "classname" "light" } { "origin" "1538 182 356" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "1640 80 360" "classname" "light" } { "light" "200" "origin" "1928 80 360" "classname" "light" } { "light" "250" "origin" "1792 296 208" "classname" "light" } { "light" "150" "origin" "1800 40 160" "classname" "light" } { "light" "200" "origin" "1776 -392 160" "classname" "light" } { "light" "200" "origin" "1304 -392 152" "classname" "light" } { "light" "250" "origin" "1632 112 136" "classname" "light" } { "light" "250" "origin" "1432 312 136" "classname" "light" } { "light" "200" "origin" "1136 -656 160" "classname" "light" } { "light" "200" "origin" "1136 -416 160" "classname" "light" } { "light" "250" "origin" "1448 -552 160" "classname" "light" } { "light" "200" "origin" "1920 440 136" "classname" "light" } { "light" "200" "origin" "968 88 177" "classname" "light" } { "light" "300" "origin" "1088 312 129" "classname" "light" } { "light" "150" "origin" "1376 168 129" "classname" "light" } { "light" "250" "origin" "112 -384 392" "classname" "light" } { "origin" "300 -1004 508" "classname" "light" } { "origin" "296 -812 505" "classname" "light" } { "origin" "300 -1204 505" "classname" "light" } { "light" "150" "origin" "470 -1006 468" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "984 -1216 496" "classname" "light" } { "light" "250" "origin" "888 -1128 552" "classname" "light" } { "light" "200" "origin" "800 -1216 592" "classname" "light" } { "light" "200" "origin" "664 -1216 592" "classname" "light" } { "light" "200" "origin" "584 -1136 592" "classname" "light" } { "light" "200" "origin" "584 -968 592" "classname" "light" } { "light" "250" "origin" "584 -744 592" "classname" "light" } { "light" "200" "origin" "528 -1144 464" "classname" "light" } { "light" "200" "origin" "528 -856 464" "classname" "light" } { "light" "200" "classname" "light" "origin" "1496 1544 440" } { "origin" "1384 1392 440" "classname" "light" "light" "250" } { "origin" "1496 1104 520" "classname" "light" } { "origin" "1608 1400 440" "classname" "light" "light" "250" } { "light" "250" "origin" "1240 1712 360" "classname" "light" } { "light" "250" "origin" "1744 1696 360" "classname" "light" } { "classname" "light" "origin" "1384 1136 440" "light" "250" } { "classname" "light" "origin" "1608 1144 440" "light" "250" } { "classname" "path_corner" "origin" "1168 736 296" "targetname" "t5" "target" "t6" } { "classname" "path_corner" "origin" "992 744 296" "targetname" "t6" "target" "t7" } { "classname" "path_corner" "origin" "1000 544 296" "targetname" "t7" "target" "t34" } { "classname" "item_health" "origin" "960 704 288" } { "classname" "item_shells" "origin" "952 512 288" } { "classname" "path_corner" "origin" "1344 -128 304" "targetname" "t9" "target" "t8" } { "classname" "path_corner" "origin" "898 -128 304" "targetname" "t8" "target" "t9" } { "spawnflags" "1" "classname" "monster_ogre" "origin" "1018 -126 320" "angle" "0" "target" "t8" } { "classname" "item_health" "origin" "1344 -224 296" "spawnflags" "1" } { "classname" "item_health" "origin" "1400 -224 296" "spawnflags" "1" } { "origin" "1528 192 296" "classname" "item_shells" } { "classname" "path_corner" "origin" "1496 1040 184" "targetname" "t22" "target" "t23" } { "classname" "path_corner" "origin" "1496 840 248" "targetname" "t23" "target" "t33" } { "spawnflags" "1" "classname" "item_shells" "origin" "1056 -648 288" } { "classname" "item_health" "origin" "1184 -736 288" } { "spawnflags" "257" "classname" "monster_army" "origin" "1646 -698 360" "angle" "180" "targetname" "t89" } { "classname" "path_corner" "origin" "1400 640 272" "targetname" "t30" "target" "t79" } { "classname" "path_corner" "origin" "1496 752 232" "targetname" "t33" "target" "t77" } { "classname" "path_corner" "origin" "1192 560 296" "targetname" "t34" "target" "t80" } { "classname" "item_shells" "origin" "1616 1280 176" } { "classname" "item_health" "origin" "1056 -840 416" "spawnflags" "1" } { "classname" "item_health" "origin" "1104 -840 416" "spawnflags" "1" } { "spawnflags" "1" "classname" "monster_army" "origin" "262 -458 320" "angle" "0" "target" "t96" } { "spawnflags" "1024" "classname" "item_health" "origin" "136 -296 296" } { "classname" "path_corner" "origin" "-536 -704 472" "targetname" "t42" "target" "t41" } { "classname" "path_corner" "origin" "-576 -416 472" "targetname" "t41" "target" "t42" } { "classname" "monster_knight" "origin" "-578 -654 480" "target" "t41" "spawnflags" "1" } { "classname" "item_shells" "origin" "-368 -752 456" } { "classname" "item_health" "origin" "-16 -520 360" "spawnflags" "1" } { "classname" "item_health" "origin" "-16 -576 360" "spawnflags" "1" } { "classname" "light" "origin" "1848 -568 320" "light" "200" } { "classname" "light" "origin" "1760 -560 408" "light" "200" } { "classname" "light" "origin" "1624 -560 352" "light" "150" } { "targetname" "t43" "angle" "270" "origin" "800 368 312" "classname" "info_teleport_destination" } { "origin" "752 168 296" "classname" "item_health" } { "target" "t43" "classname" "trigger_teleport" "model" "*1" } { "origin" "1712 -568 256" "classname" "item_health" } { "classname" "monster_ogre" "origin" "1494 1134 208" "angle" "270" "target" "t22" } { "light" "300" "origin" "1856 1288 384" "classname" "light" } { "classname" "light" "origin" "1136 1288 384" } { "light" "200" "origin" "1920 328 380" "classname" "light" } { "target" "t122" "spawnflags" "2048" "sounds" "1" "classname" "item_key1" "origin" "880 -300 464" } { "light" "300" "origin" "648 -384 430" "classname" "light_flame_small_yellow" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "1104 -224 406" } { "light" "250" "origin" "1456 -128 406" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "988 532 353" "light" "175" } { "light" "125" "origin" "1100 648 328" "classname" "light" } { "origin" "1616 936 310" "classname" "light_flame_small_yellow" "light" "300" } { "light" "300" "classname" "light_flame_small_yellow" "origin" "1360 936 310" } { "origin" "1792 504 390" "classname" "light_flame_small_yellow" "light" "300" } { "origin" "1972 -252 332" "classname" "info_null" "targetname" "t47" } { "light" "800" "origin" "1992 -252 336" "classname" "light" "target" "t47" } { "classname" "info_null" "origin" "1948 -292 332" "targetname" "t48" } { "light" "800" "classname" "light" "origin" "1948 -312 336" "target" "t48" } { "origin" "880 -328 562" "classname" "light_flame_small_yellow" "light" "300" } { "classname" "light" "origin" "1056 -1288 504" } { "origin" "1184 -1288 504" "classname" "light" } { "classname" "light" "origin" "1312 -1288 504" } { "origin" "1440 -1288 504" "classname" "light" } { "sounds" "1" "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t50" "model" "*2" } { "sounds" "1" "classname" "func_door" "wait" "-1" "angle" "-2" "targetname" "t50" "model" "*3" } { "classname" "trigger_once" "target" "t50" "model" "*4" } { "classname" "light" "origin" "1368 -1016 504" "light" "200" } { "light" "200" "origin" "1120 -1024 504" "classname" "light" } { "classname" "light" "origin" "1248 -1184 464" "light" "175" } { "classname" "light" "origin" "776 -480 480" "light" "225" } { "classname" "light" "origin" "1904 -144 168" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "1706 -206 316" "light" "300" } { "light" "300" "origin" "2134 -34 316" "classname" "light_torch_small_walltorch" } { "origin" "1152 -296 422" "classname" "light_flame_small_yellow" "light" "250" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "1152 -760 422" } { "origin" "1528 -556 478" "classname" "light_flame_small_yellow" "light" "250" } { "targetname" "t52" "origin" "1532 -552 328" "classname" "info_null" } { "origin" "1340 -544 384" "classname" "item_armor2" } { "sounds" "1" "targetname" "t53" "lip" "64" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*5" } { "sounds" "1" "targetname" "t53" "classname" "func_door" "angle" "-1" "wait" "-1" "lip" "64" "model" "*6" } { "targetname" "t53" "target" "t54" "classname" "trigger_teleport" "spawnflags" "2" "model" "*7" } { "targetname" "t54" "angle" "180" "origin" "1408 -688 449" "classname" "info_teleport_destination" } { "targetname" "t53" "target" "t57" "classname" "trigger_teleport" "spawnflags" "2" "model" "*8" } { "targetname" "t57" "angle" "180" "origin" "1408 -400 361" "classname" "info_teleport_destination" } { "spawnflags" "768" "targetname" "t53" "angle" "180" "origin" "1912 -856 217" "classname" "monster_wizard" } { "spawnflags" "768" "targetname" "t53" "classname" "monster_wizard" "origin" "1912 -936 217" "angle" "180" } { "targetname" "t50" "angle" "90" "origin" "1320 -1112 441" "classname" "monster_knight" } { "spawnflags" "256" "targetname" "t50" "angle" "0" "origin" "1056 -1144 441" "classname" "monster_knight" } { "sounds" "1" "targetname" "t61" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*9" } { "sounds" "3" "lip" "64" "spawnflags" "1" "targetname" "t58" "angle" "270" "wait" "-1" "classname" "func_door" "model" "*10" } { "sounds" "1" "wait" "-1" "angle" "270" "target" "t58" "classname" "func_button" "model" "*11" } { "target" "t61" "classname" "trigger_once" "model" "*12" } { "light" "225" "origin" "984 -480 480" "classname" "light" } { "light" "175" "origin" "880 -368 176" "classname" "light" } { "classname" "light" "origin" "880 -592 240" "light" "175" } { "light" "200" "origin" "880 -488 184" "classname" "light" } { "light" "150" "origin" "880 -304 472" "classname" "light" } { "classname" "light" "origin" "-96 308 864" "light" "850" } { "origin" "-32 -440 624" "classname" "light" } { "sounds" "1" "targetname" "t73" "wait" "-1" "lip" "196" "angle" "-1" "classname" "func_door" "model" "*13" } { "light" "300" "origin" "104 144 688" "classname" "light" } { "classname" "light" "origin" "-264 144 688" "light" "300" } { "sounds" "1" "targetname" "t73" "wait" "-1" "classname" "func_door" "angle" "-1" "lip" "196" "model" "*14" } { "classname" "light_flame_small_yellow" "origin" "-24 -232 414" "light" "250" } { "lip" "-2" "sounds" "3" "speed" "350" "targetname" "t73" "angle" "180" "wait" "-1" "classname" "func_door" "model" "*15" } { "target" "t63" "targetname" "t62" "origin" "-12 312 264" "classname" "path_corner" } { "target" "t64" "targetname" "t63" "origin" "-12 312 356" "classname" "path_corner" } { "wait" "-1" "target" "t66" "targetname" "t64" "classname" "path_corner" "origin" "-13 440 355" } { "sounds" "1" "targetname" "t71" "wait" "-1" "target" "t65" "angle" "-2" "classname" "func_button" "model" "*16" } { "target" "t64" "targetname" "t66" "origin" "-13 440 355" "classname" "path_corner" } { "light" "200" "origin" "-96 440 376" "classname" "light" } { "light" "150" "origin" "8 456 376" "classname" "light" } { "targetname" "t70" "target" "t67" "classname" "path_corner" "origin" "-220 312 264" } { "target" "t68" "targetname" "t67" "classname" "path_corner" "origin" "-220 312 356" } { "wait" "-1" "target" "t69" "targetname" "t68" "origin" "-221 440 355" "classname" "path_corner" } { "target" "t68" "targetname" "t69" "classname" "path_corner" "origin" "-221 440 355" } { "classname" "light" "origin" "-200 456 376" "light" "150" } { "targetname" "t65" "target" "t62" "classname" "func_train" "speed" "50" "sounds" "1" "model" "*17" } { "light" "250" "origin" "-96 632 406" "classname" "light_flame_small_yellow" } { "targetname" "t72" "origin" "-96 288 304" "classname" "info_null" } { "light" "450" "target" "t72" "origin" "-96 288 368" "classname" "light" } { "target" "t70" "targetname" "t65" "speed" "50" "classname" "func_train" "sounds" "1" "model" "*18" } { "lip" "-2" "sounds" "0" "speed" "350" "classname" "func_door" "wait" "-1" "angle" "0" "model" "*19" } { "targetname" "t65" "delay" "4.7" "target" "t73" "classname" "trigger_once" "model" "*20" } { "targetname" "t73" "angle" "270" "origin" "-96 552 320" "classname" "monster_demon1" "spawnflags" "1024" } { "targetname" "t74" "angle" "90" "origin" "132 -192 476" "classname" "info_teleport_destination" } { "targetname" "t75" "classname" "info_teleport_destination" "origin" "-328 -196 476" "angle" "90" } { "target" "t75" "classname" "trigger_teleport" "spawnflags" "1" "model" "*21" } { "target" "t74" "classname" "trigger_teleport" "spawnflags" "1" "model" "*22" } { "light" "200" "origin" "-418 306 356" "classname" "light" } { "classname" "light" "origin" "260 308 356" "light" "200" } { "classname" "light" "origin" "-96 24 360" "light" "100" } { "light" "100" "origin" "-96 -40 360" "classname" "light" } { "classname" "light" "origin" "-160 -568 624" } { "origin" "-160 -440 624" "classname" "light" } { "classname" "light" "origin" "-32 -568 624" } { "classname" "light" "origin" "-96 -88 484" "light" "150" } { "classname" "light" "origin" "-440 -408 804" "light" "450" } { "classname" "light" "origin" "600 -128 352" "light" "200" } { "classname" "light" "origin" "576 -608 504" "light" "250" } { "classname" "light" "origin" "384 -504 392" "light" "250" } { "classname" "light" "origin" "1264 240 295" "light" "250" } { "light" "250" "origin" "944 240 295" "classname" "light" } { "classname" "path_corner" "origin" "1480 704 264" "targetname" "t77" "target" "t78" } { "classname" "path_corner" "origin" "1448 656 264" "targetname" "t78" "target" "t30" } { "classname" "path_corner" "origin" "1264 640 304" "targetname" "t80" "target" "t5" } { "classname" "path_corner" "origin" "1328 640 304" "targetname" "t79" "target" "t80" } { "light" "200" "origin" "1488 -392 216" "classname" "light" } { "classname" "path_corner" "origin" "816 80 304" "targetname" "t83" "target" "t82" "spawnflags" "256" } { "origin" "816 312 304" "classname" "path_corner" "targetname" "t82" "target" "t83" "spawnflags" "256" } { "classname" "monster_army" "origin" "806 206 320" "angle" "90" "target" "t82" "spawnflags" "256" } { "classname" "trigger_once" "target" "t84" "model" "*28" } { "classname" "monster_ogre" "origin" "1790 -146 312" "angle" "90" "targetname" "t84" } { "classname" "path_corner" "origin" "1088 -672 296" "target" "t85" "targetname" "t88" } { "origin" "1088 -376 296" "classname" "path_corner" "targetname" "t85" "target" "t86" } { "classname" "path_corner" "origin" "1088 -376 296" "targetname" "t87" "target" "t88" } { "origin" "1448 -376 296" "classname" "path_corner" "targetname" "t86" "target" "t87" } { "spawnflags" "1" "classname" "monster_ogre" "origin" "1086 -498 312" "angle" "270" "target" "t88" } { "spawnflags" "256" "classname" "trigger_once" "target" "t89" "model" "*29" } { "classname" "item_health" "origin" "352 -752 408" "spawnflags" "1025" } { "spawnflags" "1025" "origin" "352 -792 408" "classname" "item_health" } { "classname" "item_health" "origin" "352 -832 408" "spawnflags" "1" } { "classname" "path_corner" "origin" "408 -776 416" "targetname" "t94" "target" "t95" } { "origin" "400 -1088 416" "classname" "path_corner" "targetname" "t95" "target" "t94" } { "classname" "path_corner" "origin" "584 -1096 416" "targetname" "t92" "target" "t93" } { "origin" "584 -792 416" "classname" "path_corner" "targetname" "t93" "target" "t92" } { "classname" "monster_army" "origin" "390 -970 432" "angle" "0" "target" "t94" } { "classname" "monster_army" "origin" "566 -970 432" "angle" "270" "target" "t92" } { "classname" "path_corner" "origin" "208 -304 304" "targetname" "t97" "target" "t96" } { "classname" "path_corner" "origin" "208 -464 304" "targetname" "t96" "target" "t97" } { "spawnflags" "1280" "classname" "path_corner" "origin" "-344 160 304" "targetname" "t100" "target" "t99" } { "spawnflags" "1280" "origin" "168 152 304" "classname" "path_corner" "targetname" "t99" "target" "t100" } { "spawnflags" "1280" "classname" "monster_ogre" "origin" "240 152 320" "angle" "180" "target" "t99" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "-392 80 320" "angle" "0" "targetname" "t101" } { "spawnflags" "768" "classname" "trigger_once" "target" "t101" "model" "*30" } { "classname" "item_health" "origin" "40 -16 464" } { "origin" "80 -48 464" "classname" "item_health" } { "origin" "520 -72 296" "classname" "item_shells" } { "spawnflags" "1" "origin" "-424 -216 296" "classname" "item_shells" } { "spawnflags" "769" "angle" "270" "origin" "880 -400 568" "classname" "monster_wizard" } { "light" "200" "origin" "432 176 152" "classname" "light" } { "light" "150" "origin" "432 -56 256" "classname" "light" } { "origin" "264 -96 300" "classname" "item_health" } { "classname" "item_health" "origin" "264 -140 300" } { "spawnflags" "1" "origin" "1184 1568 240" "classname" "item_health" } { "classname" "item_health" "origin" "1184 1616 240" "spawnflags" "1" } { "light" "150" "origin" "1496 1112 108" "classname" "light" } { "light" "200" "origin" "1120 1152 96" "classname" "light" } { "light" "200" "origin" "1080 692 184" "classname" "light" } { "light" "300" "classname" "light_flame_small_yellow" "origin" "832 1184 294" } { "origin" "464 536 358" "classname" "light_flame_small_yellow" "light" "300" } { "light" "300" "classname" "light_flame_small_yellow" "origin" "600 704 334" } { "light" "150" "origin" "1736 1096 110" "classname" "light" } { "light" "100" "origin" "832 1056 134" "classname" "light" } { "light" "150" "origin" "784 704 294" "classname" "light" } { "origin" "856 592 182" "classname" "item_health" } { "classname" "item_health" "origin" "824 552 182" } { "classname" "info_player_deathmatch" "origin" "-416 -144 320" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "168 -480 320" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1496 1328 200" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "1936 -136 312" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "936 -1216 432" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "792 -992 440" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1080 -720 312" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "408 -752 432" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "792 -208 320" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "784 808 206" "angle" "225" } { "sounds" "3" "wait" "3" "angle" "90" "classname" "func_door" "model" "*31" } { "sounds" "0" "wait" "3" "angle" "270" "classname" "func_door" "model" "*32" } { "spawnflags" "1" "origin" "680 832 182" "classname" "item_shells" } { "origin" "1392 240 300" "classname" "weapon_supershotgun" } { "spawnflags" "769" "angle" "270" "origin" "954 -754 444" "classname" "monster_ogre" } { "spawnflags" "1" "origin" "520 -1280 408" "classname" "item_shells" } { "light" "200" "origin" "-612 -500 548" "classname" "light" } { "classname" "func_door" "angle" "90" "targetname" "t110" "wait" "-1" "model" "*33" } { "sounds" "3" "classname" "func_door" "angle" "270" "wait" "-1" "model" "*34" } { "classname" "trigger_once" "target" "t110" "model" "*35" } { "classname" "trigger_changelevel" "map" "e1m3" "model" "*36" } { "spawnflags" "1792" "origin" "680 728 184" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "1496 1256 176" "classname" "weapon_nailgun" } { "angle" "180" "spawnflags" "1792" "origin" "-96 -496 360" "classname" "weapon_supernailgun" } { "spawnflags" "1794" "origin" "-112 -8 464" "classname" "item_health" } { "spawnflags" "1793" "origin" "-112 -568 360" "classname" "item_spikes" } { "spawnflags" "1792" "origin" "1616 1424 176" "classname" "item_spikes" } { "spawnflags" "1792" "classname" "item_spikes" "origin" "1656 1424 176" } { "spawnflags" "1792" "origin" "1696 1424 176" "classname" "item_spikes" } { "spawnflags" "768" "target" "t34" "angle" "315" "origin" "1070 646 312" "classname" "monster_ogre" } { "spawnflags" "768" "targetname" "t84" "angle" "90" "origin" "1624 88 376" "classname" "monster_wizard" } { "spawnflags" "768" "angle" "90" "targetname" "t84" "origin" "1866 -378 312" "classname" "monster_ogre" } { "angle" "45" "origin" "1088 -1096 440" "classname" "monster_knight" "targetname" "t50" } { "spawnflags" "768" "classname" "monster_knight" "origin" "1400 -1144 440" "angle" "90" "targetname" "t50" } { "spawnflags" "256" "target" "t111" "targetname" "t112" "origin" "896 -1216 416" "classname" "path_corner" } { "spawnflags" "256" "target" "t112" "targetname" "t111" "classname" "path_corner" "origin" "704 -1216 416" } { "spawnflags" "257" "target" "t111" "angle" "180" "origin" "758 -1218 432" "classname" "monster_army" } { "spawnflags" "768" "target" "t114" "targetname" "t113" "origin" "-96 -520 368" "classname" "path_corner" } { "spawnflags" "768" "target" "t113" "targetname" "t114" "origin" "-96 -152 304" "classname" "path_corner" } { "targetname" "t116" "spawnflags" "769" "target" "t113" "angle" "270" "origin" "-98 -194 320" "classname" "monster_ogre" } { "spawnflags" "1536" "origin" "1936 -96 289" "classname" "item_health" } { "spawnflags" "1025" "origin" "1040 -1200 417" "classname" "item_health" } { "spawnflags" "769" "target" "t117" "angle" "315" "origin" "-560 -312 592" "classname" "monster_wizard" } { "spawnflags" "768" "target" "t118" "targetname" "t117" "origin" "-528 -344 576" "classname" "path_corner" } { "spawnflags" "768" "target" "t117" "targetname" "t118" "origin" "-352 -656 576" "classname" "path_corner" } { "classname" "light" "origin" "1360 976 224" "light" "150" } { "light" "150" "origin" "1616 976 224" "classname" "light" } { "classname" "light" "origin" "1208 1296 368" "light" "250" } { "origin" "1784 1288 368" "classname" "light" "light" "250" } { "classname" "light" "origin" "1496 1664 336" "light" "250" } { "classname" "light" "origin" "1752 1176 112" "light" "150" } { "light" "200" "origin" "1776 976 112" "classname" "light" } { "classname" "light" "origin" "1216 976 112" "light" "200" } { "light" "150" "origin" "1224 1176 112" "classname" "light" } { "classname" "light" "origin" "1496 1432 520" "light" "250" } { "classname" "light" "origin" "1496 1304 264" "light" "200" } { "classname" "light" "origin" "1496 1432 288" "light" "200" } { "classname" "light" "origin" "1608 1120 88" "light" "150" } { "light" "150" "origin" "1384 1120 88" "classname" "light" } { "classname" "light" "origin" "1496 864 368" "light" "150" } { "light" "175" "origin" "980 764 353" "classname" "light" } { "classname" "light" "origin" "1228 764 353" "light" "175" } { "classname" "light" "origin" "1104 464 353" "light" "200" } { "classname" "light" "origin" "1104 -40 423" "light" "200" } { "light" "150" "origin" "1416 -128 367" "classname" "light" } { "classname" "light" "origin" "1104 -184 367" "light" "200" } { "classname" "light" "origin" "1184 56 423" "light" "150" } { "light" "150" "origin" "1024 56 423" "classname" "light" } { "classname" "light" "origin" "1272 -64 399" "light" "150" } { "light" "150" "origin" "888 -64 399" "classname" "light" } { "classname" "light" "origin" "1104 152 129" "light" "300" } { "classname" "light" "origin" "976 392 129" "light" "200" } { "classname" "light" "origin" "1104 656 120" } { "classname" "light" "origin" "896 712 144" "light" "200" } { "classname" "light" "origin" "640 704 280" "light" "200" } { "classname" "light" "origin" "464 496 296" "light" "150" } { "classname" "light" "origin" "888 1152 96" "light" "200" } { "classname" "light" "origin" "840 880 240" "light" "200" } { "classname" "light" "origin" "848 584 240" "light" "150" } { "classname" "light" "origin" "784 160 144" "light" "200" } { "classname" "light" "origin" "440 336 144" "light" "150" } { "light" "150" "origin" "584 336 144" "classname" "light" } { "classname" "light" "origin" "432 24 136" "light" "150" } { "classname" "light" "origin" "656 328 224" "light" "200" } { "classname" "light" "origin" "432 -128 312" "light" "200" } { "classname" "light" "origin" "600 -384 360" "light" "200" } { "origin" "520 -128 406" "classname" "light_flame_small_yellow" "light" "250" } { "classname" "light" "origin" "424 -320 352" "light" "200" } { "classname" "light" "origin" "664 -1216 472" "light" "150" } { "classname" "light" "origin" "336 -1208 504" "light" "150" } { "light" "150" "origin" "336 -1008 504" "classname" "light" } { "classname" "light" "origin" "336 -816 504" "light" "150" } { "classname" "light" "origin" "880 -1000 496" "light" "200" } { "classname" "light" "origin" "880 -792 496" "light" "200" } { "classname" "light" "origin" "880 -376 304" "light" "200" } { "classname" "light" "origin" "1048 -912 480" "light" "225" } { "classname" "light" "origin" "1120 -1192 468" "light" "150" } { "light" "150" "origin" "1376 -1192 468" "classname" "light" } { "classname" "light" "origin" "1472 -912 464" "light" "175" } { "classname" "light" "origin" "880 -304 480" "light" "100" } { "classname" "light" "origin" "880 -680 480" "light" "175" } { "classname" "light" "origin" "1600 -704 484" "light" "150" } { "classname" "light" "origin" "1504 -704 348" "light" "175" } { "light" "175" "origin" "1336 -704 348" "classname" "light" } { "classname" "light" "origin" "1152 -640 332" "light" "200" } { "classname" "light" "origin" "1096 -552 348" "light" "150" } { "light" "200" "origin" "1160 -456 332" "classname" "light" } { "light" "150" "origin" "1216 -384 348" "classname" "light" } { "classname" "light" "origin" "1344 -384 348" "light" "150" } { "classname" "light" "origin" "1544 392 156" "light" "225" } { "light" "225" "origin" "1848 248 156" "classname" "light" } { "classname" "light" "origin" "1936 136 156" "light" "225" } { "light" "200" "origin" "2096 -80 156" "classname" "light" } { "light" "200" "origin" "2048 -408 156" "classname" "light" } { "classname" "light" "origin" "1456 -392 444" "light" "225" } { "classname" "light" "origin" "1640 -384 352" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "2134 -474 316" "light" "250" } { "light" "200" "origin" "168 216 496" "classname" "light" } { "classname" "light" "origin" "-328 208 496" "light" "200" } { "light" "200" "origin" "-96 360 432" "classname" "light" } { "classname" "light" "origin" "-96 144 432" "light" "200" } { "light" "200" "origin" "-376 32 432" "classname" "light" } { "light" "200" "origin" "208 -72 432" "classname" "light" } { "light" "150" "origin" "-96 72 360" "classname" "light" } { "light" "150" "origin" "-64 -232 368" "classname" "light" } { "light" "150" "origin" "-96 -320 560" "classname" "light" } { "light" "250" "origin" "-96 -496 448" "classname" "light" } { "light" "150" "origin" "-416 -104 392" "classname" "light" } { "light" "150" "origin" "-344 -152 528" "classname" "light" } { "classname" "light" "origin" "160 -152 528" "light" "150" } { "light" "150" "origin" "-96 8 528" "classname" "light" } { "light" "200" "origin" "-560 -504 688" "classname" "light" } { "classname" "light" "origin" "-440 -368 688" "light" "200" } { "light" "200" "origin" "-440 -656 688" "classname" "light" } { "classname" "light" "origin" "-336 -504 688" "light" "200" } { "classname" "light" "origin" "2084 -208 336" "light" "100" } { "light" "100" "origin" "2012 -252 332" "classname" "light" } { "classname" "light" "origin" "1948 -328 332" "light" "100" } { "light" "150" "origin" "1892 -452 332" "classname" "light" } { "sounds" "1" "targetname" "t120" "wait" "-1" "angle" "-2" "classname" "func_door" "lip" "4" "model" "*37" } { "target" "t120" "classname" "trigger_once" "model" "*38" } { "light" "100" "origin" "2076 -312 336" "classname" "light" } { "sounds" "3" "spawnflags" "2064" "angle" "0" "wait" "-1" "classname" "func_door" "model" "*39" } { "spawnflags" "2064" "wait" "-1" "angle" "180" "classname" "func_door" "model" "*40" } { "light" "100" "origin" "332 -264 356" "classname" "light" } { "classname" "light" "origin" "144 -264 356" "light" "100" } { "light" "100" "origin" "1104 572 316" "classname" "light" } { "target" "t121" "wait" ".8" "classname" "trigger_multiple" "model" "*41" } { "targetname" "t121" "angle" "180" "origin" "2120 -256 332" "classname" "trap_spikeshooter" "spawnflags" "1024" } { "targetname" "t121" "angle" "90" "origin" "1944 -456 332" "classname" "trap_spikeshooter" "spawnflags" "1024" } { "light" "150" "origin" "1312 -856 472" "classname" "light" } { "classname" "light" "origin" "1184 -856 472" "light" "175" } { "classname" "light" "origin" "1560 -568 224" "light" "200" } { "classname" "func_door" "angle" "-2" "wait" "-1" "speed" "50" "sounds" "1" "targetname" "t123" "lip" "6" "model" "*42" } { "classname" "trigger_once" "target" "t123" "model" "*43" } { "classname" "light" "origin" "1496 -552 330" "light" "700" "target" "t52" } { "classname" "light" "origin" "1288 80 140" "light" "250" } { "classname" "light" "origin" "1288 400 80" "light" "200" } { "classname" "light" "origin" "1328 -664 160" "light" "200" } { "classname" "item_armor1" "origin" "784 56 304" } { "classname" "light" "origin" "1544 464 352" "light" "75" } { "classname" "func_plat" "model" "*44" } { "classname" "light" "origin" "1496 1192 280" "light" "200" } { "classname" "light" "origin" "1608 1192 136" "light" "100" } { "light" "100" "origin" "1384 1184 136" "classname" "light" } { "light" "100" "origin" "1608 1048 136" "classname" "light" } { "classname" "light" "origin" "1384 1048 136" "light" "100" } { "classname" "light" "origin" "1200 1148 92" "light" "150" } { "light" "150" "origin" "876 -184 367" "classname" "light" } { "classname" "light" "origin" "768 -128 384" "light" "200" } { "classname" "light" "origin" "1104 388 552" "light" "250" } { "light" "200" "origin" "1392 240 384" "classname" "light" } { "classname" "light" "origin" "1392 80 368" "light" "200" } { "classname" "light" "origin" "1272 400 367" "light" "150" } { "light" "150" "origin" "920 400 367" "classname" "light" } { "classname" "light" "origin" "816 208 368" "light" "200" } { "classname" "light" "origin" "800 24 368" "light" "200" } { "classname" "light" "origin" "800 376 385" "light" "150" } { "light" "150" "origin" "1400 400 385" "classname" "light" } { "classname" "path_corner" "origin" "1104 336 300" "target" "t126" "targetname" "t127" } { "origin" "1104 24 300" "classname" "path_corner" "targetname" "t126" "target" "t127" } { "classname" "monster_army" "origin" "1104 424 316" "angle" "270" "target" "t127" } { "targetname" "t128" "origin" "1392 240 308" "classname" "info_null" } { "light" "300" "target" "t128" "origin" "1392 240 376" "classname" "light" } { "targetname" "t129" "angle" "0" "origin" "552 -128 320" "classname" "monster_army" } { "target" "t129" "classname" "trigger_once" "model" "*45" } { "sounds" "1" "classname" "trigger_secret" "model" "*46" } { "sounds" "1" "classname" "trigger_secret" "model" "*47" } { "classname" "light" "origin" "1104 24 536" "light" "350" } { "spawnflags" "33" // +32 for disable in capture mode "classname" "func_door_secret" "angle" "270" "model" "*48" } { "light" "200" "origin" "1680 1552 320" "classname" "light" } { "classname" "light" "origin" "1312 1552 320" "light" "200" } { "classname" "item_spikes" "origin" "1480 1104 68" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1760 -568 256" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1232 -1200 416" } { "message" "This door is opened elsewhere..." "classname" "func_door" "sounds" "3" "angle" "180" "wait" "-1" "targetname" "t122" "speed" "35" "spawnflags" "2048" "model" "*49" } { "classname" "func_door" "angle" "0" "wait" "-1" "speed" "30" "spawnflags" "2048" "model" "*50" } { "classname" "light" "origin" "1496 1600 296" "light" "150 " } { "light" "150" "origin" "1568 1664 296" "classname" "light" } { "classname" "light" "origin" "1424 1664 296" "light" "150" } { "classname" "light" "origin" "1328 1424 296" "light" "200" } { "light" "250" "origin" "1696 1416 296" "classname" "light" } { "classname" "monster_army" "origin" "1592 1296 200" "angle" "270" } { "spawnflags" "768" "classname" "monster_demon1" "origin" "-96 576 320" "angle" "270" "targetname" "t73" "target" "t143" } { "classname" "path_corner" "origin" "1392 416 304" "targetname" "t131" "target" "t130" "spawnflags" "768" } { "origin" "1392 296 304" "classname" "path_corner" "targetname" "t130" "target" "t131" "spawnflags" "768" } { "classname" "monster_army" "origin" "1392 352 320" "angle" "270" "target" "t130" "spawnflags" "768" } { "target" "t132" "targetname" "t133" "origin" "296 -328 304" "classname" "path_corner" } { "target" "t133" "targetname" "t132" "classname" "path_corner" "origin" "472 -416 304" } { "spawnflags" "1" "target" "t132" "angle" "90" "origin" "472 -456 320" "classname" "monster_army" } { "spawnflags" "1" "targetname" "t89" "angle" "135" "origin" "1712 -784 376" "classname" "monster_army" } { "target" "t135" "spawnflags" "256" "targetname" "t134" "origin" "400 -1128 416" "classname" "path_corner" } { "target" "t134" "spawnflags" "256" "targetname" "t135" "classname" "path_corner" "origin" "400 -1248 416" } { "target" "t134" "spawnflags" "257" "angle" "90" "origin" "408 -1208 432" "classname" "monster_army" } { "targetname" "t101" "angle" "90" "origin" "-288 -24 488" "classname" "monster_army" "spawnflags" "768" } { "spawnflags" "768" "targetname" "t101" "classname" "monster_army" "origin" "136 -128 488" "angle" "90" } { "spawnflags" "1792" "origin" "-264 -24 464" "classname" "item_rockets" } { "spawnflags" "2048" "origin" "-240 -8 464" "classname" "item_spikes" } { "classname" "monster_ogre" "origin" "-304 -304 488" "angle" "225" "spawnflags" "769" } { "classname" "func_wall" "spawnflags" "768" "model" "*51" } { "classname" "trap_spikeshooter" "origin" "2048 -48 332" "angle" "270" "spawnflags" "769" "targetname" "t121" } { "origin" "2048 -476 332" "classname" "info_null" "targetname" "t136" } { "style" "32" "origin" "2048 -456 336" "classname" "light" "light" "800" "spawnflags" "1" "target" "t136" "targetname" "t137" } { "style" "32" "classname" "trigger_once" "spawnflags" "768" "target" "t137" "model" "*52" } { "classname" "monster_wizard" "origin" "672 328 384" "angle" "180" "spawnflags" "768" "targetname" "t138" } { "classname" "trigger_once" "target" "t138" "model" "*53" } { "style" "32" "classname" "light" "origin" "2004 -52 332" "light" "100" "spawnflags" "1" "targetname" "t137" } { "classname" "item_shells" "origin" "1416 224 300" "spawnflags" "768" } { "classname" "path_corner" "origin" "-344 136 304" "targetname" "t139" "target" "t140" "spawnflags" "768" } { "origin" "168 128 304" "classname" "path_corner" "target" "t139" "targetname" "t140" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "-400 168 320" "spawnflags" "768" "target" "t139" } { "classname" "trap_spikeshooter" "origin" "2120 -256 332" "angle" "180" "spawnflags" "769" "targetname" "t121" } { "classname" "trap_spikeshooter" "origin" "1944 -456 332" "targetname" "t121" "angle" "90" "spawnflags" "769" } { "classname" "item_spikes" "origin" "-336 -80 470" "spawnflags" "768" } { "targetname" "t143" "classname" "trigger_teleport" "target" "t142" "spawnflags" "2" "model" "*54" } { "targetname" "t143" "classname" "trigger_teleport" "target" "t141" "spawnflags" "2" "model" "*55" } { "classname" "monster_demon1" "origin" "32 840 359" "angle" "270" "targetname" "t143" "spawnflags" "768" } { "angle" "270" "origin" "-192 840 359" "classname" "monster_demon1" "targetname" "t143" "spawnflags" "768" } { "classname" "info_teleport_destination" "origin" "80 216 303" "angle" "270" "targetname" "t141" } { "angle" "270" "origin" "-264 224 303" "classname" "info_teleport_destination" "targetname" "t142" } { "wait" "-1" "target" "t53" "health" "1" "classname" "func_button" "model" "*56" } { "spawnflags" "768" "angle" "270" "origin" "1408 1296 200" "classname" "monster_army" } { "classname" "item_shells" "origin" "772 -856 420" "spawnflags" "768" } { "spawnflags" "1792" "origin" "1248 -1128 420" "classname" "weapon_grenadelauncher" } { "spawnflags" "1793" "origin" "864 -312 440" "classname" "item_rockets" } { "classname" "trigger_once" "message" "Pass through the arch to exit..." "model" "*57" } { "mangle" "20 300 0" "classname" "info_intermission" "origin" "-224 424 512" } { "mangle" "20 45 0" "origin" "1048 -744 488" "classname" "info_intermission" } { "mangle" "20 270 0" "origin" "1104 424 528" "classname" "info_intermission" } { "mangle" "20 45 0" "origin" "1240 984 416" "classname" "info_intermission" } { "sounds" "1" "speed" "20" "classname" "func_button" "angle" "0" "wait" "-1" "target" "t144" "model" "*58" } { "classname" "light" "origin" "400 -1392 480" "light" "150" } { "classname" "func_door" "angle" "-2" "wait" "-1" "speed" "20" "sounds" "1" "targetname" "t144" "model" "*59" } { "classname" "trigger_secret" "model" "*60" } { "classname" "item_artifact_super_damage" "origin" "400 -1360 432" } { "classname" "item_spikes" "origin" "808 -632 192" "spawnflags" "2049" } { "classname" "item_health" "origin" "924 -632 192" "spawnflags" "2048" } { "classname" "weapon_supernailgun" "origin" "880 -616 192" "spawnflags" "1792" } { "classname" "ambient_drip" "origin" "842 978 344" } { "classname" "ambient_drip" "origin" "546 330 400" } { "classname" "info_player_coop" "origin" "1608 1664 264" "angle" "270" } { "angle" "270" "origin" "1392 1664 264" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1496 1560 264" "angle" "270" } { "spawnflags" "256" "angle" "270" "origin" "232 -176 320" "classname" "monster_ogre" } { "spawnflags" "1280" "angle" "225" "origin" "-368 -312 480" "classname" "monster_knight" } { "spawnflags" "1792" "classname" "func_wall" "model" "*61" } { "origin" "1810 274 200" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1802 -102 200" } { "origin" "2050 -214 200" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "2002 -390 200" } { "origin" "1738 -398 200" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1346 -398 200" } { "origin" "1138 -542 200" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "882 -494 200" } { "classname" "ambient_swamp1" "origin" "1722 1090 176" } { "origin" "1242 1090 176" "classname" "ambient_swamp1" } { "classname" "ambient_swamp2" "origin" "1106 642 192" } { "origin" "1346 242 192" "classname" "ambient_swamp2" } { "classname" "ambient_swamp1" "origin" "866 210 192" } { "classname" "ambient_swamp1" "origin" "1802 90 192" } { "origin" "1546 -398 192" "classname" "ambient_swamp1" } { "classname" "ambient_swamp2" "origin" "2042 -310 192" } { "origin" "1178 -398 192" "classname" "ambient_swamp2" } { "classname" "ambient_swamp2" "origin" "1202 -678 192" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "1496 1668 308" "classname" "item_flag_team1" } { "angle" "270" "origin" "1396 1240 200" "classname" "info_player_team1" } { "angle" "270" "origin" "1496 1240 204" "classname" "info_player_team1" } { "angle" "270" "origin" "1596 1240 200" "classname" "info_player_team1" } { "angle" "270" "origin" "1396 1340 200" "classname" "info_player_team1" } { "angle" "270" "origin" "1496 1340 200" "classname" "info_player_team1" } { "angle" "270" "origin" "1596 1340 200" "classname" "info_player_team1" } // team2 { "origin" "-600 -500 500" "classname" "item_flag_team2" } { "angle" "0" "origin" "-425 -400 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-425 -500 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-425 -600 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-525 -400 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-525 -500 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-525 -600 480" "classname" "info_player_team2" } { "angle" "0" "origin" "-525 -400 480" "classname" "info_player_team2" } // base one weapons upgrade //{ //"classname" "item_health" //"origin" "-488 2064 1220" //} //{ //"origin" "-488 2112 1220" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "-488 2160 1220" //} //{ //"origin" "-72 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-120 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-168 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-72 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-120 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-168 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-72 2160 1220" //"classname" "weapon_supershotgun" //} //{ //"origin" "-120 2160 1220" //"classname" "item_armor2" //} //{ //"origin" "-168 2160 1220" //"classname" "weapon_supernailgun" //} // //// base two weapons upgrade //{ //"classname" "item_shells" //"origin" "1240 768 1384" //} //{ //"classname" "item_shells" //"origin" "1192 768 1384" //} //{ //"classname" "item_shells" //"origin" "1144 768 1384" //} //{ //"classname" "item_spikes" //"origin" "1240 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1192 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1144 816 1384" //} //{ //"origin" "1240 864 1384" //"classname" "weapon_supershotgun" //} //{ //"classname" "item_armor2" //"origin" "1192 864 1384" //} //{ //"classname" "weapon_supernailgun" //"origin" "1144 864 1384" //} //{ //"origin" "1240 912 1384" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "1192 912 1384" //} //{ //"classname" "item_health" //"origin" "1144 912 1384" //} // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m3.ent000066400000000000000000001367071475442401000252070ustar00rootroot00000000000000{ "sounds" "9" "message" "the Necropolis" "worldtype" "0" "wad" "gfx/wizard.wad" "classname" "worldspawn" } { "wait" "-1" "sounds" "3" "classname" "func_door" "angle" "180" "model" "*1" } { "wait" "-1" "sounds" "0" "classname" "func_door" "angle" "0" "model" "*2" } { "classname" "light" "origin" "1360 336 48" } { "origin" "1360 440 476" "classname" "light" } { "speed" "35" "targetname" "t5" "target" "t1" "classname" "func_train" "dmg" "100" "sounds" "1" "model" "*3" } { "speed" "35" "targetname" "t5" "target" "t6" "classname" "func_train" "dmg" "100" "sounds" "1" "model" "*4" } { "target" "t2" "targetname" "t1" "origin" "1360 296 136" "classname" "path_corner" } { "target" "t3" "targetname" "t2" "origin" "1360 296 -88" "classname" "path_corner" } { "target" "t4" "targetname" "t3" "wait" "-1" "origin" "1496 296 -88" "classname" "path_corner" } { "target" "t3" "targetname" "t4" "classname" "path_corner" "origin" "1496 292 -80" } { "target" "t8" "targetname" "t6" "classname" "path_corner" "origin" "1224 296 136" } { "target" "t7" "targetname" "t8" "classname" "path_corner" "origin" "1224 296 -88" } { "target" "t9" "targetname" "t7" "classname" "path_corner" "origin" "1084 296 -88" "wait" "-1" } { "targetname" "t9" "origin" "1084 276 -80" "classname" "path_corner" } { "sounds" "2" "target" "t5" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*5" } { "light" "225" "origin" "1360 552 -112" "classname" "light" } { "sounds" "0" "targetname" "t5" "speed" "400" "dmg" "1000" "wait" "20" "angle" "0" "spawnflags" "1" "classname" "func_door" "model" "*6" } { "sounds" "1" "targetname" "t5" "speed" "400" "wait" "20" "spawnflags" "5" "angle" "-2" "dmg" "1000" "classname" "func_door" "lip" "3" "model" "*7" } { "delay" "10.5" "target" "t10" "targetname" "t5" "classname" "trigger_once" "model" "*8" } { "sounds" "1" "targetname" "t10" "wait" "12" "spawnflags" "5" "angle" "-2" "classname" "func_door" "dmg" "75" "model" "*9" } { "targetname" "t5" "dmg" "1000" "speed" "400" "wait" "20" "spawnflags" "1" "angle" "180" "classname" "func_door" "model" "*10" } { "light" "225" "origin" "-752 -1576 176" "classname" "light" } { "angle" "270" "origin" "-736 -1592 88" "classname" "info_player_start" } { "light" "225" "origin" "-584 -1800 312" "classname" "light" } { "light" "175" "origin" "-488 -1800 320" "classname" "light" } { "origin" "-288 -1800 308" "classname" "light" } { "light" "225" "origin" "-176 -1616 320" "classname" "light" } { "light" "225" "classname" "light" "origin" "-184 -1248 280" } { "classname" "light" "origin" "-184 -1416 280" "light" "225" } { "sounds" "0" "angle" "90" "classname" "func_door" "model" "*11" } { "sounds" "3" "angle" "270" "classname" "func_door" "model" "*12" } { "classname" "light" "origin" "-424 -1256 160" "light" "250" } { "classname" "light_flame_small_yellow" "origin" "-312 -1000 158" } { "origin" "-400 -1096 158" "classname" "light_flame_small_yellow" } { "classname" "info_null" "origin" "-720 -1244 52" "targetname" "t11" } { "light" "400" "classname" "light" "origin" "-712 -1240 164" "target" "t11" } { "sounds" "0" "classname" "func_door" "lip" "2" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t12" "model" "*13" } { "sounds" "1" "classname" "func_door" "wait" "-1" "angle" "-2" "lip" "16" "spawnflags" "4" "targetname" "t12" "model" "*14" } { "sounds" "0" "classname" "func_door" "angle" "-2" "wait" "-1" "lip" "32" "spawnflags" "4" "targetname" "t12" "model" "*15" } { "sounds" "0" "classname" "func_door" "lip" "48" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t12" "model" "*16" } { "sounds" "1" "targetname" "t12" "lip" "64" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*17" } { "style" "32" "target" "t13" "classname" "trigger_once" "model" "*18" } { "style" "32" "spawnflags" "1" "targetname" "t13" "origin" "-628 -1252 380" "classname" "light" } { "target" "t15" "targetname" "t14" "origin" "-816 -1384 504" "classname" "path_corner" } { "target" "t16" "targetname" "t15" "origin" "-816 -1384 60" "classname" "path_corner" } { "target" "t14" "targetname" "t16" "wait" "-1" "origin" "-816 -1384 232" "classname" "path_corner" } { "light" "225" "origin" "-908 -1248 12" "classname" "light" } { "light" "225" "origin" "-568 -1176 240" "classname" "light" } { "classname" "light" "origin" "-760 -1172 240" "light" "225" } { "light" "225" "origin" "-756 -1332 240" "classname" "light" } { "classname" "light" "origin" "-564 -1336 240" "light" "225" } { "style" "33" "targetname" "t12" "target" "t18" "light" "500" "origin" "-776 -1240 104" "classname" "light" } { "targetname" "t18" "origin" "-818 -1240 104" "classname" "info_null" } { "sounds" "3" "wait" "20" "targetname" "t13" "speed" "300" "dmg" "200" "spawnflags" "1" "angle" "270" "classname" "func_door" "model" "*19" } { "wait" "20" "targetname" "t13" "dmg" "200" "spawnflags" "1" "angle" "90" "speed" "300" "classname" "func_door" "model" "*20" } { "classname" "light" "origin" "-1224 -800 0" "light" "225" } { "light" "175" "origin" "-952 -936 8" "classname" "light" } { "classname" "light" "origin" "-1216 -960 8" "light" "175" } { "classname" "light" "origin" "-776 -160 128" } { "sounds" "0" "classname" "func_door" "angle" "90" "spawnflags" "2056" "wait" "-1" "model" "*21" } { "sounds" "3" "classname" "func_door" "angle" "270" "spawnflags" "2056" "wait" "-1" "model" "*22" } { "classname" "light" "origin" "-264 -160 124" } { "classname" "light_torch_small_walltorch" "origin" "-544 -82 -4" "light" "225" } { "origin" "-544 -238 -4" "classname" "light_torch_small_walltorch" "light" "225" } { "classname" "light_flame_small_yellow" "origin" "-1144 48 38" } { "origin" "-1432 -256 38" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "1352 440 600" "light" "225" } { "origin" "-1040 -272 38" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "-1352 -432 14" } { "origin" "-960 -48 14" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "-1408 -624 20" "light" "225" } { "light" "225" "origin" "-1072 -512 20" "classname" "light" } { "classname" "light" "origin" "-1016 64 20" "light" "225" } { "classname" "light" "origin" "-1048 -712 20" "light" "225" } { "classname" "light" "origin" "-632 32 64" "light" "175" } { "light" "175" "origin" "-632 -168 -32" "classname" "light" } { "classname" "light" "origin" "-952 -432 16" "light" "225" } { "classname" "light" "origin" "-952 0 -312" "light" "225" } { "light" "225" "origin" "-944 -248 -312" "classname" "light" } { "classname" "light" "origin" "-824 -72 -312" "light" "225" } { "classname" "light" "origin" "-800 -344 -312" "light" "225" } { "classname" "light" "origin" "-648 -176 -312" "light" "175" } { "light" "175" "origin" "-528 -320 -360" "classname" "light" } { "classname" "light" "origin" "-960 -448 -312" "light" "175" } { "light" "225" "origin" "-1232 -448 -312" "classname" "light" } { "classname" "light" "origin" "-1232 -608 -312" "light" "225" } { "light" "225" "origin" "-1432 -696 -312" "classname" "light" } { "classname" "light" "origin" "-1464 -376 -312" "light" "225" } { "light" "225" "origin" "-1056 -736 -312" "classname" "light" } { "classname" "light" "origin" "-992 -560 -312" "light" "175" } { "origin" "-620 -1958 256" "classname" "light_flame_large_yellow" } { "light" "175" "origin" "-624 -1912 176" "classname" "light" } { "classname" "light_flame_large_yellow" "origin" "-966 -1750 256" } { "classname" "light" "origin" "-920 -1744 176" "light" "175" } { "light" "250" "origin" "-768 -1760 200" "classname" "light" } { "light" "175" "origin" "-616 -1600 248" "classname" "light" } { "light" "225" "origin" "-288 -1632 144" "classname" "light" } { "classname" "light" "origin" "-352 -1696 144" "light" "225" } { "light" "175" "origin" "-584 -1640 136" "classname" "light" } { "light" "175" "origin" "-184 -1488 144" "classname" "light" } { "light" "125" "origin" "-152 -1832 144" "classname" "light" } { "classname" "light_flame_small_yellow" "origin" "72 -1312 158" } { "light" "300" "classname" "light_flame_small_yellow" "origin" "120 -464 -98" } { "origin" "-264 -520 30" "classname" "light_flame_small_yellow" } { "origin" "64 -480 -256" "classname" "light" "light" "225" } { "classname" "light" "origin" "68 -548 -156" "light" "100" } { "classname" "path_corner" "origin" "48 -128 -172" "targetname" "t72" "target" "t73" } { "origin" "48 -672 -172" "classname" "path_corner" "targetname" "t73" "target" "t77" "wait" "-1" } { "sounds" "1" "classname" "func_train" "target" "t72" "targetname" "t75" "speed" "800" "dmg" "49" "model" "*23" } { "classname" "func_door_secret" "angle" "0" "spawnflags" "1" "targetname" "t76" "model" "*24" } { "sounds" "1" "spawnflags" "3" "angle" "180" "classname" "func_door_secret" "targetname" "t76" "model" "*25" } { "classname" "trigger_once" "target" "t76" "model" "*26" } { "classname" "trigger_once" "delay" "2.4" "targetname" "t76" "target" "t75" "model" "*27" } { "wait" "-1" "classname" "path_corner" "origin" "48 -144 -172" "targetname" "t77" "target" "t73" } { "style" "34" "classname" "light" "origin" "64 -160 -152" "spawnflags" "1" "light" "250" "targetname" "t76" } { "sounds" "3" "classname" "func_door" "angle" "0" "wait" "-1" "targetname" "t78" "speed" "50" "lip" "-4" "model" "*28" } { "sounds" "0" "classname" "func_door" "angle" "180" "wait" "-1" "speed" "50" "lip" "-4" "model" "*29" } { "classname" "trigger_once" "delay" "3" "target" "t78" "targetname" "t76" "model" "*30" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "40 -468 -280" "angle" "90" "targetname" "t79" } { "classname" "trigger_once" "target" "t79" "model" "*31" } { "spawnflags" "256" "angle" "90" "origin" "88 -468 -280" "classname" "monster_zombie" "targetname" "t79" } { "sounds" "0" "classname" "func_door" "angle" "-2" "spawnflags" "1" "targetname" "t79" "speed" "50" "wait" "-1" "model" "*32" } { "classname" "light" "origin" "136 -604 -260" "light" "175" } { "light" "225" "origin" "384 -48 -168" "classname" "light" } { "light" "175" "origin" "776 -248 -256" "classname" "light" } { "classname" "light" "origin" "768 -464 -256" "light" "175" } { "light" "225" "origin" "216 136 -104" "classname" "light" } { "origin" "228 -168 -98" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "8 148 -98" } { "classname" "light" "origin" "976 -352 -168" "light" "225" } { "classname" "light" "origin" "1368 -336 -112" "light" "225" } { "sounds" "0" "angle" "90" "classname" "func_door" "model" "*33" } { "sounds" "3" "angle" "270" "classname" "func_door" "model" "*34" } { "light" "175" "origin" "1488 -360 72" "classname" "light" } { "light" "225" "origin" "1426 -274 -68" "classname" "light_torch_small_walltorch" } { "light" "225" "classname" "light_torch_small_walltorch" "origin" "1426 -430 -68" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "1120 -136 -18" } { "classname" "light" "origin" "1608 -344 -8" "light" "225" } { "light" "225" "origin" "1608 -96 -8" "classname" "light" } { "classname" "light" "origin" "1168 -352 120" } { "classname" "light" "origin" "896 -216 -16" "light" "225" } { "light" "225" "origin" "896 -488 -16" "classname" "light" } { "classname" "light" "origin" "1336 -224 88" "light" "225" } { "light" "225" "origin" "1336 -488 88" "classname" "light" } { "light" "250" "origin" "1728 -360 -80" "classname" "light" } { "classname" "light" "origin" "1500 -96 -80" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "1608 10 116" "light" "225" } { "light" "225" "origin" "1608 -458 116" "classname" "light_torch_small_walltorch" } { "light" "225" "origin" "1686 396 672" "classname" "light_flame_large_yellow" } { "light" "225" "classname" "light_flame_large_yellow" "origin" "1686 652 672" } { "classname" "light_flame_large_yellow" "origin" "1008 396 672" "light" "225" } { "origin" "1008 652 672" "classname" "light_flame_large_yellow" "light" "225" } { "classname" "light" "origin" "1360 800 736" "light" "225" } { "classname" "light" "origin" "1360 752 592" "light" "250" } { "classname" "light" "origin" "1360 392 864" "light" "450" } { "light" "450" "origin" "1360 648 864" "classname" "light" } { "light" "225" "origin" "1632 496 672" "classname" "light" } { "classname" "light" "origin" "1064 488 672" "light" "225" } { "light" "225" "origin" "1600 968 672" "classname" "light" } { "classname" "light" "origin" "1104 968 672" "light" "225" } { "classname" "light" "origin" "1200 240 648" "light" "225" } { "light" "225" "origin" "1520 240 648" "classname" "light" } { "sounds" "3" "classname" "func_door" "angle" "0" "targetname" "t80" "wait" "-1" "model" "*35" } { "sounds" "3" "classname" "func_door" "angle" "180" "wait" "-1" "model" "*36" } { "classname" "trigger_once" "target" "t80" "model" "*37" } { "light" "225" "origin" "1344 160 -32" "classname" "light" } { "classname" "light" "origin" "1608 152 -32" "light" "225" } { "classname" "light" "origin" "-520 -448 -288" "light" "175" } { "light" "175" "origin" "-520 -640 -288" "classname" "light" } { "light" "225" "origin" "208 -1152 32" "classname" "light" } { "light" "200" "origin" "150 -1466 -4" "classname" "light_torch_small_walltorch" } { "origin" "518 -890 120" "classname" "light_flame_large_yellow" } { "light" "225" "origin" "520 -888 36" "classname" "light" } { "light" "225" "origin" "516 -764 -48" "classname" "light" } { "classname" "light" "origin" "520 -1028 4" "light" "225" } { "origin" "-144 -728 -256" "classname" "light" } { "light" "250" "origin" "-186 -822 -292" "classname" "light_torch_small_walltorch" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "306 -810 -292" } { "sounds" "2" "targetname" "t82" "spawnflags" "1" "classname" "func_plat" "dmg" "0" "model" "*38" } { "light" "250" "origin" "698 -886 -292" "classname" "light_torch_small_walltorch" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "522 -1066 -292" } { "light" "225" "origin" "520 -776 -280" "classname" "light" } { "light" "175" "origin" "368 -888 -280" "classname" "light" } { "classname" "light" "origin" "384 -248 -256" "light" "175" } { "light" "175" "origin" "384 -456 -256" "classname" "light" } { "sounds" "2" "classname" "func_plat" "model" "*39" } { "origin" "280 -1000 102" "classname" "light_flame_small_yellow" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "728 -1128 78" } { "light" "250" "origin" "312 -1128 78" "classname" "light_flame_small_yellow" } { "light" "225" "origin" "150 -1210 -108" "classname" "light_torch_small_walltorch" } { "light" "175" "origin" "400 -1160 -10" "classname" "light" } { "classname" "light" "origin" "632 -1160 -10" "light" "175" } { "light" "125" "origin" "456 -1160 -118" "classname" "light" } { "classname" "light" "origin" "576 -1160 -118" "light" "125" } { "light" "125" "origin" "344 -1264 -118" "classname" "light" } { "light" "125" "origin" "344 -1096 -118" "classname" "light" } { "light" "100" "origin" "712 -1064 -118" "classname" "light" } { "light" "100" "origin" "216 -1000 -118" "classname" "light" } { "light" "225" "origin" "200 -1000 -6" "classname" "light" } { "light" "125" "origin" "96 -1000 -78" "classname" "light" } { "light" "175" "origin" "72 -1000 122" "classname" "light" } { "sounds" "0" "target" "t81" "wait" "-1" "angle" "-2" "classname" "func_button" "model" "*40" } { "sounds" "3" "targetname" "t81" "lip" "16" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*41" } { "light" "175" "origin" "-272 -1000 120" "classname" "light" } { "light" "175" "origin" "368 -1408 8" "classname" "light" } { "light" "175" "origin" "608 -808 -20" "classname" "light" } { "classname" "light" "origin" "440 -808 -20" "light" "175" } { "light" "100" "origin" "672 -880 -60" "classname" "light" } { "classname" "light" "origin" "368 -888 -60" "light" "100" } { "target" "t82" "classname" "trigger_once" "model" "*42" } { "target" "t82" "classname" "trigger_once" "model" "*43" } { "target" "t83" "classname" "trigger_once" "model" "*44" } { "lip" "-4" "sounds" "0" "targetname" "t83" "classname" "func_door" "angle" "-2" "spawnflags" "5" "wait" "-1" "speed" "35" "model" "*45" } { "classname" "monster_zombie" "origin" "-1218 -532 -438" "angle" "0" "targetname" "t83" } { "origin" "-1270 -558 -438" "classname" "monster_zombie" "angle" "0" "targetname" "t83" } { "sounds" "0" "targetname" "t83" "classname" "func_door" "spawnflags" "4" "angle" "90" "wait" "-1" "lip" "-8" "speed" "200" "model" "*46" } { "spawnflags" "2048" "sounds" "1" "classname" "item_key2" "origin" "-976 -360 -336" } { "classname" "light" "origin" "80 -1144 24" "light" "175" } { "classname" "light" "origin" "-72 -1136 80" "light" "175" } { "lip" "-4" "sounds" "0" "classname" "func_door" "angle" "-2" "spawnflags" "1" "wait" "-1" "targetname" "t83" "speed" "35" "model" "*47" } { "sounds" "0" "classname" "func_door" "angle" "90" "wait" "-1" "speed" "500" "targetname" "t83" "model" "*48" } { "angle" "315" "origin" "-866 -44 -448" "classname" "monster_zombie" "targetname" "t83" } { "classname" "light" "origin" "-892 -64 -450" "light" "175" } { "light" "175" "origin" "-1236 -528 -450" "classname" "light" } { "classname" "light" "origin" "912 -208 -160" "light" "150" } { "light" "150" "origin" "920 -504 -160" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "726 -206 -4" "light" "225" } { "origin" "726 -506 -4" "classname" "light_torch_small_walltorch" "light" "225" } { "classname" "light" "origin" "740 -360 -8" "light" "200" } { "classname" "light" "origin" "1344 -192 -112" "light" "175" } { "light" "175" "origin" "1344 -520 -112" "classname" "light" } { "sounds" "1" "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t84" "model" "*49" } { "sounds" "1" "wait" "-1" "angle" "-1" "classname" "func_door" "targetname" "t84" "model" "*50" } { "origin" "1120 -560 -18" "classname" "light_flame_small_yellow" "light" "250" } { "sounds" "1" "wait" "-1" "angle" "-1" "classname" "func_door" "targetname" "t84" "model" "*51" } { "sounds" "1" "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t84" "model" "*52" } { "classname" "light" "origin" "1216 -136 -136" "light" "125" } { "light" "125" "origin" "1024 -136 -136" "classname" "light" } { "classname" "light" "origin" "1216 -568 -136" "light" "125" } { "light" "125" "origin" "1024 -568 -136" "classname" "light" } { "classname" "light" "origin" "1024 -40 -136" "light" "125" } { "light" "125" "origin" "1216 -40 -136" "classname" "light" } { "classname" "light" "origin" "1216 -656 -136" "light" "125" } { "light" "125" "origin" "1024 -656 -136" "classname" "light" } { "sounds" "2" "classname" "func_button" "angle" "180" "wait" "-1" "target" "t84" "model" "*53" } { "classname" "light" "origin" "1120 -192 -104" "light" "175" } { "light" "175" "origin" "1120 -504 -104" "classname" "light" } { "classname" "light" "origin" "1760 128 -96" "light" "225" } { "sounds" "1" "classname" "func_door_secret" "angle" "90" "spawnflags" "33" // modified for capture the flag "targetname" "t5" "model" "*54" } { "classname" "info_teleport_destination" "origin" "1609 -9 80" "angle" "270" "targetname" "t86" } { "classname" "trigger_teleport" "target" "t86" "model" "*55" } { "light" "225" "origin" "1724 -96 -80" "classname" "light" } { "classname" "path_corner" "origin" "-216 -1504 96" "targetname" "t87" "target" "t88" } { "origin" "-216 -1768 96" "classname" "path_corner" "targetname" "t90" "target" "t87" } { "classname" "path_corner" "origin" "-216 -1768 96" "targetname" "t88" "target" "t89" } { "origin" "-376 -1768 96" "classname" "path_corner" "targetname" "t89" "target" "t90" } { "classname" "monster_zombie" "origin" "-194 -1466 112" "angle" "270" "target" "t87" } { "spawnflags" "1" "angle" "270" "origin" "-154 -1002 72" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "358 -1274 -40" "angle" "90" "targetname" "t93" "spawnflags" "768" } { "spawnflags" "768" "classname" "monster_wizard" "origin" "672 -1080 24" "angle" "270" "target" "t91" } { "spawnflags" "768" "classname" "path_corner" "origin" "672 -1152 8" "targetname" "t91" "target" "t92" } { "spawnflags" "768" "origin" "392 -1160 8" "classname" "path_corner" "targetname" "t92" "target" "t91" } { "classname" "monster_zombie" "origin" "704 -1192 -120" "angle" "135" "targetname" "t93" "spawnflags" "256" } { "spawnflags" "256" "classname" "trigger_once" "target" "t93" "model" "*56" } { "spawnflags" "768" "classname" "trigger_once" "target" "t93" "model" "*57" } { "classname" "path_corner" "origin" "232 -864 -344" "targetname" "t94" "target" "t95" } { "origin" "8 -824 -344" "classname" "path_corner" "targetname" "t95" "target" "t94" } { "classname" "path_corner" "origin" "-96 -816 -344" "targetname" "t96" "target" "t97" } { "origin" "-168 -744 -344" "classname" "path_corner" "targetname" "t97" "target" "t96" } { "classname" "monster_zombie" "origin" "184 -856 -328" "angle" "180" "target" "t94" } { "angle" "180" "origin" "-48 -856 -328" "classname" "monster_zombie" "target" "t96" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "-556 -12 -336" "angle" "0" "targetname" "t83" } { "classname" "monster_zombie" "origin" "-1384 -856 -336" "targetname" "t83" "angle" "270" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "-258 -490 -88" "angle" "90" "targetname" "t111" } { "classname" "path_corner" "origin" "384 -256 -296" "target" "t100" "targetname" "t103" } { "origin" "768 -256 -296" "classname" "path_corner" "targetname" "t100" "target" "t101" } { "classname" "path_corner" "origin" "768 -448 -296" "targetname" "t101" "target" "t102" } { "origin" "384 -456 -296" "classname" "path_corner" "targetname" "t102" "target" "t103" } { "classname" "monster_zombie" "origin" "384 -352 -280" "angle" "90" "target" "t103" } { "classname" "monster_zombie" "origin" "776 -360 -280" "angle" "270" "target" "t101" } { "classname" "path_corner" "origin" "384 -616 -296" "targetname" "t105" "target" "t104" } { "origin" "192 -616 -296" "classname" "path_corner" "targetname" "t104" "target" "t105" } { "classname" "monster_zombie" "origin" "320 -616 -280" "angle" "180" "target" "t104" } { "classname" "path_corner" "origin" "-216 -688 -344" "targetname" "t106" "target" "t107" } { "origin" "-336 -656 -344" "classname" "path_corner" "targetname" "t107" "target" "t106" } { "classname" "monster_zombie" "origin" "-224 -656 -328" "angle" "315" "target" "t106" } { "spawnflags" "1280" "classname" "path_corner" "origin" "232 88 -200" "targetname" "t108" "target" "t109" } { "spawnflags" "1280" "origin" "232 -104 -200" "classname" "path_corner" "targetname" "t109" "target" "t108" } { "spawnflags" "1280" "classname" "monster_zombie" "origin" "238 -18 -184" "angle" "90" "target" "t108" } { "classname" "trigger_once" "target" "t110" "model" "*58" } { "classname" "monster_zombie" "origin" "552 -216 -280" "angle" "225" "targetname" "t110" "spawnflags" "256" } { "angle" "270" "origin" "800 -216 -280" "classname" "monster_zombie" "targetname" "t110" } { "classname" "monster_zombie" "origin" "656 -480 -280" "angle" "225" "targetname" "t110" "spawnflags" "256" } { "classname" "monster_wizard" "origin" "8 -472 -32" "angle" "180" "targetname" "t111" } { "classname" "trigger_once" "target" "t111" "model" "*59" } { "classname" "monster_zombie" "origin" "1024 -88 -184" "angle" "270" "targetname" "t84" } { "angle" "270" "origin" "1216 -72 -184" "classname" "monster_zombie" "targetname" "t84" } { "classname" "monster_zombie" "origin" "1216 -608 -184" "angle" "90" "targetname" "t84" } { "angle" "90" "origin" "1024 -604 -184" "classname" "monster_zombie" "targetname" "t84" } { "classname" "trigger_once" "target" "t112" "model" "*60" } { "spawnflags" "1280" "classname" "path_corner" "origin" "1120 768 544" "targetname" "t116" "target" "t115" } { "spawnflags" "1280" "origin" "1528 752 544" "classname" "path_corner" "targetname" "t115" "target" "t116" } { "spawnflags" "1280" "classname" "monster_demon1" "origin" "1224 768 560" "angle" "0" "target" "t115" } { "classname" "path_corner" "origin" "392 -1408 -48" "targetname" "t118" "target" "t122" } { "origin" "216 -1408 -48" "classname" "path_corner" "targetname" "t117" "target" "t118" } { "spawnflags" "1" "classname" "monster_ogre" "origin" "302 -1410 -40" "angle" "180" "target" "t117" } { "classname" "weapon_nailgun" "origin" "-712 -1240 60" "angle" "90" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "790 -346 -40" "angle" "0" } { "classname" "light_torch_small_walltorch" "origin" "1658 -574 -92" "light" "225" } { "sounds" "0" "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t119" "model" "*61" } { "sounds" "0" "classname" "func_door" "wait" "-1" "angle" "-1" "targetname" "t119" "model" "*62" } { "sounds" "3" "classname" "func_door" "angle" "180" "wait" "-1" "targetname" "t120" "model" "*63" } { "sounds" "0" "classname" "func_door" "wait" "-1" "angle" "0" "targetname" "t120" "model" "*64" } { "classname" "item_shells" "origin" "1592 -524 -152" "spawnflags" "1" } { "classname" "trigger_once" "spawnflags" "1792" "target" "t119" "model" "*65" } { "spawnflags" "1792" "classname" "trigger_once" "target" "t120" "model" "*66" } { "classname" "item_health" "origin" "-960 -1616 64" } { "spawnflags" "1" "origin" "-960 -1664 64" "classname" "item_health" } { "classname" "weapon_supershotgun" "origin" "184 -1432 -56" "spawnflags" "2048" } { "spawnflags" "1024" "classname" "item_shells" "origin" "-688 -1944 88" } { "classname" "item_rockets" "origin" "-352 -1128 48" } { "classname" "item_spikes" "origin" "-1000 -1320 -32" "spawnflags" "1" } { "classname" "item_armor2" "origin" "-288 -992 48" } { "classname" "item_health" "origin" "-24 -1272 80" "spawnflags" "2048" } { "classname" "item_spikes" "origin" "344 -1288 -152" } { "classname" "item_health" "origin" "656 -904 -112" "spawnflags" "1" } { "classname" "item_health" "origin" "616 -856 -112" "spawnflags" "1" } { "classname" "item_rockets" "origin" "504 -1064 -352" } { "classname" "item_health" "origin" "-144 -840 -348" } { "origin" "-464 -684 -348" "classname" "item_health" } { "classname" "item_spikes" "origin" "1008 -70 -208" "spawnflags" "1" } { "classname" "item_shells" "origin" "1008 -656 -208" } { "classname" "item_rockets" "origin" "792 -264 -64" "spawnflags" "1" } { "classname" "item_health" "origin" "1200 -660 -208" } { "classname" "item_health" "origin" "1344 -200 -208" "spawnflags" "1" } { "spawnflags" "1" "origin" "1288 -200 -208" "classname" "item_health" } { "classname" "trigger_once" "target" "t171" "spawnflags" "256" "model" "*67" } { "classname" "light" "origin" "32 -1312 112" "light" "175" } { "light" "175" "origin" "-400 -1136 112" "classname" "light" } { "classname" "light" "origin" "-1144 0 -20" "light" "175" } { "light" "175" "origin" "-1088 -272 -20" "classname" "light" } { "classname" "item_shells" "origin" "536 -1464 -64" } { "classname" "item_spikes" "origin" "-1192 16 -92" } { "origin" "-1128 16 -92" "classname" "item_spikes" } { "classname" "item_shells" "origin" "344 -904 -112" } { "classname" "item_spikes" "origin" "-200 -176 -96" } { "classname" "item_health" "origin" "176 -152 -208" "spawnflags" "1" } { "spawnflags" "1" "origin" "272 -152 -208" "classname" "item_health" } { "classname" "item_health" "origin" "24 152 -208" } { "classname" "item_rockets" "origin" "48 -112 -96" "spawnflags" "1" } { "classname" "item_shells" "origin" "-576 -24 -96" "spawnflags" "2048" } { "classname" "item_shells" "origin" "64 152 -208" } { "spawnflags" "1" "origin" "-936 -936 -32" "classname" "item_spikes" } { "classname" "item_rockets" "origin" "-1048 -752 -96" } { "origin" "216 -1408 -48" "classname" "path_corner" "targetname" "t122" "target" "t123" } { "classname" "path_corner" "origin" "216 -1264 -48" "targetname" "t123" "target" "t117" } { "classname" "item_health" "origin" "152 -1144 -150" "spawnflags" "1" } { "sounds" "1" "classname" "func_door" "angle" "-2" "wait" "-1" "lip" "-2" "targetname" "t83" "model" "*68" } { "classname" "monster_ogre" "origin" "34 -1466 72" "angle" "90" "target" "t124" "spawnflags" "257" } { "classname" "path_corner" "origin" "32 -1280 56" "targetname" "t124" "target" "t125" "spawnflags" "256" } { "origin" "-320 -1280 56" "classname" "path_corner" "targetname" "t125" "target" "t124" "spawnflags" "256" } { "classname" "light" "origin" "40 -1488 120" "light" "75" } { "classname" "light" "origin" "-264 -472 -32" "light" "175" } { "classname" "light" "origin" "80 -464 -136" "light" "100" } { "classname" "light" "origin" "232 -136 -144" "light" "100" } { "light" "100" "origin" "48 144 -144" "classname" "light" } { "classname" "light" "origin" "64 -96 -32" "light" "100" } { "classname" "item_health" "origin" "1288 104 -160" } { "spawnflags" "1" "origin" "1336 104 -160" "classname" "item_health" } { "classname" "item_shells" "origin" "1600 968 536" } { "classname" "light" "origin" "584 -448 -256" "light" "100" } { "light" "100" "origin" "568 -248 -256" "classname" "light" } { "classname" "light" "origin" "400 -624 -256" "light" "100" } { "classname" "light" "origin" "-928 -48 -40" "light" "125" } { "classname" "item_health" "origin" "-1256 -1000 -30" "spawnflags" "3584" } { "spawnflags" "3584" "origin" "-1208 -1000 -30" "classname" "item_health" } { "classname" "light" "origin" "-1376 -104 26" "light" "175" } { "origin" "-1320 -56 -94" "classname" "item_health" } { "light" "175" "origin" "-448 -160 136" "classname" "light" } { "classname" "light" "origin" "-416 -216 -24" "light" "175" } { "light" "225" "origin" "-288 -64 -32" "classname" "light" } { "classname" "light" "origin" "-448 -88 -32" "light" "125" } { "classname" "monster_wizard" "origin" "-528 -304 -64" "angle" "0" "spawnflags" "256" "targetname" "t148" } { "classname" "light" "origin" "-648 16 -48" "light" "175" } { "classname" "light" "origin" "-600 -320 40" "light" "175" } { "classname" "monster_wizard" "origin" "-1196 100 0" "angle" "90" "targetname" "t147" } { "classname" "light" "origin" "-704 -384 -152" "light" "175" } { "classname" "light" "origin" "-40 -992 152" "light" "175" } { "origin" "1686 884 672" "classname" "light_flame_large_yellow" "light" "225" } { "light" "225" "classname" "light_flame_large_yellow" "origin" "1008 884 672" } { "classname" "light" "origin" "1360 880 864" "light" "450" } { "classname" "light" "origin" "1344 960 576" "light" "225" } { "classname" "light" "origin" "1096 632 592" "light" "175" } { "light" "175" "origin" "1600 632 592" "classname" "light" } { "classname" "light" "origin" "1080 396 592" "light" "175" } { "light" "175" "origin" "1620 396 592" "classname" "light" } { "classname" "light" "origin" "1084 884 592" "light" "175" } { "light" "175" "origin" "1604 884 592" "classname" "light" } { "classname" "monster_demon1" "origin" "1584 816 560" "angle" "180" "target" "t130" "spawnflags" "1024" } { "classname" "path_corner" "origin" "1536 880 544" "targetname" "t130" "target" "t131" "spawnflags" "1024" } { "origin" "1120 880 544" "classname" "path_corner" "targetname" "t131" "target" "t130" "spawnflags" "1024" } { "classname" "trigger_changelevel" "map" "e1m4" "model" "*69" } { "light" "175" "origin" "-136 -1568 144" "classname" "light" } { "light" "175" "origin" "-192 -1304 144" "classname" "light" } { "classname" "item_health" "origin" "-200 -96 -96" } { "targetname" "t13" "target" "t14" "classname" "func_train" "speed" "35" "dmg" "75" "sounds" "1" "model" "*70" } { "classname" "item_health" "origin" "-1208 -1000 -24" "spawnflags" "1281" } { "spawnflags" "1281" "origin" "-1256 -1000 -24" "classname" "item_health" } { "classname" "item_shells" "origin" "-200 -216 -96" "spawnflags" "2048" } { "classname" "monster_zombie" "origin" "-912 -88 -448" "angle" "315" "spawnflags" "256" } { "spawnflags" "1025" "classname" "monster_ogre" "origin" "-1400 -256 -72" "angle" "0" } { "targetname" "t112" "target" "t135" "angle" "270" "origin" "1608 -96 80" "classname" "monster_ogre" } { "targetname" "t112" "target" "t135" "classname" "monster_ogre" "origin" "1608 -344 104" "angle" "90" } { "target" "t119" "targetname" "t135" "count" "1" "classname" "trigger_counter" "spawnflags" "1" "model" "*71" } { "target" "t120" "targetname" "t135" "count" "2" "classname" "trigger_counter" "spawnflags" "1" "model" "*72" } { "classname" "monster_zombie" "origin" "368 -1136 -120" "angle" "0" "targetname" "t93" } { "classname" "monster_zombie" "origin" "-16 -904 -328" "angle" "45" } { "classname" "monster_zombie" "origin" "808 -488 -280" "angle" "135" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "1384 -344 -136" "angle" "180" "spawnflags" "768" "targetname" "t140" } { "classname" "path_corner" "origin" "-272 -1824 96" "targetname" "t138" "target" "t137" } { "origin" "-176 -1800 96" "classname" "path_corner" "targetname" "t136" "target" "t138" } { "classname" "path_corner" "origin" "-176 -1800 96" "targetname" "t137" "target" "t139" } { "origin" "-144 -1496 96" "classname" "path_corner" "target" "t136" "targetname" "t139" } { "classname" "monster_zombie" "origin" "-136 -1416 112" "angle" "270" "target" "t139" } { "classname" "func_door" "angle" "-1" "wait" "-1" "lip" "16" "sounds" "3" "targetname" "t81" "model" "*73" } { "light" "125" "origin" "64 -160 -296" "classname" "light" } { "classname" "light" "origin" "64 -280 -296" "light" "125" } { "classname" "trigger_once" "spawnflags" "768" "target" "t140" "model" "*74" } { "classname" "monster_zombie" "origin" "1536 104 -136" "angle" "270" "targetname" "t112" "spawnflags" "1024" } { "angle" "315" "origin" "1440 168 -136" "classname" "monster_zombie" "targetname" "t112" "spawnflags" "1024" } { "classname" "monster_zombie" "origin" "1592 112 -136" "angle" "270" "targetname" "t112" "spawnflags" "1280" } { "targetname" "t140" "spawnflags" "1536" "angle" "180" "origin" "1384 -344 -136" "classname" "monster_zombie" } { "angle" "0" "classname" "func_door_secret" "model" "*75" } { "target" "t141" "classname" "trigger_teleport" "model" "*76" } { "light" "200" "origin" "1608 -688 -88" "classname" "light" } { "targetname" "t141" "angle" "90" "origin" "1612 -372 72" "classname" "info_teleport_destination" } { "classname" "trigger_secret" "model" "*77" } { "spawnflags" "2049" "origin" "1592 -164 56" "classname" "item_rockets" } { "classname" "monster_zombie" "origin" "116 132 -184" "angle" "315" "spawnflags" "768" } { "spawnflags" "768" "angle" "315" "origin" "264 152 -184" "classname" "monster_zombie" } { "origin" "1608 -584 -152" "classname" "item_armor2" } { "targetname" "t144" "origin" "-404 -1804 92" "classname" "info_null" } { "target" "t144" "light" "350" "origin" "-392 -1804 160" "classname" "light" } { "origin" "-408 -1800 88" "classname" "weapon_grenadelauncher" } { "target" "t146" "targetname" "t145" "classname" "path_corner" "origin" "-112 -1536 96" } { "target" "t145" "targetname" "t146" "origin" "-112 -1608 96" "classname" "path_corner" } { "target" "t145" "angle" "270" "origin" "-104 -1480 112" "classname" "monster_zombie" } { "classname" "light" "origin" "-584 8 -288" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "-494 -334 -300" "light" "250" } { "classname" "trigger_once" "target" "t147" "model" "*78" } { "classname" "trigger_once" "target" "t148" "spawnflags" "256" "model" "*79" } { "origin" "-200 -136 -96" "classname" "item_health" "spawnflags" "3072" } { "speed" "50" "sounds" "1" "targetname" "t149" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*80" } { "targetname" "t149" "spawnflags" "768" "angle" "180" "origin" "-848 -928 -4" "classname" "monster_zombie" } { "targetname" "t149" "classname" "monster_zombie" "origin" "-808 -984 -4" "angle" "180" "spawnflags" "768" } { "targetname" "t149" "spawnflags" "768" "angle" "180" "origin" "-856 -992 -4" "classname" "monster_zombie" } { "target" "t149" "spawnflags" "768" "classname" "trigger_once" "model" "*81" } { "target" "t169" "spawnflags" "769" "angle" "0" "origin" "-1384 -256 -72" "classname" "monster_shambler" } { "spawnflags" "769" "origin" "-808 -936 -32" "classname" "item_rockets" } { "spawnflags" "2" "target" "t150" "classname" "trigger_teleport" "targetname" "t151" "model" "*82" } { "targetname" "t151" "spawnflags" "768" "angle" "270" "origin" "-1224 272 -64" "classname" "monster_shambler" } { "targetname" "t150" "angle" "270" "origin" "-1232 -136 -88" "classname" "info_teleport_destination" } { "light" "150" "origin" "-800 -968 28" "classname" "light" } { "spawnflags" "768" "targetname" "t155" "target" "t152" "origin" "600 -856 -344" "classname" "path_corner" } { "spawnflags" "768" "target" "t153" "targetname" "t152" "classname" "path_corner" "origin" "440 -848 -344" } { "spawnflags" "768" "target" "t154" "targetname" "t153" "origin" "440 -968 -344" "classname" "path_corner" } { "spawnflags" "768" "target" "t155" "targetname" "t154" "classname" "path_corner" "origin" "608 -968 -344" } { "spawnflags" "768" "target" "t152" "origin" "536 -848 -328" "classname" "monster_zombie" } { "spawnflags" "768" "target" "t154" "origin" "520 -960 -328" "classname" "monster_zombie" } { "classname" "func_wall" "spawnflags" "1024" "model" "*83" } { "classname" "light_torch_small_walltorch" "origin" "586 -1466 -4" "light" "200" } { "target" "t157" "classname" "monster_ogre" "origin" "648 -1400 152" "angle" "180" "targetname" "t156" "spawnflags" "768" } { "classname" "trigger_once" "spawnflags" "768" "target" "t156" "model" "*84" } { "classname" "trigger_once" "target" "t156" "spawnflags" "768" "model" "*85" } { "light" "125" "origin" "672 -1400 -16" "classname" "light" } { "sounds" "1" "targetname" "t157" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*86" } { "targetname" "t157" "spawnflags" "768" "angle" "180" "origin" "648 -1400 -40" "classname" "monster_ogre" } { "target" "t157" "origin" "676 -1336 -28" "classname" "info_null" } { "light" "125" "origin" "520 -1296 16" "classname" "light" } { "target" "t12" "wait" "-1" "health" "1" "angle" "180" "classname" "func_button" "model" "*87" } { "spawnflags" "2561" "classname" "item_shells" "origin" "672 -1144 -152" } { "classname" "path_corner" "origin" "248 88 -200" "spawnflags" "768" "targetname" "t159" "target" "t160" } { "spawnflags" "768" "origin" "216 -104 -200" "classname" "path_corner" "targetname" "t160" "target" "t159" } { "classname" "monster_ogre" "origin" "216 24 -184" "spawnflags" "768" "angle" "90" "target" "t159" } { "angle" "0" "origin" "782 -434 -40" "classname" "monster_ogre" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "1600 184 -136" "angle" "270" "targetname" "t112" "spawnflags" "769" } { "classname" "monster_demon1" "origin" "1496 1272 560" "angle" "270" "spawnflags" "768" "targetname" "t173" "target" "t175" } { "angle" "270" "origin" "1392 1272 560" "classname" "monster_demon1" "spawnflags" "768" "targetname" "t174" "target" "t175" } { "classname" "monster_shambler" "origin" "1288 1288 560" "angle" "270" "spawnflags" "768" "targetname" "t176" } { "classname" "monster_demon1" "origin" "1288 920 560" "angle" "180" "spawnflags" "768" "target" "t174" } { "classname" "monster_demon1" "origin" "1408 920 560" "angle" "0" "target" "t173" "spawnflags" "768" } { "classname" "trigger_teleport" "spawnflags" "770" "target" "t165" "targetname" "t176" "model" "*88" } { "classname" "trigger_teleport" "spawnflags" "770" "target" "t166" "targetname" "t174" "model" "*89" } { "classname" "trigger_teleport" "spawnflags" "770" "target" "t167" "targetname" "t173" "model" "*90" } { "classname" "info_teleport_destination" "origin" "1352 912 544" "angle" "270" "spawnflags" "768" "targetname" "t165" } { "spawnflags" "768" "angle" "270" "origin" "1512 912 544" "classname" "info_teleport_destination" "targetname" "t167" } { "classname" "info_teleport_destination" "origin" "1176 912 544" "angle" "270" "spawnflags" "768" "targetname" "t166" } { "spawnflags" "2816" "origin" "552 -1024 -352" "classname" "item_rockets" } { "spawnflags" "768" "origin" "-1072 -256 -96" "classname" "item_shells" } { "spawnflags" "2817" "origin" "-680 -1944 88" "classname" "item_shells" } { "classname" "trigger_once" "delay" "3" "targetname" "t169" "spawnflags" "768" "target" "t151" "model" "*91" } { "classname" "monster_wizard" "origin" "-1400 -856 -40" "angle" "270" "spawnflags" "768" "targetname" "t147" } { "classname" "monster_wizard" "origin" "-1480 -312 112" "angle" "135" "spawnflags" "256" "targetname" "t147" } { "classname" "monster_wizard" "origin" "-792 -452 152" "angle" "270" "spawnflags" "257" "targetname" "t170" } { "classname" "trigger_once" "spawnflags" "256" "target" "t170" "model" "*92" } { "targetname" "t171" "spawnflags" "1281" "angle" "180" "origin" "28 -1352 72" "classname" "monster_ogre" } { "targetname" "t171" "spawnflags" "769" "angle" "180" "origin" "28 -1344 72" "classname" "monster_demon1" } { "angle" "315" "origin" "-864 -1696 92" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-1216 -928 -8" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "1128 -352 -184" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "384 136 -184" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-816 -152 -80" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-200 -368 -72" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "-976 -360 -360" "classname" "weapon_rocketlauncher" } { "classname" "weapon_supershotgun" "origin" "784 -360 -64" "spawnflags" "1792" } { "classname" "trigger_teleport" "spawnflags" "1792" "target" "t86" "model" "*93" } { "classname" "func_wall" "spawnflags" "1792" "model" "*94" } { "classname" "func_wall" "spawnflags" "1792" "model" "*95" } { "classname" "func_wall" "spawnflags" "1792" "model" "*96" } { "classname" "func_wall" "spawnflags" "1792" "model" "*97" } { "classname" "func_wall" "spawnflags" "1792" "model" "*98" } { "classname" "info_teleport_destination" "origin" "-864 -1696 76" "angle" "0" "spawnflags" "1792" "targetname" "t172" } { "classname" "func_wall" "spawnflags" "1792" "model" "*99" } { "classname" "item_health" "origin" "1328 816 540" "spawnflags" "1794" } { "classname" "weapon_supernailgun" "origin" "1648 -96 56" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "1560 -112 56" "spawnflags" "1793" } { "classname" "weapon_nailgun" "origin" "232 24 -208" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "72 -864 -328" "angle" "180" } { "classname" "item_health" "origin" "1064 504 540" "spawnflags" "1536" } { "classname" "item_health" "origin" "1064 464 540" "spawnflags" "2048" } { "targetname" "t171" "classname" "monster_demon1" "origin" "-408 -1344 72" "angle" "0" "spawnflags" "769" } { "classname" "trigger_once" "message" "Shoot the button!" "targetname" "t13" "spawnflags" "3584" "model" "*100" } { "mangle" "20 225 0" "origin" "-544 24 176" "classname" "info_intermission" } { "mangle" "20 305 0" "origin" "904 -216 56" "classname" "info_intermission" } { "mangle" "12 65 0" "origin" "1112 288 680" "classname" "info_intermission" } { "mangle" "15 45 0" "origin" "-1448 -744 64" "classname" "info_intermission" } { "light" "200" "origin" "-1552 -560 -464" "classname" "light" } { "light" "125" "origin" "-1448 -560 -424" "classname" "light" } { "light" "125" "origin" "-1672 -568 -424" "classname" "light" } { "light" "200" "origin" "-1774 -550 -300" "classname" "light_torch_small_walltorch" } { "light" "125" "origin" "-1584 -560 -328" "classname" "light" } { "classname" "trigger_secret" "model" "*101" } { "origin" "-1736 -552 -336" "classname" "item_artifact_invisibility" } { "angle" "180" "spawnflags" "3" "classname" "func_door_secret" "model" "*102" } { "light" "150" "origin" "368 -1400 -120" "classname" "light" } { "classname" "light" "origin" "520 -1320 -120" "light" "150" } { "light" "150" "origin" "512 -1408 -120" "classname" "light" } { "classname" "trigger_secret" "model" "*103" } { "origin" "544 -1424 -152" "classname" "item_health" } { "spawnflags" "1" "origin" "504 -1304 -152" "classname" "item_rockets" } { "spawnflags" "2817" "origin" "1072 968 544" "classname" "item_shells" } { "classname" "item_shells" "origin" "1112 968 544" "spawnflags" "2817" } { "angle" "270" "origin" "-648 -1592 88" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-824 -1584 88" "angle" "270" } { "angle" "270" "origin" "-888 -1584 88" "classname" "info_player_coop" } { "classname" "item_health" "origin" "32 -1544 56" } { "spawnflags" "1792" "classname" "func_wall" "model" "*104" } { "classname" "trigger_counter" "count" "2" "targetname" "t175" "spawnflags" "1" "target" "t176" "model" "*105" } { "origin" "162 -878 -208" "classname" "ambient_drip" } { "origin" "-150 -758 -248" "classname" "ambient_drip" } { "origin" "-518 -606 -256" "classname" "ambient_drip" } { "origin" "-742 -166 -256" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-958 -374 -256" } { "origin" "-1070 -670 -256" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-1438 -694 -256" } { "origin" "394 -102 -152" "classname" "ambient_drip" } { "origin" "50 98 -96" "classname" "ambient_drip" } { "origin" "386 -262 -256" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "602 -470 -256" } { "origin" "762 -246 -256" "classname" "ambient_drip" } { "origin" "978 -358 -192" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-1686 -558 -288" } { "classname" "ambient_drip" "origin" "58 -214 -248" } { "origin" "-822 -374 -304" "classname" "ambient_swamp2" } { "classname" "ambient_swamp2" "origin" "-1150 -646 -304" } { "origin" "-1470 -438 -304" "classname" "ambient_swamp1" } { "classname" "ambient_swamp1" "origin" "-854 50 -304" } { "origin" "-526 -526 -304" "classname" "ambient_swamp1" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "-950 -1865 92" "classname" "item_flag_team1" } { "angle" "270" "origin" "-834 -1760 104" "classname" "info_player_team1" } { "angle" "270" "origin" "-734 -1760 104" "classname" "info_player_team1" } { "angle" "270" "origin" "-634 -1760 104" "classname" "info_player_team1" } { "angle" "270" "origin" "-834 -1660 104" "classname" "info_player_team1" } { "angle" "270" "origin" "-734 -1660 104" "classname" "info_player_team1" } { "angle" "270" "origin" "-634 -1660 104" "classname" "info_player_team1" } // team2 { "origin" "1360 434 -132" "classname" "item_flag_team2" "angle" "90" } { "angle" "0" "origin" "1266 377 -132" "classname" "info_player_team2" } { "angle" "0" "origin" "1366 377 -132" "classname" "info_player_team2" } { "angle" "0" "origin" "1466 377 -132" "classname" "info_player_team2" } { "angle" "0" "origin" "1266 477 -132" "classname" "info_player_team2" } { "angle" "0" "origin" "1366 477 -132" "classname" "info_player_team2" } { "angle" "0" "origin" "1466 477 -132" "classname" "info_player_team2" } // base one weapons upgrade //{ //"classname" "item_health" //"origin" "-488 2064 1220" //} //{ //"origin" "-488 2112 1220" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "-488 2160 1220" //} //{ //"origin" "-72 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-120 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-168 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-72 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-120 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-168 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-72 2160 1220" //"classname" "weapon_supershotgun" //} //{ //"origin" "-120 2160 1220" //"classname" "item_armor2" //} //{ //"origin" "-168 2160 1220" //"classname" "weapon_supernailgun" //} // //// base two weapons upgrade //{ //"classname" "item_shells" //"origin" "1240 768 1384" //} //{ //"classname" "item_shells" //"origin" "1192 768 1384" //} //{ //"classname" "item_shells" //"origin" "1144 768 1384" //} //{ //"classname" "item_spikes" //"origin" "1240 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1192 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1144 816 1384" //} //{ //"origin" "1240 864 1384" //"classname" "weapon_supershotgun" //} //{ //"classname" "item_armor2" //"origin" "1192 864 1384" //} //{ //"classname" "weapon_supernailgun" //"origin" "1144 864 1384" //} //{ //"origin" "1240 912 1384" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "1192 912 1384" //} //{ //"classname" "item_health" //"origin" "1144 912 1384" //} // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m4.ent000066400000000000000000001324011475442401000251730ustar00rootroot00000000000000{ "message" "the Grisly Grotto" "worldtype" "0" "classname" "worldspawn" "wad" "gfx/wizard.wad" "sounds" "5" } { "classname" "light" "origin" "464 480 1656" "light" "300" } { "light" "400" "origin" "712 296 1512" "classname" "light" } { "sounds" "3" "angle" "180" "classname" "func_door" "model" "*1" } { "angle" "0" "classname" "func_door" "model" "*2" } { "classname" "light_flame_small_yellow" "origin" "560 -112 1374" } { "origin" "848 -112 1374" "classname" "light_flame_small_yellow" } { "origin" "760 656 1536" "classname" "light" } { "light" "400" "origin" "834 498 1040" "classname" "light" } { "light" "200" "classname" "light" "origin" "944 728 1456" } { "classname" "light_flame_small_yellow" "origin" "1016 80 998" } { "origin" "392 80 998" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "680 1224 516" "light" "200" } { "light" "200" "origin" "704 992 516" "classname" "light" } { "light" "200" "origin" "696 1608 628" "classname" "light" } { "origin" "704 1368 588" "classname" "light" } { "origin" "816 1616 444" "classname" "light" } { "classname" "light" "origin" "712 1728 444" } { "origin" "592 1608 444" "classname" "light" } { "classname" "light" "origin" "624 1096 444" } { "light" "300" "origin" "432 1328 816" "classname" "light" } { "classname" "light" "origin" "696 1112 816" "light" "300" } { "classname" "light" "origin" "704 -80 960" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "818 18 948" "light" "200" } { "origin" "586 18 948" "classname" "light_torch_small_walltorch" "light" "200" } { "light" "200" "origin" "688 496 880" "classname" "light" } { "origin" "489 483 1356" "classname" "light_flame_large_yellow" } { "light" "200" "origin" "704 -120 1360" "classname" "light" } { "classname" "light" "origin" "1216 936 1560" "light" "200" } { "origin" "1294 826 1576" "classname" "light_flame_large_yellow" } { "sounds" "1" "targetname" "t1" "wait" "-1" "angle" "180" "classname" "func_door" "model" "*3" } { "angle" "0" "wait" "-1" "classname" "func_door" "model" "*4" } { "target" "t1" "classname" "trigger_once" "model" "*5" } { "map" "e1m5" "classname" "trigger_changelevel" "model" "*6" } { "wait" "-1" "angle" "0" "classname" "func_door" "speed" "50" "model" "*7" } { "classname" "info_player_start" "origin" "-256 2272 1240" "angle" "270" } { "targetname" "t23" "classname" "func_door" "angle" "180" "wait" "-1" "speed" "50" "sounds" "3" "model" "*8" } { "classname" "light" "origin" "696 704 820" } { "classname" "light" "origin" "704 776 672" "light" "200" } { "classname" "light" "origin" "360 904 520" "light" "200" } { "origin" "704 856 400" "classname" "light" "light" "200" } { "classname" "light" "origin" "944 880 416" "light" "150" } { "origin" "1056 1176 424" "classname" "light" "light" "200" } { "classname" "light" "origin" "1096 1408 360" } { "classname" "light" "origin" "416 1696 360" } { "origin" "328 1368 360" "classname" "light" "light" "200" } { "light" "200 " "classname" "light" "origin" "696 752 896" } { "light" "250" "origin" "798 1850 1024" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "642 1850 1024" "light" "250" } { "light" "200 " "origin" "700 1364 952" "classname" "light" } { "classname" "light_flame_large_yellow" "origin" "1094 1494 1064" } { "origin" "324 1104 1064" "classname" "light_flame_large_yellow" } { "light" "200 " "origin" "704 1660 952" "classname" "light" } { "sounds" "3" "classname" "func_door" "angle" "180" "wait" "-1" "targetname" "t2" "model" "*9" } { "sounds" "3" "classname" "func_door" "wait" "-1" "angle" "0" "targetname" "t4" "model" "*10" } { "classname" "trigger_once" "targetname" "t4" "target" "t7" "model" "*11" } { "classname" "trigger_once" "targetname" "t2" "target" "t7" "model" "*12" } { "dmg" "90" "speed" "200" "classname" "func_train" "target" "t5" "targetname" "t8" "model" "*13" } { "classname" "path_corner" "origin" "-359 1528 1316" "targetname" "t5" "target" "t6" } { "classname" "path_corner" "origin" "-359 1528 880" "targetname" "t6" "target" "t5" "wait" "-1" } { "classname" "trigger_counter" "targetname" "t7" "target" "t8" "count" "2" "model" "*14" } { "targetname" "t11" "origin" "-96 1640 1256" "classname" "info_null" } { "targetname" "t9" "origin" "-416 1640 1256" "classname" "info_null" } { "light" "400" "target" "t9" "origin" "-396 1640 1256" "classname" "light" } { "light" "400" "target" "t11" "origin" "-116 1640 1256" "classname" "light" } { "classname" "light" "origin" "-328 1564 1532" } { "classname" "light_flame_small_yellow" "origin" "-88 1640 1514" } { "origin" "-424 1640 1514" "classname" "light_flame_small_yellow" } { "origin" "-248 1464 1154" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "-256 1808 1046" } { "light" "200" "origin" "-164 1732 1268" "classname" "light" } { "classname" "light" "origin" "-348 1732 1268" "light" "200" } { "light" "150" "origin" "-248 1500 1056" "classname" "light" } { "light" "150" "origin" "-256 1772 956" "classname" "light" } { "classname" "light" "origin" "-128 1636 920" "light" "150" } { "light" "150" "origin" "-124 1640 920" "classname" "light" } { "classname" "light" "origin" "-172 1524 920" "light" "150" } { "light" "150" "origin" "-284 1516 920" "classname" "light" } { "classname" "light" "origin" "-360 1580 920" "light" "150" } { "light" "75" "origin" "-360 1700 920" "classname" "light" } { "classname" "light" "origin" "72 1632 928" "light" "125" } { "light" "150" "origin" "80 1488 928" "classname" "light" } { "classname" "light_flame_large_yellow" "origin" "158 1308 1064" } { "classname" "light" "origin" "-192 1688 1380" "light" "100" } { "light" "100" "origin" "-192 1592 1380" "classname" "light" } { "classname" "light" "origin" "-320 1592 1380" "light" "100" } { "light" "100" "origin" "-320 1688 1380" "classname" "light" } { "classname" "light" "origin" "-384 1640 1452" "light" "125" } { "classname" "light" "origin" "-112 1640 1452" "light" "125" } { "light" "200" "origin" "-248 1504 1336" "classname" "light" } { "classname" "light" "origin" "-128 1640 1336" "light" "200" } { "light" "200" "origin" "-384 1640 1336" "classname" "light" } { "classname" "light" "origin" "696 1608 816" "light" "300" } { "light" "200" "classname" "light" "origin" "888 1328 424" } { "classname" "light" "origin" "160 1352 960" "light" "150" } { "light" "150" "origin" "368 1104 1000" "classname" "light" } { "classname" "light" "origin" "1048 1504 1000" "light" "150" } { "classname" "light" "origin" "992 992 1048" "light" "150" } { "classname" "light" "origin" "48 1384 1008" "light" "100" } { "light" "150" "origin" "1080 1144 1048" "classname" "light" } { "classname" "light" "origin" "968 824 976" "light" "150" } { "classname" "light" "origin" "896 1328 1000" "light" "150" } { "classname" "light" "origin" "368 1616 1000" "light" "175" } { "classname" "light" "origin" "256 1496 824" "light" "150" } { "light" "150" "origin" "256 1352 824" "classname" "light" } { "classname" "light" "origin" "856 1368 536" "light" "200" } { "light" "150" "origin" "552 1360 536" "classname" "light" } { "classname" "light" "origin" "872 1552 1056" "light" "150" } { "classname" "light" "origin" "1032 1056 904" "light" "150" } { "light" "150" "origin" "1080 1184 904" "classname" "light" } { "classname" "light" "origin" "864 848 904" "light" "150" } { "classname" "light" "origin" "312 1496 1016" "light" "175" } { "light" "200" "origin" "704 1368 808" "classname" "light" } { "light" "150" "origin" "464 816 904" "classname" "light" } { "light" "200" "origin" "944 888 800" "classname" "light" } { "light" "150" "origin" "888 1112 728" "classname" "light" } { "light" "175" "origin" "1008 1504 728" "classname" "light" } { "light" "200" "origin" "720 1848 1200" "classname" "light" } { "light" "200" "origin" "704 888 672" "classname" "light" } { "light" "175" "origin" "512 1456 1040" "classname" "light" } { "light" "150" "origin" "440 840 380" "classname" "light" } { "light" "150" "origin" "720 1848 1028" "classname" "light" } { "light" "150" "origin" "720 1936 1024" "classname" "light" } { "origin" "544 2128 984" "classname" "light" "light" "200" } { "light" "200" "origin" "712 1912 576" "classname" "light" } { "light" "300" "origin" "720 2544 856" "classname" "light" } { "light" "200" "origin" "888 2048 592" "classname" "light" } { "origin" "704 2496 1128" "classname" "light" } { "origin" "512 2048 976" "classname" "light" "light" "150" } { "origin" "952 2328 528" "classname" "light" "light" "200" } { "classname" "light" "origin" "700 2760 808" "light" "200" } { "classname" "light" "origin" "700 2800 616" "light" "200" } { "classname" "light" "origin" "584 2780 584" "light" "175" } { "light" "175" "origin" "808 2780 584" "classname" "light" } { "sounds" "3" "wait" "-1" "targetname" "t29" "classname" "func_door" "angle" "270" "model" "*15" } { "message" "This door is opened elsewhere..." "wait" "-1" "classname" "func_door" "angle" "90" "model" "*16" } { "classname" "light" "origin" "424 2304 1000" "light" "200" } { "light" "300" "origin" "696 2880 1062" "classname" "light_flame_small_yellow" } { "light" "200" "classname" "light" "origin" "864 2128 984" } { "classname" "light_flame_large_yellow" "origin" "702 2154 1228" "light" "0" } { "classname" "light" "origin" "832 2008 1136" "light" "200" } { "classname" "light" "origin" "584 2008 1136" "light" "200" } { "light" "200" "origin" "272 2016 1136" "classname" "light" } { "classname" "light" "origin" "272 2320 1136" "light" "150" } { "light" "150" "origin" "1104 2408 984" "classname" "light" } { "sounds" "2" "classname" "func_plat" "wait" "4" "model" "*17" } { "classname" "light" "origin" "700 2844 996" "light" "200" } { "classname" "light" "origin" "704 2216 1252" } { "origin" "936 2304 1252" "classname" "light" } { "classname" "light" "origin" "936 2536 1252" } { "light" "300" "classname" "light" "origin" "488 2536 1252" } { "origin" "488 2304 1252" "classname" "light" "light" "300" } { "light" "0" "origin" "998 2306 1228" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "998 2534 1228" "light" "0" } { "light" "0" "origin" "426 2534 1228" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "426 2306 1228" "light" "0" } { "classname" "light" "origin" "704 2152 984" "light" "200" } { "classname" "light_flame_small_yellow" "origin" "1160 2400 1038" "light" "250" } { "origin" "840 2536 630" "classname" "light_flame_small_yellow" "light" "250" } { "classname" "light_flame_small_yellow" "origin" "584 2544 630" "light" "250" } { "light" "250" "origin" "408 2304 694" "classname" "light_flame_small_yellow" } { "light" "200" "classname" "light" "origin" "960 2632 528" } { "classname" "light" "origin" "960 2480 528" "light" "150" } { "classname" "light" "origin" "456 2304 624" "light" "175" } { "classname" "light" "origin" "704 2416 576" "light" "250" } { "light" "150" "origin" "728 2184 528" "classname" "light" } { "classname" "light" "origin" "512 2176 528" "light" "150" } { "classname" "light" "origin" "832 2336 656" "light" "175" } { "light" "175" "origin" "592 2336 656" "classname" "light" } { "classname" "light" "origin" "808 2584 576" "light" "150" } { "light" "150" "origin" "616 2576 576" "classname" "light" } { "classname" "light_flame_small_yellow" "origin" "488 2712 694" "light" "250" } { "classname" "light" "origin" "488 2624 608" "light" "175" } { "classname" "light" "origin" "480 2464 608" "light" "175" } { "light" "250" "origin" "184 2184 1038" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "512 2096 1038" "light" "250" } { "classname" "light" "origin" "224 2184 976" "light" "150" } { "classname" "light" "origin" "848 2024 992" "light" "200" } { "classname" "light" "origin" "256 1992 1000" "light" "150" } { "classname" "light" "origin" "272 2376 1000" "light" "200" } { "classname" "light" "origin" "1112 2208 1032" "light" "150" } { "light" "0" "origin" "698 2860 1228" "classname" "light_flame_large_yellow" } { "origin" "700 2808 1252" "classname" "light" } { "light" "250" "origin" "472 2632 1062" "classname" "light" } { "classname" "light" "origin" "952 2632 1062" "light" "250" } { "light" "150" "origin" "952 2424 894" "classname" "light" } { "classname" "light" "origin" "480 2424 894" "light" "150" } { "light" "150" "origin" "896 2296 966" "classname" "light" } { "classname" "light" "origin" "704 2304 966" "light" "150" } { "light" "150" "origin" "552 2304 966" "classname" "light" } { "light" "250" "origin" "704 2184 406" "classname" "light" } { "light" "150" "origin" "712 2000 406" "classname" "light" } { "light" "200" "origin" "504 2224 400" "classname" "light" } { "light" "200" "origin" "960 2576 400" "classname" "light" } { "light" "150" "origin" "960 2400 400" "classname" "light" } { "light" "150" "origin" "808 1112 592" "classname" "light" } { "classname" "light" "origin" "600 1112 592" "light" "150" } { "light" "175" "origin" "1016 128 936" "classname" "light" } { "classname" "light" "origin" "392 128 936" "light" "175" } { "light" "150" "origin" "848 -64 1304" "classname" "light" } { "classname" "light" "origin" "560 -64 1304" "light" "150" } { "light" "175" "origin" "1248 832 1496" "classname" "light" } { "light" "150" "origin" "1096 872 1496" "classname" "light" } { "light" "150" "origin" "896 2208 976" "classname" "light" } { "classname" "light" "origin" "1096 200 1512" "light" "350" } { "light" "350" "origin" "264 192 1512" "classname" "light" } { "light" "175" "origin" "488 448 1264" "classname" "light" } { "origin" "1048 728 1456" "classname" "light" "light" "200" } { "light" "125" "origin" "1328 928 1448" "classname" "light" } { "light" "225" "origin" "696 672 1320" "classname" "light" } { "origin" "816 -56 1640" "classname" "light" } { "classname" "light" "origin" "584 -56 1640" } { "light" "175" "origin" "880 96 1376" "classname" "light" } { "classname" "light" "origin" "528 96 1376" "light" "175" } { "light" "200" "origin" "960 344 1072" "classname" "light" } { "classname" "light" "origin" "1120 264 1072" "light" "200" } { "light" "175" "origin" "1208 96 1016" "classname" "light" } { "light" "175" "origin" "1024 360 968" "classname" "light" } { "classname" "light" "origin" "328 336 968" "light" "150" } { "classname" "light" "origin" "416 424 1072" "light" "200" } { "light" "200" "origin" "296 256 1072" "classname" "light" } { "light" "150" "origin" "704 48 1040" "classname" "light" } { "light" "175" "origin" "384 464 976" "classname" "light" } { "classname" "light" "origin" "224 264 976" "light" "150" } { "light" "150" "origin" "952 2192 416" "classname" "light" } { "classname" "light" "origin" "1040 -464 1016" "light" "150" } { "sounds" "2" "spawnflags" "1" "classname" "func_plat" "model" "*18" } { "light" "250" "origin" "1072 -272 1262" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "1024 -272 1200" "light" "150" } { "light" "200" "origin" "624 -240 1328" "classname" "light" } { "light" "175" "origin" "1080 -624 1168" "classname" "light" } { "origin" "456 -576 1230" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "504 -576 1168" "light" "175" } { "origin" "624 -448 924" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "624 -704 924" } { "light" "125" "origin" "664 -448 880" "classname" "light" } { "classname" "light" "origin" "624 -488 880" "light" "125" } { "light" "125" "origin" "584 -448 880" "classname" "light" } { "classname" "light" "origin" "624 -408 880" "light" "125" } { "light" "125" "origin" "624 -664 880" "classname" "light" } { "classname" "light" "origin" "664 -704 880" "light" "125" } { "light" "125" "origin" "624 -744 880" "classname" "light" } { "classname" "light" "origin" "584 -704 880" "light" "125" } { "light" "250" "origin" "296 -96 968" "classname" "light" } { "light" "250" "origin" "1112 -96 968" "classname" "light" } { "light" "175" "origin" "1056 -224 968" "classname" "light" } { "light" "500" "origin" "-264 2120 1504" "classname" "light" } { "spawnflags" "2064" "angle" "0" "classname" "func_door" "wait" "-1" "model" "*19" } { "sounds" "3" "classname" "func_door" "angle" "180" "spawnflags" "2064" "wait" "-1" "model" "*20" } { "light" "200" "origin" "704 32 952" "classname" "light" } { "target" "t101" "spawnflags" "256" "targetname" "t23" "angle" "90" "origin" "-248 1560 1224" "classname" "monster_wizard" } { "target" "t23" "classname" "trigger_once" "model" "*21" } { "origin" "-280 1560 1348" "classname" "item_armor2" } { "origin" "-488 2112 1220" "classname" "item_health" } { "classname" "item_health" "origin" "-488 2064 1220" } { "spawnflags" "1536" "origin" "-272 1784 1156" "classname" "item_shells" } { "spawnflags" "256" "target" "t25" "targetname" "t24" "origin" "888 1640 1028" "classname" "path_corner" } { "spawnflags" "256" "target" "t24" "targetname" "t25" "classname" "path_corner" "origin" "624 1264 1028" } { "spawnflags" "256" "target" "t24" "origin" "928 1672 1028" "classname" "monster_wizard" } { "spawnflags" "2304" "target" "t26" "classname" "trigger_once" "model" "*22" } { "target" "t27" "targetname" "t28" "origin" "568 2040 928" "classname" "path_corner" } { "target" "t28" "targetname" "t27" "classname" "path_corner" "origin" "368 2044 928" } { "target" "t27" "origin" "472 2040 944" "classname" "monster_ogre" "spawnflags" "1" } { "sounds" "2" "target" "t29" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*23" } { "sounds" "3" "angle" "180" "classname" "func_door" "model" "*24" } { "angle" "0" "classname" "func_door" "model" "*25" } { "light" "175" "origin" "1112 2520 964" "classname" "light" } { "origin" "104 1308 892" "classname" "item_health" } { "spawnflags" "2048" "origin" "704 1344 936" "classname" "item_key1" "sounds" "1" } { "target" "t34" "angle" "180" "origin" "920 2040 544" "classname" "monster_ogre" "spawnflags" "1" } { "target" "t35" "targetname" "t34" "origin" "864 2044 528" "classname" "path_corner" } { "target" "t37" "targetname" "t35" "classname" "path_corner" "origin" "704 2048 528" } { "target" "t34" "targetname" "t36" "origin" "704 2048 528" "classname" "path_corner" } { "target" "t36" "targetname" "t37" "classname" "path_corner" "origin" "704 1808 528" } { "targetname" "t38" "angle" "270" "origin" "456 2476 544" "classname" "monster_ogre" } { "target" "t38" "classname" "trigger_once" "model" "*26" } { "targetname" "t29" "angle" "0" "origin" "336 2272 952" "classname" "monster_knight" "spawnflags" "768" } { "targetname" "t39" "spawnflags" "1" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*27" } { "targetname" "t39" "angle" "270" "origin" "712 2540 448" "classname" "monster_ogre" } { "target" "t39" "classname" "trigger_once" "model" "*28" } { "classname" "light" "origin" "712 2544 440" "light" "200" } { "classname" "item_health" "origin" "1064 2184 920" "spawnflags" "1024" } { "spawnflags" "1" "origin" "1128 2184 920" "classname" "item_health" } { "classname" "item_spikes" "origin" "816 2840 920" } { "origin" "816 2800 920" "classname" "item_spikes" } { "spawnflags" "256" "classname" "monster_wizard" "origin" "1656 1496 968" "angle" "180" "target" "t41" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t40" "targetname" "t39" "model" "*29" } { "classname" "info_teleport_destination" "origin" "984 1496 1000" "angle" "180" "targetname" "t40" } { "spawnflags" "256" "classname" "path_corner" "origin" "912 1496 1000" "targetname" "t41" "target" "t42" } { "spawnflags" "256" "origin" "528 1368 1000" "classname" "path_corner" "targetname" "t42" "target" "t41" } { "classname" "item_health" "origin" "408 2640 520" } { "classname" "item_shells" "origin" "456 2672 520" "spawnflags" "1" } { "angle" "0" "origin" "80 864 968" "classname" "monster_wizard" "target" "t44" } { "targetname" "t119" "spawnflags" "2" "classname" "trigger_teleport" "target" "t45" "model" "*30" } { "classname" "info_teleport_destination" "origin" "432 856 952" "angle" "45" "targetname" "t45" } { "classname" "path_corner" "origin" "496 872 952" "target" "t43" "targetname" "t44" } { "origin" "872 1056 952" "classname" "path_corner" "targetname" "t43" "target" "t44" } { "classname" "trigger_once" "spawnflags" "1792" "target" "t39" "model" "*31" } { "spawnflags" "1024" "classname" "monster_knight" "origin" "1168 56 904" "angle" "135" "target" "t49" "targetname" "t67" } { "classname" "monster_ogre" "origin" "1800 224 920" "angle" "180" "target" "t116" "spawnflags" "256" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t49" "lip" "-24" "model" "*32" } { "wait" "-1" "angle" "-1" "classname" "func_door" "spawnflags" "1" "targetname" "t39" "lip" "-24" "model" "*33" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t29" "lip" "-24" "model" "*34" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t46" "model" "*35" } { "classname" "info_teleport_destination" "origin" "1104 232 880" "angle" "180" "targetname" "t46" } { "classname" "path_corner" "origin" "1064 256 880" "target" "t47" "targetname" "t48" "spawnflags" "256" } { "origin" "312 232 880" "classname" "path_corner" "targetname" "t47" "target" "t48" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "704 -40 1256" "angle" "90" "targetname" "t50" } { "classname" "trigger_once" "target" "t52" "model" "*36" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t50" "targetname" "t52" "model" "*37" } { "angle" "90" "origin" "570 -898 1300" "classname" "monster_wizard" "targetname" "t52" } { "classname" "item_shells" "origin" "216 120 880" "spawnflags" "1" } { "classname" "item_health" "origin" "192 232 880" } { "origin" "192 192 880" "classname" "item_health" "spawnflags" "1024" } { "classname" "item_shells" "origin" "-216 1464 888" } { "classname" "item_health" "origin" "816 1160 512" "spawnflags" "1024" } { "spawnflags" "1" "origin" "816 1120 512" "classname" "item_health" } { "classname" "monster_wizard" "origin" "944 840 956" "angle" "135" "target" "t53" "targetname" "t64" } { "classname" "trigger_once" "target" "t64" "model" "*38" } { "classname" "monster_knight" "origin" "704 392 1280" "angle" "270" "target" "t65" "spawnflags" "1" } { "classname" "path_corner" "origin" "704 208 1264" "targetname" "t65" "target" "t66" } { "origin" "704 496 1264" "classname" "path_corner" "targetname" "t66" "target" "t65" } { "classname" "trigger_once" "target" "t67" "model" "*39" } { "sounds" "1" "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t72" "model" "*40" } { "sounds" "1" "classname" "func_door" "wait" "-1" "angle" "-2" "targetname" "t72" "model" "*41" } { "classname" "trigger_once" "target" "t72" "model" "*42" } { "classname" "info_null" "origin" "852 -580 820" "targetname" "t73" } { "classname" "light" "origin" "856 -584 936" "light" "400" "target" "t73" } { "classname" "light" "origin" "920 -448 744" "light" "150" } { "light" "150" "origin" "760 -448 744" "classname" "light" } { "classname" "light" "origin" "552 -424 744" "light" "150" } { "light" "150" "origin" "560 -728 744" "classname" "light" } { "classname" "light" "origin" "776 -712 744" "light" "150" } { "light" "150" "origin" "936 -712 744" "classname" "light" } { "classname" "path_corner" "origin" "652 -576 952" "targetname" "t75" "target" "t74" } { "origin" "908 -576 952" "classname" "path_corner" "targetname" "t74" "target" "t75" } { "classname" "monster_ogre" "origin" "816 -260 952" "angle" "270" "targetname" "t72" } { "classname" "monster_ogre" "origin" "724 -260 952" "angle" "270" "targetname" "t72" "spawnflags" "256" } { "classname" "item_health" "origin" "632 -548 820" "spawnflags" "3072" } { "origin" "672 -548 820" "classname" "item_health" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t76" "model" "*43" } { "sounds" "1" "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t76" "model" "*44" } { "light" "150" "origin" "1040 -712 1016" "classname" "light" } { "origin" "1112 -576 942" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "1064 -576 896" "light" "150" } { "classname" "light" "origin" "888 -80 968" "light" "175" } { "light" "175" "origin" "512 -80 968" "classname" "light" } { "classname" "item_armor2" "origin" "1184 -96 920" } { "classname" "monster_ogre" "origin" "392 8 912" "angle" "315" "targetname" "t77" "spawnflags" "256" } { "classname" "trigger_once" "target" "t77" "model" "*45" } { "classname" "item_health" "origin" "336 -224 888" "spawnflags" "1" } { "classname" "item_spikes" "origin" "968 16 888" "spawnflags" "1" } { "classname" "item_health" "origin" "560 2808 516" "spawnflags" "1" } { "classname" "path_corner" "origin" "1056 -384 824" "targetname" "t78" "target" "t79" "spawnflags" "256" } { "origin" "1056 -736 824" "classname" "path_corner" "targetname" "t79" "target" "t78" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "1064 -656 840" "angle" "90" "target" "t78" "spawnflags" "257" } { "angle" "90" "origin" "848 -880 952" "classname" "monster_ogre" "targetname" "t72" } { "classname" "item_shells" "origin" "1160 16 1248" } { "classname" "item_health" "origin" "280 64 1248" } { "classname" "item_rockets" "origin" "648 -256 928" "spawnflags" "1025" } { "classname" "item_spikes" "origin" "648 -304 1248" } { "origin" "696 -304 1248" "classname" "item_spikes" } { "classname" "light_flame_small_yellow" "origin" "768 -352 1230" } { "target" "t83" "wait" ".8" "classname" "trigger_multiple" "model" "*46" } { "target" "t83" "classname" "trigger_multiple" "wait" ".8" "model" "*47" } { "target" "t83" "wait" ".8" "classname" "trigger_multiple" "model" "*48" } { "target" "t83" "classname" "trigger_multiple" "wait" ".8" "model" "*49" } { "target" "t83" "wait" ".8" "classname" "trigger_multiple" "model" "*50" } { "targetname" "t83" "classname" "trap_spikeshooter" "origin" "1108 -576 1140" "spawnflags" "1" "angle" "180" } { "targetname" "t83" "angle" "90" "spawnflags" "1" "origin" "768 -796 1140" "classname" "trap_spikeshooter" } { "origin" "1112 -576 1230" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "768 -800 1230" } { "classname" "light" "origin" "712 -756 1168" "light" "175" } { "light" "175" "origin" "768 -424 1168" "classname" "light" } { "light" "175" "origin" "888 -744 956" "classname" "light" } { "classname" "light" "origin" "888 -408 956" "light" "175" } { "origin" "384 -224 888" "classname" "item_shells" } { "origin" "584 1784 920" "classname" "item_health" } { "origin" "832 2064 920" "classname" "item_shells" } { "target" "t72" "classname" "trigger_once" "model" "*51" } { "target" "t85" "targetname" "t84" "origin" "1560 216 896" "classname" "path_corner" } { "target" "t48" "targetname" "t85" "classname" "path_corner" "origin" "1456 216 896" } { "origin" "704 1368 516" "classname" "weapon_supernailgun" } { "spawnflags" "1" "origin" "184 1928 920" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "656 1816 528" "spawnflags" "768" } { "classname" "item_shells" "origin" "1072 -800 820" "spawnflags" "1024" } { "classname" "monster_ogre" "origin" "840 -40 1276" "angle" "180" "targetname" "t86" "spawnflags" "768" } { "classname" "trigger_once" "target" "t86" "model" "*52" } { "classname" "light" "origin" "472 -576 876" "light" "150" } { "classname" "item_shells" "origin" "656 680 1256" "spawnflags" "1536" } { "angle" "270" "origin" "880 2224 536" "classname" "monster_knight" "spawnflags" "256" } { "angle" "180" "origin" "1112 2424 944" "classname" "monster_ogre" "spawnflags" "1281" } { "targetname" "t88" "target" "t87" "origin" "360 384 880" "classname" "path_corner" "spawnflags" "1280" } { "target" "t88" "targetname" "t87" "classname" "path_corner" "origin" "504 160 880" "spawnflags" "1280" } { "target" "t87" "angle" "315" "origin" "384 320 896" "classname" "monster_knight" "spawnflags" "1280" } { "spawnflags" "257" "targetname" "t86" "angle" "0" "origin" "376 120 1272" "classname" "monster_ogre" } { "origin" "776 1368 916" "classname" "item_shells" "spawnflags" "1024" } { "classname" "item_spikes" "origin" "184 1968 920" "spawnflags" "1" } { "classname" "monster_wizard" "origin" "312 936 944" "angle" "45" "spawnflags" "769" } { "classname" "monster_knight" "origin" "704 -80 908" "angle" "90" } { "angle" "0" "origin" "568 -56 1276" "classname" "monster_ogre" "targetname" "t86" "spawnflags" "768" } { "spawnflags" "1536" "targetname" "t90" "target" "t89" "origin" "720 1696 924" "classname" "path_corner" } { "spawnflags" "1536" "target" "t90" "targetname" "t89" "classname" "path_corner" "origin" "720 1416 924" } { "spawnflags" "1537" "target" "t90" "origin" "704 1784 948" "classname" "monster_ogre" } { "classname" "func_door_secret" "angle" "0" "spawnflags" "1" "targetname" "t91" "model" "*53" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t92" "model" "*54" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t92" "model" "*55" } { "classname" "func_button" "wait" "-1" "angle" "-2" "target" "t92" "model" "*56" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t92" "model" "*57" } { "classname" "func_button" "wait" "-1" "angle" "-2" "target" "t92" "model" "*58" } { "classname" "trigger_counter" "count" "5" "target" "t91" "targetname" "t92" "model" "*59" } { "classname" "light" "origin" "680 -920 1144" "light" "150" } { "classname" "item_spikes" "origin" "752 -876 928" "spawnflags" "1" } { "spawnflags" "3" "angle" "0" "classname" "func_door_secret" "targetname" "t91" "model" "*60" } { "light" "150" "origin" "680 -256 1144" "classname" "light" } { "classname" "trigger_once" "spawnflags" "1792" "target" "t72" "model" "*61" } { "classname" "trigger_secret" "sounds" "1" "targetname" "t8" "model" "*62" } { "angle" "270" "origin" "704 624 1280" "classname" "monster_knight" "spawnflags" "1" } { "angle" "225" "origin" "1016 -440 1128" "classname" "monster_knight" } { "angle" "180" "origin" "1024 -728 1128" "classname" "monster_knight" } { "spawnflags" "256" "angle" "180" "origin" "1008 -568 1128" "classname" "monster_knight" } { "spawnflags" "256" "classname" "monster_knight" "origin" "304 2312 952" "angle" "0" "targetname" "t29" } { "spawnflags" "1025" "classname" "monster_knight" "origin" "272 136 896" "angle" "45" } { "classname" "monster_wizard" "origin" "784 -576 960" "angle" "0" "target" "t74" "spawnflags" "1" } { "classname" "item_health" "origin" "732 -936 928" } { "origin" "772 -936 928" "classname" "item_health" } { "spawnflags" "256" "classname" "monster_knight" "origin" "704 -248 1272" "angle" "0" } { "classname" "path_corner" "origin" "1328 928 1396" "targetname" "t93" "target" "t94" "spawnflags" "512" } { "origin" "1176 928 1396" "classname" "path_corner" "target" "t93" "targetname" "t94" "spawnflags" "512" } { "classname" "monster_knight" "origin" "1192 884 1412" "angle" "0" "target" "t93" "spawnflags" "513" } { "classname" "monster_knight" "origin" "704 2376 944" "angle" "90" } { "classname" "monster_knight" "origin" "888 2312 944" "angle" "180" "targetname" "t95" } { "angle" "0" "origin" "512 2304 944" "classname" "monster_knight" "targetname" "t95" "spawnflags" "768" } { "classname" "trigger_once" "target" "t95" "model" "*63" } { "spawnflags" "256" "angle" "315" "origin" "728 2312 536" "classname" "monster_knight" } { "light" "200" "origin" "1296 1528 936" "classname" "light" } { "light" "250" "origin" "1432 1360 982" "classname" "light_flame_small_yellow" } { "light" "150" "origin" "1400 1360 920" "classname" "light" } { "light" "200" "origin" "1248 1344 680" "classname" "light" } { "lip" "-384" "wait" "-1" "angle" "90" "classname" "func_door" "targetname" "t98" "model" "*64" } { "light" "150" "origin" "1152 1328 584" "classname" "light" } { "origin" "1376 1480 864" "classname" "item_health" } { "sounds" "1" "classname" "trigger_secret" "model" "*65" } { "classname" "func_button" "sounds" "1" "angle" "0" "wait" "-1" "target" "t97" "model" "*66" } { "classname" "func_button" "wait" "-1" "angle" "0" "sounds" "1" "target" "t97" "model" "*67" } { "classname" "trigger_counter" "targetname" "t97" "target" "t98" "model" "*68" } { "classname" "light" "origin" "880 -888 968" "light" "150" } { "light" "150" "origin" "880 -264 968" "classname" "light" } { "angle" "180" "origin" "1112 2344 944" "classname" "monster_ogre" "spawnflags" "769" } { "angle" "270" "origin" "1120 880 1412" "classname" "monster_ogre" "spawnflags" "257" } { "map" "e1m8" "classname" "trigger_changelevel" "model" "*69" } { "light" "175" "origin" "824 -756 1168" "classname" "light" } { "classname" "light" "origin" "1080 -528 1168" "light" "175" } { "classname" "monster_wizard" "origin" "672 -392 1024" "angle" "315" "spawnflags" "257" } { "classname" "monster_knight" "origin" "1008 -656 1128" "angle" "180" "spawnflags" "768" } { "origin" "520 1064 440" "classname" "air_bubbles" } { "classname" "item_spikes" "origin" "16 1432 892" } { "classname" "trigger_once" "message" "A secret cave has opened..." "targetname" "t98" "model" "*70" } { "target" "t4" "health" "1" "wait" "-1" "angle" "0" "classname" "func_button" "model" "*71" } { "target" "t2" "health" "1" "wait" "-1" "angle" "180" "classname" "func_button" "model" "*72" } { "target" "t49" "spawnflags" "769" "angle" "135" "origin" "1208 128 904" "classname" "monster_demon1" } { "spawnflags" "769" "angle" "45" "origin" "288 160 896" "classname" "monster_demon1" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "692 -884 952" "angle" "90" } { "classname" "monster_ogre" "origin" "-312 1648 1372" "angle" "90" "targetname" "t23" "spawnflags" "768" } { "angle" "90" "origin" "-192 1648 1372" "classname" "monster_ogre" "targetname" "t23" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "704 1288 540" "angle" "270" "spawnflags" "768" } { "targetname" "t101" "target" "t106" "spawnflags" "770" "classname" "trigger_teleport" "model" "*73" } { "spawnflags" "768" "targetname" "t101" "angle" "270" "origin" "-256 2424 1288" "classname" "monster_wizard" } { "targetname" "t101" "origin" "-248 2440 1280" "classname" "trigger_relay" } { "targetname" "t29" "spawnflags" "256" "angle" "0" "origin" "144 2648 1024" "classname" "monster_wizard" } { "targetname" "t29" "spawnflags" "768" "classname" "monster_wizard" "origin" "144 2592 1024" "angle" "0" } { "targetname" "t29" "spawnflags" "768" "angle" "0" "origin" "144 2536 1024" "classname" "monster_wizard" } { "targetname" "t29" "target" "t102" "spawnflags" "258" "classname" "trigger_teleport" "model" "*74" } { "targetname" "t29" "target" "t103" "spawnflags" "770" "classname" "trigger_teleport" "model" "*75" } { "targetname" "t29" "target" "t104" "spawnflags" "770" "classname" "trigger_teleport" "model" "*76" } { "angle" "270" "targetname" "t102" "spawnflags" "256" "origin" "704 2656 1008" "classname" "info_teleport_destination" } { "angle" "270" "targetname" "t103" "spawnflags" "768" "classname" "info_teleport_destination" "origin" "920 2520 1008" } { "angle" "0" "targetname" "t104" "spawnflags" "768" "origin" "592 2192 1008" "classname" "info_teleport_destination" } { "sounds" "1" "classname" "func_door" "angle" "0" "wait" "-1" "speed" "150" "targetname" "t105" "model" "*77" } { "classname" "monster_demon1" "origin" "1056 -880 1128" "angle" "90" "spawnflags" "768" "targetname" "t105" } { "classname" "trigger_once" "spawnflags" "768" "target" "t105" "model" "*78" } { "classname" "light" "origin" "1056 -920 1184" "light" "125" } { "classname" "trigger_relay" "origin" "1104 -864 1120" "target" "t105" } { "classname" "monster_ogre" "origin" "1120 768 1416" "angle" "180" "spawnflags" "769" } { "classname" "air_bubbles" "origin" "884 1616 440" } { "targetname" "t106" "spawnflags" "768" "angle" "270" "origin" "-264 2232 1296" "classname" "info_teleport_destination" } { "classname" "path_corner" "origin" "568 1984 928" "targetname" "t107" "target" "t108" "spawnflags" "256" } { "origin" "424 1960 928" "classname" "path_corner" "target" "t107" "spawnflags" "256" "targetname" "t111" } { "classname" "path_corner" "origin" "704 2024 928" "targetname" "t108" "target" "t109" "spawnflags" "256" } { "origin" "712 1712 928" "classname" "path_corner" "targetname" "t109" "target" "t110" "spawnflags" "256" } { "classname" "path_corner" "origin" "712 1416 928" "targetname" "t110" "target" "t109" "spawnflags" "256" } { "classname" "func_door" "angle" "-2" "wait" "-1" "lip" "-24" "targetname" "t26" "spawnflags" "2304" "model" "*79" } { "classname" "monster_ogre" "origin" "240 2048 944" "angle" "0" "spawnflags" "257" "target" "t111" } { "target" "t23" "spawnflags" "1792" "classname" "trigger_once" "model" "*80" } { "classname" "monster_knight" "origin" "576 2768 536" "angle" "0" "spawnflags" "256" } { "spawnflags" "256" "angle" "180" "origin" "824 2776 536" "classname" "monster_knight" } { "classname" "monster_wizard" "origin" "704 -1032 1024" "angle" "90" "spawnflags" "256" "targetname" "t52" } { "angle" "90" "origin" "760 -1032 1024" "classname" "monster_wizard" "spawnflags" "768" "targetname" "t114" } { "classname" "monster_wizard" "origin" "816 -1032 1024" "angle" "90" "spawnflags" "768" "targetname" "t114" } { "targetname" "t52" "classname" "trigger_teleport" "spawnflags" "258" "target" "t112" "model" "*81" } { "classname" "trigger_teleport" "spawnflags" "770" "target" "t113" "targetname" "t114" "model" "*82" } { "targetname" "t114" "classname" "trigger_teleport" "spawnflags" "770" "target" "t115" "model" "*83" } { "classname" "info_teleport_destination" "origin" "896 224 1352" "angle" "135" "spawnflags" "256" "targetname" "t112" } { "classname" "info_teleport_destination" "origin" "488 1648 1016" "angle" "315" "spawnflags" "768" "targetname" "t113" } { "classname" "trigger_once" "spawnflags" "768" "target" "t114" "model" "*84" } { "classname" "info_teleport_destination" "origin" "800 904 928" "angle" "90" "spawnflags" "768" "targetname" "t115" } { "angle" "270" "origin" "-256 2232 1242" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "-256 2096 1218" "classname" "weapon_supershotgun" } { "angle" "270" "origin" "704 424 1266" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "704 2488 946" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "704 1968 546" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "704 104 898" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "704 1568 938" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "704 1344 912" "classname" "weapon_rocketlauncher" } { "angle" "0" "origin" "712 -576 840" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "944 -576 816" "classname" "weapon_nailgun" } { "angle" "180" "origin" "1064 -576 1128" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "696 584 1256" "classname" "weapon_grenadelauncher" } { "classname" "light" "origin" "316 804 780" "light" "150" } { "classname" "light" "origin" "316 804 644" "light" "75" } { "classname" "item_rockets" "origin" "298 710 706" "spawnflags" "1" } { "classname" "item_shells" "origin" "988 -928 1104" "spawnflags" "1" } { "classname" "item_health" "origin" "-56 2112 1220" "spawnflags" "3584" } { "classname" "item_health" "origin" "-56 2072 1220" "spawnflags" "2305" } { "spawnflags" "1" "origin" "584 2416 512" "classname" "item_spikes" } { "origin" "688 1392 516" "classname" "item_spikes" } { "classname" "item_artifact_invulnerability" "origin" "712 2312 948" "spawnflags" "1792" } { "origin" "32 1392 916" "classname" "item_artifact_envirosuit" } { "mangle" "26 310 0" "origin" "384 488 1552" "classname" "info_intermission" } { "light" "100" "origin" "800 1160 464" "classname" "light" } { "classname" "light" "origin" "608 1160 464" "light" "100" } { "light" "100" "origin" "604 1472 464" "classname" "light" } { "target" "t40" "classname" "trigger_teleport" "model" "*85" } { "mangle" "-20 75 0" "origin" "456 2144 568" "classname" "info_intermission" } { "mangle" "10 80 0" "origin" "464 1032 1000" "classname" "info_intermission" } { "mangle" "20 135 0" "origin" "1080 -752 1008" "classname" "info_intermission" } { "classname" "trigger_secret" "model" "*86" } { "classname" "path_corner" "origin" "1632 216 896" "targetname" "t116" "target" "t84" } { "classname" "item_spikes" "origin" "1200 48 872" "spawnflags" "1" } { "classname" "item_spikes" "origin" "928 2664 320" "spawnflags" "1" } //{ //"classname" "item_shells" //"origin" "1240 768 1384" //"spawnflags" "1" //} { "classname" "item_shells" "origin" "-88 2160 1224" "spawnflags" "2049" } { "classname" "info_player_coop" "origin" "-208 2272 1240" "angle" "270" } { "angle" "270" "origin" "-304 2272 1240" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-352 2272 1240" "angle" "270" } { "light" "200" "origin" "1288 1648 956" "classname" "light" } { "classname" "item_spikes" "origin" "-264 1464 888" } { "spawnflags" "1792" "origin" "1296 1488 888" "classname" "item_artifact_invisibility" } { "spawnflags" "1792" "classname" "func_wall" "model" "*87" } { "classname" "func_wall" "spawnflags" "1792" "model" "*88" } { "target" "t118" "targetname" "t117" "origin" "-176 1640 888" "classname" "path_corner" } { "targetname" "t118" "target" "t117" "classname" "path_corner" "origin" "-320 1640 888" } { "target" "t117" "origin" "-256 1632 904" "classname" "monster_knight" "spawnflags" "1" } { "origin" "1376 1424 864" "classname" "weapon_grenadelauncher" } { "spawnflags" "1" "targetname" "t120" "target" "t119" "classname" "trigger_counter" "model" "*89" } { "target" "t120" "targetname" "t53" "classname" "trigger_once" "model" "*90" } { "target" "t120" "targetname" "t39" "classname" "trigger_once" "model" "*91" } { "classname" "light" "origin" "480 2568 568" "light" "125" } { "origin" "162 1482 976" "classname" "ambient_drip" } { "origin" "786 1010 584" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "778 1210 584" } { "origin" "594 1202 584" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "602 1010 584" } { "origin" "786 1514 584" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "794 1698 584" } { "origin" "618 1690 584" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "618 1522 584" } { "origin" "698 1362 584" "classname" "ambient_drip" } { "origin" "714 1970 592" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "898 2170 592" } { "origin" "938 2346 592" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "682 2298 592" } { "origin" "458 2306 592" "classname" "ambient_drip" } { "origin" "458 1690 880" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "322 1506 880" } { "origin" "338 1226 880" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "466 1090 880" } { "origin" "394 882 880" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "674 810 880" } { "origin" "914 818 880" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "922 1034 880" } { "origin" "1082 1266 880" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "994 1442 880" } { "origin" "898 1714 880" "classname" "ambient_drip" } { "origin" "706 1362 1080" "classname" "ambient_drip" } { "origin" "1194 1522 1032" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1314 1354 1032" } { "origin" "442 354 920" "classname" "ambient_swamp1" } { "origin" "978 314 920" "classname" "ambient_swamp2" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "-416 2112 1220" "classname" "item_flag_team1" } { "angle" "270" "origin" "-284 2211 1242" "classname" "info_player_team1" } { "angle" "270" "origin" "-184 2211 1242" "classname" "info_player_team1" } { "angle" "270" "origin" "-284 2261 1242" "classname" "info_player_team1" } { "angle" "270" "origin" "-184 2261 1242" "classname" "info_player_team1" } { "angle" "270" "origin" "-284 2161 1242" "classname" "info_player_team1" } { "angle" "270" "origin" "-184 2161 1242" "classname" "info_player_team1" } // team2 { "origin" "1288 912 1484" "classname" "item_flag_team2" } { "angle" "270" "origin" "1210 870 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1160 870 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1210 870 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1160 820 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1210 820 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1160 920 1407" "classname" "info_player_team2" } { "angle" "270" "origin" "1210 920 1407" "classname" "info_player_team2" } // base one weapons upgrade //{ //"classname" "item_health" //"origin" "-488 2064 1220" //} //{ //"origin" "-488 2112 1220" //"classname" "item_health" //} { "classname" "item_health" "origin" "-488 2160 1220" } { "origin" "-72 2064 1220" "classname" "item_shells" } { "origin" "-120 2064 1220" "classname" "item_shells" } { "origin" "-168 2064 1220" "classname" "item_shells" } { "origin" "-72 2112 1220" "classname" "item_spikes" } { "origin" "-120 2112 1220" "classname" "item_spikes" } { "origin" "-168 2112 1220" "classname" "item_spikes" } { "origin" "-72 2160 1220" "classname" "weapon_supershotgun" } { "origin" "-120 2160 1220" "classname" "item_armor2" } { "origin" "-168 2160 1220" "classname" "weapon_supernailgun" } // base two weapons upgrade { "classname" "item_shells" "origin" "1240 768 1384" } { "classname" "item_shells" "origin" "1192 768 1384" } { "classname" "item_rockets" "origin" "1144 768 1384" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1240 816 1384" } { "classname" "item_spikes" "origin" "1192 816 1384" } { "classname" "item_spikes" "origin" "1144 816 1384" } { "origin" "1240 864 1384" "classname" "weapon_supershotgun" } { "classname" "item_armorInv" "origin" "1192 864 1384" } { "classname" "weapon_supernailgun" "origin" "1144 864 1384" } { "origin" "1240 912 1384" "classname" "item_health" } { "classname" "item_health" "origin" "1192 912 1384" } { "classname" "item_health" "origin" "1144 912 1384" } // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m5.ent000066400000000000000000001233351475442401000252020ustar00rootroot00000000000000{ "message" "Gloom Keep" "worldtype" "0" "sounds" "11" "wad" "gfx/medieval.wad" "classname" "worldspawn" } { "angle" "90" "origin" "-576 192 184" "classname" "info_player_start" } { "light" "400" "origin" "-710 442 360" "classname" "light_flame_large_yellow" } { "light" "400" "classname" "light_flame_large_yellow" "origin" "-444 442 360" } { "origin" "-584 736 216" "classname" "light" "light" "264" } { "classname" "light" "origin" "-584 720 470" "light" "364" } { "origin" "-212 440 244" "classname" "light" } { "origin" "164 492 282" "classname" "light" } { "origin" "-144 720 438" "classname" "light" } { "origin" "-224 944 686" "classname" "light" } { "origin" "0 280 452" "classname" "light" } { "light" "264" "origin" "-172 918 392" "classname" "light" } { "classname" "light" "origin" "-928 872 686" } { "origin" "-968 368 596" "classname" "light" } { "origin" "-980 534 192" "classname" "light" "light" "264" } { "classname" "light" "origin" "-740 788 216" "target" "t5" "light" "264" } { "classname" "light" "origin" "-768 272 368" "light" "264" } { "classname" "light" "origin" "-344 264 80" "light" "264" } { "classname" "light" "origin" "-72 888 148" "light" "264" } { "light" "264" "origin" "-56 1084 176" "classname" "light" } { "lip" "16" "angle" "-1" "classname" "func_door" "sounds" "3" "model" "*1" } { "origin" "-536 1120 208" "classname" "light" "light" "264" } { "light" "214" "classname" "light" "origin" "-560 1324 104" } { "light" "264" "classname" "light" "origin" "-312 1592 224" } { "light" "264" "origin" "-760 1592 224" "classname" "light" } { "light" "314" "classname" "light" "origin" "-544 1716 434" } { "classname" "func_plat" "targetname" "t2" "model" "*2" } { "classname" "func_button" "target" "t2" "angle" "270" "wait" "-1" "model" "*3" } { "classname" "light" "origin" "-544 1540 200" "light" "300" } { "classname" "light" "origin" "-544 1636 16" "light" "200" } { "classname" "light" "origin" "-320 1676 400" "light" "264" } { "classname" "light" "origin" "-768 1672 400" "light" "264" } { "classname" "light" "origin" "-544 1272 368" } { "classname" "light" "origin" "-264 1408 264" "light" "264" } { "light" "264" "origin" "-824 1408 264" "classname" "light" } { "origin" "-48 1392 256" "classname" "light" } { "light" "264" "origin" "-152 1592 256" "classname" "light" } { "light" "200" "origin" "-320 1312 72" "classname" "light" } { "light" "264" "origin" "-184 1336 72" "classname" "light" } { "light" "225" "origin" "120 1312 144" "classname" "light" } { "origin" "0 1856 56" "classname" "light" } { "classname" "trap_spikeshooter" "origin" "-1168 1564 174" "angle" "90" "targetname" "t4" } { "angle" "0" "origin" "-1088 1488 174" "classname" "trap_spikeshooter" "targetname" "t4" } { "classname" "trap_spikeshooter" "origin" "-1168 1414 174" "angle" "270" "targetname" "t4" } { "angle" "180" "origin" "-1244 1488 174" "classname" "trap_spikeshooter" "targetname" "t4" } { "classname" "light" "origin" "-1296 1536 190" "light" "175" } { "classname" "info_null" "origin" "-740 788 132" "targetname" "t5" } { "origin" "-828 948 132" "classname" "info_null" "targetname" "t6" } { "origin" "-644 1156 132" "classname" "info_null" "targetname" "t8" } { "origin" "-828 948 188" "classname" "light" "target" "t6" "light" "264" } { "origin" "-644 1156 180" "classname" "light" "target" "t8" "light" "264" } { "light" "100" "origin" "-738 758 280" "classname" "light" } { "origin" "208 1360 285" "classname" "light" } { "classname" "light" "origin" "208 1552 285" } { "origin" "208 1760 285" "classname" "light" } { "classname" "trap_spikeshooter" "origin" "-740 792 280" "spawnflags" "1" "angle" "-2" "targetname" "t9" } { "angle" "-2" "spawnflags" "1" "origin" "-828 948 280" "classname" "trap_spikeshooter" "targetname" "t10" } { "angle" "-2" "spawnflags" "1" "origin" "-644 1156 280" "classname" "trap_spikeshooter" "targetname" "t12" } { "classname" "trigger_multiple" "target" "t9" "model" "*4" } { "classname" "trigger_multiple" "target" "t10" "model" "*5" } { "classname" "trigger_multiple" "target" "t12" "model" "*6" } { "light" "300" "classname" "light_flame_small_yellow" "origin" "-984 1488 256" } { "origin" "-1168 1304 256" "classname" "light_flame_small_yellow" "light" "300" } { "origin" "-1536 1528 330" "classname" "light" } { "origin" "-1528 2208 314" "classname" "light" } { "classname" "light" "origin" "-1536 1760 298" } { "light" "264" "classname" "light" "origin" "-1536 2096 50" } { "light" "264" "origin" "-1248 2164 50" "classname" "light" } { "origin" "-1208 2176 290" "classname" "light" } { "sounds" "1" "target" "t31" "classname" "func_train" "model" "*7" } { "target" "t31" "targetname" "t14" "classname" "path_corner" "origin" "-1392 1904 158" } { "sounds" "1" "speed" "150" "target" "t15" "classname" "func_train" "model" "*8" } { "target" "t15" "targetname" "t16" "classname" "path_corner" "origin" "-1344 2256 158" } { "target" "t16" "targetname" "t15" "origin" "-1344 2112 158" "classname" "path_corner" } { "sounds" "1" "speed" "125" "target" "t17" "classname" "func_train" "model" "*9" } { "target" "t18" "targetname" "t17" "classname" "path_corner" "origin" "-1296 2048 158" } { "target" "t17" "targetname" "t18" "origin" "-1296 1962 158" "classname" "path_corner" } { "sounds" "1" "speed" "150" "target" "t19" "classname" "func_train" "model" "*10" } { "target" "t19" "targetname" "t20" "classname" "path_corner" "origin" "-1656 1880 158" } { "target" "t20" "targetname" "t19" "origin" "-1800 1880 158" "classname" "path_corner" } { "origin" "-1336 1920 168" "classname" "light_flame_small_yellow" "light" "250" } { "wait" ".75" "targetname" "t29" "spawnflags" "1" "angle" "270" "origin" "-1536 2134 54" "classname" "trap_spikeshooter" } { "wait" ".7" "target" "t29" "classname" "trigger_multiple" "model" "*11" } { "style" "2" "light" "250" "origin" "-1536 1320 54" "classname" "light" } { "target" "t30" "classname" "trigger_teleport" "model" "*12" } { "targetname" "t30" "angle" "90" "origin" "-1536 1460 138" "classname" "info_teleport_destination" } { "light" "364" "origin" "-1536 1552 298" "classname" "light" } { "origin" "-1536 2008 298" "classname" "light" } { "target" "t14" "targetname" "t31" "origin" "-1392 2048 158" "classname" "path_corner" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "-1656 1848 120" } { "wait" "-1" "targetname" "t32" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*13" } { "target" "t32" "wait" "-1" "angle" "-2" "classname" "func_button" "model" "*14" } { "classname" "light" "origin" "-1008 2176 330" } { "light" "350" "origin" "-748 2160 548" "classname" "light" } { "light" "264" "origin" "-744 2160 372" "classname" "light" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t35" "spawnflags" "4" "model" "*15" } { "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "4" "targetname" "t35" "sounds" "1" "model" "*16" } { "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "4" "targetname" "t35" "sounds" "1" "model" "*17" } { "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "4" "targetname" "t35" "model" "*18" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t35" "sounds" "0" "model" "*19" } { "classname" "func_door" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t35" "sounds" "1" "model" "*20" } { "classname" "func_door" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t35" "model" "*21" } { "classname" "func_door" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t35" "model" "*22" } { "classname" "func_door" "angle" "-2" "wait" "-1" "spawnflags" "4" "targetname" "t35" "sounds" "1" "model" "*23" } { "light" "350" "origin" "712 1688 368" "classname" "light" } { "classname" "light" "origin" "712 1536 368" "light" "350" } { "classname" "light" "origin" "480 1856 368" "light" "350" } { "light" "350" "origin" "520 1896 368" "classname" "light" } { "classname" "light" "origin" "904 1896 368" "light" "350" } { "light" "350" "origin" "944 1856 368" "classname" "light" } { "classname" "light" "origin" "928 1360 368" "light" "350" } { "light" "350" "origin" "888 1320 368" "classname" "light" } { "classname" "light" "origin" "520 1328 368" "light" "350" } { "light" "350" "origin" "480 1368 368" "classname" "light" } { "light" "125" "origin" "824 1548 -16" "classname" "light" } { "classname" "light" "origin" "792 1504 -16" "light" "125" } { "light" "125" "origin" "644 1504 -16" "classname" "light" } { "classname" "light" "origin" "600 1540 -16" "light" "125" } { "light" "125" "origin" "600 1672 -16" "classname" "light" } { "classname" "light" "origin" "636 1712 -16" "light" "125" } { "light" "125" "origin" "780 1712 -16" "classname" "light" } { "classname" "light" "origin" "824 1676 -16" "light" "125" } { "light" "214" "origin" "700 1676 12" "classname" "light" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "712 1256 112" } { "origin" "408 1616 112" "classname" "light_flame_small_yellow" "light" "364" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "368 2264 354" } { "origin" "1008 1616 112" "classname" "light_flame_small_yellow" "light" "364" } { "classname" "light" "origin" "-152 2216 432" "light" "250" } { "classname" "light" "origin" "-120 2544 560" "light" "350" } { "light" "300" "origin" "48 2544 560" "classname" "light" } { "classname" "light" "origin" "96 1952 304" "light" "314" } { "classname" "func_door" "angle" "-2" "lip" "-8" "targetname" "t35" "wait" "-1" "sounds" "1" "model" "*24" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "-216 1816 192" } { "classname" "light" "origin" "-512 2136 488" "light" "264" } { "light" "264" "origin" "-512 2296 488" "classname" "light" } { "classname" "light" "origin" "-560 2448 488" "light" "264" } { "light" "264" "origin" "-888 2472 488" "classname" "light" } { "classname" "light" "origin" "-960 2400 488" "light" "264" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "-744 2552 360" } { "origin" "-768 1736 424" "classname" "light_flame_small_yellow" "light" "364" } { "classname" "light" "origin" "-704 1952 374" "light" "150" } { "light" "150" "origin" "-824 1952 374" "classname" "light" } { "classname" "func_door" "spawnflags" "1" "dmg" "35" "speed" "250" "targetname" "t37" "angle" "-1" "lip" "24" "wait" "1" "sounds" "1" "model" "*25" } { "classname" "trigger_multiple" "target" "t37" "model" "*26" } { "light" "350" "origin" "-1076 1792 224" "classname" "light" "target" "t42" } { "origin" "-1056 1792 132" "classname" "info_null" "targetname" "t42" } { "classname" "light" "origin" "-1028 1792 248" "light" "264" } { "light" "264" "origin" "-804 1116 216" "classname" "light" "target" "t44" } { "origin" "-804 1116 132" "classname" "info_null" "targetname" "t44" } { "angle" "-2" "spawnflags" "1" "origin" "-804 1120 280" "classname" "trap_spikeshooter" "targetname" "t43" } { "classname" "trigger_multiple" "target" "t43" "model" "*27" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "-320 2016 328" } { "light" "314" "origin" "-988 872 380" "classname" "light" } //{ //"classname" "trigger_teleport" //"target" "t45" //"spawnflags" "1" //"model" "*28" //} //{ //"classname" "info_teleport_destination" //"origin" "-984 852 328" //"angle" "270" //"targetname" "t46" //} //{ //"classname" "info_teleport_destination" //"origin" "704 1520 4" //"angle" "90" //"targetname" "t45" //} //{ //"classname" "trigger_teleport" //"target" "t45" //"spawnflags" "1" //"model" "*29" //} //{ //"classname" "trigger_teleport" //"target" "t46" //"spawnflags" "1" //"model" "*30" //} { "origin" "256 1832 104" "classname" "light_flame_small_yellow" "light" "364" } { "light" "250" "origin" "-24 2216 432" "classname" "light" } { "classname" "light" "origin" "104 2216 432" "light" "250" } { "classname" "light" "origin" "-120 2544 384" "light" "214" } { "classname" "light" "origin" "-224 2208 320" "light" "214" } { "classname" "light" "origin" "432 2216 304" "light" "264" } { "light" "364" "classname" "light_flame_small_yellow" "origin" "-544 1936 472" } { "classname" "item_key2" "origin" "704 1688 48" "sounds" "1" "spawnflags" "2048" } { "classname" "func_door" "spawnflags" "2056" "angle" "180" "wait" "-1" "lip" "8" "model" "*31" } { "classname" "func_door" "angle" "-1" "targetname" "t47" "wait" "-1" "sounds" "1" "model" "*32" } { "spawnflags" "256" "classname" "trigger_once" "target" "t47" "model" "*33" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "-978 1918 152" "angle" "270" "targetname" "t47" } { "origin" "-56 1280 72" "classname" "light_flame_small_yellow" "light" "314" } { "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t35" "sounds" "1" "model" "*34" } { "classname" "monster_ogre" "origin" "138 1058 98" "angle" "90" "targetname" "t48" } { "classname" "trigger_once" "target" "t48" "model" "*35" } { "classname" "light" "origin" "-576 344 274" } { "classname" "light" "origin" "-24 1624 64" "light" "314" } { "classname" "trigger_once" "target" "t51" "model" "*36" } { "spawnflags" "256" "classname" "monster_knight" "origin" "-90 662 112" "angle" "270" "targetname" "t51" } { "classname" "path_corner" "origin" "-808 1168 136" "targetname" "t61" "target" "t62" } { "origin" "-728 1056 136" "classname" "path_corner" "targetname" "t62" "target" "t63" } { "classname" "path_corner" "origin" "-752 1056 136" "targetname" "t60" "target" "t61" } { "origin" "-784 864 136" "classname" "path_corner" "targetname" "t59" "target" "t60" } { "classname" "path_corner" "origin" "-784 888 136" "targetname" "t63" "target" "t58" } { "origin" "-776 704 136" "classname" "path_corner" "targetname" "t58" "target" "t59" } { "classname" "monster_knight" "origin" "-824 744 152" "target" "t58" "spawnflags" "1" } { "classname" "path_corner" "origin" "-768 1792 136" "targetname" "t64" "target" "t65" } { "origin" "-768 1536 136" "classname" "path_corner" "targetname" "t65" "target" "t66" } { "classname" "path_corner" "origin" "-624 1400 136" "targetname" "t66" "target" "t67" } { "origin" "-744 1536 136" "classname" "path_corner" "targetname" "t67" "target" "t64" } { "classname" "monster_knight" "origin" "-748 1608 152" "angle" "270" "target" "t64" } { "spawnflags" "256" "classname" "path_corner" "origin" "-288 1560 328" "targetname" "t69" "target" "t68" } { "spawnflags" "256" "origin" "-456 1560 328" "classname" "path_corner" "targetname" "t68" "target" "t69" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "-330 1614 344" "angle" "180" "target" "t68" } { "classname" "monster_knight" "origin" "-320 1912 216" "angle" "270" "targetname" "t70" } { "classname" "trigger_once" "target" "t70" "model" "*37" } { "spawnflags" "256" "classname" "path_corner" "origin" "-176 1952 248" "targetname" "t72" "target" "t71" } { "spawnflags" "256" "origin" "64 1952 248" "classname" "path_corner" "targetname" "t71" "target" "t72" } { "spawnflags" "257" "classname" "monster_knight" "origin" "24 1944 264" "angle" "180" "target" "t71" } { "classname" "monster_ogre" "origin" "-1162 1790 152" "angle" "0" "spawnflags" "1" } { "classname" "trigger_once" "target" "t77" "model" "*38" } { "classname" "monster_knight" "origin" "-936 2432 172" "angle" "270" "targetname" "t77" } { "spawnflags" "256" "classname" "monster_knight" "origin" "-776 2488 220" "angle" "180" "targetname" "t77" } { "spawnflags" "256" "classname" "monster_knight" "origin" "-1064 1352 164" "angle" "90" "targetname" "t4" } { "angle" "90" "origin" "-1320 1352 164" "classname" "monster_knight" "targetname" "t4" } { "classname" "monster_ogre" "origin" "-146 1794 116" "angle" "315" } { "classname" "monster_demon1" "origin" "-1198 2166 36" "angle" "180" "targetname" "t29" } { "spawnflags" "256" "angle" "90" "origin" "-1534 1622 36" "classname" "monster_demon1" "targetname" "t29" } { "classname" "path_corner" "origin" "-1616 2200 196" "targetname" "t78" "target" "t79" } { "origin" "-1624 1664 196" "classname" "path_corner" "targetname" "t79" "target" "t80" } { "classname" "path_corner" "origin" "-1464 1664 196" "targetname" "t80" "target" "t81" } { "origin" "-1464 2120 196" "classname" "path_corner" "targetname" "t81" "target" "t82" } { "classname" "path_corner" "origin" "-1152 2152 196" "target" "t78" "targetname" "t82" } { "classname" "monster_wizard" "origin" "-1112 2136 212" "target" "t82" "angle" "180" } { "classname" "path_corner" "origin" "136 1176 84" "targetname" "t84" "target" "t83" } { "origin" "-112 1176 84" "classname" "path_corner" "targetname" "t83" "target" "t84" } { "classname" "monster_knight" "origin" "56 1176 100" "angle" "180" "target" "t83" "spawnflags" "1" } { "classname" "item_armor2" "origin" "-164 1844 88" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "-42 1334 -24" "angle" "90" } { "classname" "path_corner" "origin" "-184 1568 -40" "targetname" "t85" "target" "t86" "spawnflags" "768" } { "origin" "-184 1320 -40" "classname" "path_corner" "targetname" "t86" "target" "t85" "spawnflags" "768" } { "classname" "monster_knight" "origin" "-176 1424 -24" "angle" "90" "target" "t85" "spawnflags" "768" } { "spawnflags" "256" "classname" "monster_knight" "origin" "-24 2000 264" "angle" "270" "targetname" "t70" } { "classname" "path_corner" "origin" "-768 2240 308" "targetname" "t90" "target" "t89" } { "origin" "-768 2080 308" "classname" "path_corner" "targetname" "t89" "target" "t90" } { "classname" "monster_ogre" "origin" "-770 2186 332" "angle" "270" "target" "t89" "spawnflags" "257" } { "spawnflags" "768" "target" "t144" "classname" "monster_shambler" "origin" "712 1900 20" "angle" "270" "targetname" "t35" } { "classname" "item_health" "origin" "632 1528 -4" } { "origin" "632 1568 -4" "classname" "item_health" } { "classname" "item_shells" "origin" "520 1328 -4" "spawnflags" "1024" } { "classname" "item_health" "origin" "896 1384 -4" "spawnflags" "1" } { "spawnflags" "256" "classname" "path_corner" "origin" "304 1840 4" "targetname" "t91" "target" "t92" } { "spawnflags" "256" "origin" "312 1632 4" "classname" "path_corner" "targetname" "t92" "target" "t91" } { "spawnflags" "256" "classname" "monster_knight" "origin" "312 1688 20" "angle" "90" "target" "t91" } { "spawnflags" "256" "classname" "monster_wizard" "origin" "-1536 2016 260" "angle" "270" "target" "t93" } { "spawnflags" "256" "classname" "path_corner" "origin" "-1536 2088 236" "targetname" "t94" "target" "t93" } { "spawnflags" "256" "origin" "-1536 1936 252" "classname" "path_corner" "targetname" "t93" "target" "t94" } { "spawnflags" "257" "classname" "monster_wizard" "origin" "-512 2168 404" "angle" "90" "target" "t95" } { "spawnflags" "256" "classname" "path_corner" "origin" "-512 2216 388" "targetname" "t95" "target" "t96" } { "spawnflags" "256" "origin" "-520 2400 388" "classname" "path_corner" "targetname" "t96" "target" "t97" } { "spawnflags" "256" "classname" "path_corner" "origin" "-640 2496 388" "targetname" "t97" "target" "t98" } { "spawnflags" "256" "origin" "-752 2496 388" "classname" "path_corner" "targetname" "t98" "target" "t99" } { "spawnflags" "256" "classname" "path_corner" "origin" "-640 2496 388" "targetname" "t99" "target" "t100" } { "spawnflags" "256" "origin" "-520 2400 388" "classname" "path_corner" "targetname" "t100" "target" "t95" } { "classname" "path_corner" "origin" "528 2136 252" "targetname" "t101" "target" "t102" } { "origin" "488 2400 252" "classname" "path_corner" "targetname" "t102" "target" "t103" } { "classname" "path_corner" "origin" "264 2376 252" "targetname" "t103" "target" "t104" } { "origin" "264 2128 252" "classname" "path_corner" "target" "t101" "targetname" "t104" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "334 2214 268" "angle" "315" "target" "t101" } { "classname" "monster_ogre" "origin" "382 2374 268" "angle" "225" "target" "t103" "spawnflags" "1" } { "spawnflags" "768" "targetname" "t114" "classname" "monster_wizard" "origin" "128 2552 492" "angle" "180" } { "classname" "monster_knight" "origin" "64 2304 268" "angle" "270" "target" "t105" "spawnflags" "1" } { "classname" "path_corner" "origin" "64 2424 252" "targetname" "t106" "target" "t105" } { "origin" "64 2096 252" "classname" "path_corner" "targetname" "t105" "target" "t106" } { "classname" "item_health" "origin" "-224 2080 244" "spawnflags" "1" } { "spawnflags" "1" "origin" "-224 2120 244" "classname" "item_health" } { "classname" "item_health" "origin" "-224 2160 244" "spawnflags" "1" } { "spawnflags" "769" "classname" "monster_knight" "origin" "-528 1136 152" "angle" "180" } { "classname" "path_corner" "origin" "-744 1576 -40" "targetname" "t110" "target" "t111" } { "origin" "-712 1352 -40" "classname" "path_corner" "targetname" "t111" "target" "t112" } { "classname" "path_corner" "origin" "-328 1296 -40" "targetname" "t112" "target" "t113" } { "origin" "-424 1480 -40" "classname" "path_corner" "target" "t110" "targetname" "t113" } { "spawnflags" "256" "classname" "monster_demon1" "origin" "-432 1360 -24" "angle" "0" "target" "t112" } { "classname" "weapon_grenadelauncher" "origin" "-112 1656 -48" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-1304 1360 144" "spawnflags" "1792" } { "classname" "item_health" "origin" "-1656 1520 132" } { "origin" "-1656 1472 132" "classname" "item_health" } { "classname" "item_health" "origin" "-1216 1912 12" } { "origin" "-1272 1912 12" "classname" "item_health" } { "classname" "item_health" "origin" "-944 2056 132" "spawnflags" "1" } { "classname" "item_shells" "origin" "-1120 1776 132" } { "classname" "item_shells" "origin" "-136 1200 76" } { "classname" "item_health" "origin" "112 1824 -44" } { "origin" "72 1824 -44" "classname" "item_health" } { "classname" "item_shells" "origin" "-808 1640 132" } { "classname" "item_health" "origin" "-808 1592 132" "spawnflags" "2049" } { "classname" "item_spikes" "origin" "-296 1648 -44" } { "classname" "item_rockets" "origin" "-488 2120 288" } { "classname" "item_health" "origin" "324 1760 -4" "spawnflags" "2304" } { "spawnflags" "2304" "origin" "324 1720 -4" "classname" "item_health" } { "classname" "item_shells" "origin" "240 1608 -4" } { "classname" "item_shells" "origin" "-824 668 132" "spawnflags" "1" } { "classname" "item_health" "origin" "-1224 1328 144" } { "origin" "-1144 1328 144" "classname" "item_health" } { "classname" "item_health" "origin" "-800 1240 -44" "spawnflags" "1" } { "spawnflags" "1" "origin" "-800 1284 -44" "classname" "item_health" } { "classname" "item_health" "origin" "-808 1648 324" "spawnflags" "2048" } { "classname" "item_shells" "origin" "-808 1608 324" "spawnflags" "1" } { "classname" "item_shells" "origin" "-1064 568 92" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-120 1280 -44" "spawnflags" "2048" } { "spawnflags" "1" "origin" "68 1000 72" "classname" "item_health" } { "spawnflags" "768" "target" "t114" "classname" "trigger_once" "model" "*39" } { "classname" "light" "origin" "48 720 8" "light" "214" } { "classname" "light" "origin" "-544 1880 -196" "light" "264" } { "classname" "info_teleport_destination" "origin" "-545 1825 344" //Q-Man "angle" "270" "targetname" "t115" } { "classname" "func_plat" "model" "*40" } { "light" "250" "classname" "light_flame_small_yellow" "origin" "-1096 1920 168" } { "angle" "270" "target" "t116" "origin" "-72 856 112" "classname" "monster_knight" "spawnflags" "1" } { "target" "t117" "targetname" "t116" "origin" "-72 824 96" "classname" "path_corner" } { "target" "t116" "targetname" "t117" "classname" "path_corner" "origin" "-72 720 96" } { "angle" "90" "origin" "-576 376 176" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-1212 1792 152" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-1532 1600 152" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-676 2156 324" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "-212 2312 264" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-352 1996 220" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "776 1568 20" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-40 1836 -24" "classname" "info_player_deathmatch" } { "angle" "90" "spawnflags" "1792" "origin" "-820 2160 300" "classname" "weapon_supershotgun" } { "angle" "45" "origin" "-780 1348 -24" "classname" "info_player_deathmatch" } { "targetname" "t4" "angle" "90" "origin" "-1168 1336 164" "classname" "monster_knight" "spawnflags" "256" } { "targetname" "t70" "spawnflags" "769" "angle" "0" "origin" "-978 1790 152" "classname" "monster_ogre" } { "spawnflags" "768" "target" "t118" "angle" "270" "origin" "-1528 1832 152" "classname" "monster_knight" } { "spawnflags" "768" "target" "t119" "targetname" "t118" "origin" "-1528 1800 136" "classname" "path_corner" } { "spawnflags" "768" "target" "t118" "targetname" "t119" "classname" "path_corner" "origin" "-1528 1680 136" } { "light" "200" "origin" "-544 1248 80" "classname" "light" } { "origin" "-544 1080 72" "classname" "light_flame_small_yellow" "light" "200" } { "light" "150" "origin" "-544 1088 0" "classname" "light" } { "light" "200" "origin" "-336 1608 72" "classname" "light" } { "classname" "light" "origin" "-728 1560 40" "light" "200" } { "light" "200" "origin" "-744 1296 80" "classname" "light" } { "light" "150" "origin" "-320 1984 256" "classname" "light" } { "classname" "light" "origin" "-712 1920 -208" "light" "150" } { "wait" ".5" "target" "t4" "classname" "trigger_multiple" "model" "*41" } { "light" "175" "origin" "-768 1792 312" "classname" "light" } { "classname" "light" "origin" "-584 192 336" "light" "200" } { "spawnflags" "256" "classname" "monster_knight" "origin" "-464 776 152" "angle" "225" "targetname" "t51" } { "classname" "light" "origin" "-576 584 336" "light" "200" } { "classname" "light" "origin" "-72 552 240" "light" "250" } { "classname" "light" "origin" "-584 264 56" "light" "200" } { "classname" "light" "origin" "-968 400 8" "light" "200" } { "light" "200" "origin" "-760 288 8" "classname" "light" } { "classname" "light" "origin" "-216 336 8" "light" "200" } { "classname" "light" "origin" "-504 288 8" "light" "200" } { "classname" "light" "origin" "32 416 8" "light" "200" } { "classname" "light" "origin" "-448 544 184" "light" "170" } { "light" "170" "origin" "-704 544 184" "classname" "light" } { "classname" "light" "origin" "120 1152 144" "light" "175" } { "light" "150" "origin" "120 1032 144" "classname" "light" } { "classname" "light" "origin" "-192 1816 144" "light" "175" } { "classname" "light" "origin" "-56 1304 40" "light" "150" } { "classname" "light" "origin" "-336 552 144" "light" "150" } { "light" "150" "origin" "-808 552 144" "classname" "light" } { "classname" "light" "origin" "72 312 144" } { "classname" "light" "origin" "-168 1824 8" "light" "150" } { "classname" "light" "origin" "-816 688 240" "light" "160" } { "light" "160" "origin" "-824 856 240" "classname" "light" } { "classname" "light" "origin" "-728 960 240" "light" "160" } { "light" "160" "origin" "-832 1160 240" "classname" "light" } { "classname" "light" "origin" "712 1288 88" "light" "165" } { "light" "165" "origin" "976 1616 88" "classname" "light" } { "classname" "light" "origin" "440 1616 88" "light" "165" } { "light" "165" "origin" "624 1880 88" "classname" "light" } { "classname" "light" "origin" "792 1880 88" "light" "165" } { "classname" "func_door" "angle" "0" "wait" "-1" "sounds" "3" "model" "*42" } { "classname" "func_door" "angle" "180" "targetname" "t126" "wait" "-1" "model" "*43" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t126" "model" "*44" } { "classname" "light" "origin" "-1624 2264 192" "light" "150" } { "light" "175" "origin" "-1464 2264 192" "classname" "light" } { "classname" "item_health" "origin" "-384 1840 -256" "spawnflags" "1" } { "classname" "light" "origin" "-544 1904 400" "light" "160" } { "lip" "8" "wait" "-1" "angle" "0" "spawnflags" "2056" "classname" "func_door" "sounds" "3" "model" "*45" } { "light" "150" "origin" "56 592 -16" "classname" "light" } { "light" "150" "origin" "112 1552 64" "classname" "light" } { "light" "150" "origin" "-728 1816 200" "classname" "light" } { "origin" "336 2264 240" "classname" "weapon_supernailgun" } { "origin" "-776 1912 328" "classname" "item_key1" "sounds" "1" "spawnflags" "2048" } { "light" "150" "origin" "912 1400 72" "classname" "light" } { "classname" "light" "origin" "512 1800 72" "light" "150" } { "light" "150" "origin" "896 1784 72" "classname" "light" } { "light" "160" "origin" "296 1832 72" "classname" "light" } { "light" "150" "origin" "-960 1928 208" "classname" "light" } { "classname" "light" "origin" "-1272 2264 192" "light" "175" } { "light" "175" "origin" "-1096 2256 192" "classname" "light" } { "classname" "light" "origin" "-928 2264 192" "light" "175" } { "classname" "light" "origin" "-936 2088 192" "light" "175" } { "light" "175" "origin" "-1216 2080 192" "classname" "light" } { "classname" "light" "origin" "-1640 2136 192" "light" "175" } { "light" "175" "origin" "-1640 1440 192" "classname" "light" } { "classname" "light" "origin" "-1464 1440 192" "light" "175" } { "light" "200" "origin" "-1320 1896 120" "classname" "light" } { "light" "150" "origin" "-1384 1792 120" "classname" "light" } { "light" "200" "origin" "-992 2376 192" "classname" "light" } { "light" "150" "origin" "-744 2520 272" "classname" "light" } { "spawnflags" "1" "origin" "-944 2160 132" "classname" "item_spikes" } { "light" "150" "origin" "-1624 1848 64" "classname" "light" } { "light" "175" "origin" "-1624 2264 64" "classname" "light" } { "light" "150" "origin" "-1448 1632 64" "classname" "light" } { "light" "200" "origin" "-512 2184 422" "classname" "light" } { "origin" "224 2408 244" "classname" "item_health" "spawnflags" "2048" } { "origin" "-824 2232 300" "classname" "item_health" } { "spawnflags" "1" "origin" "-776 2232 300" "classname" "item_spikes" } { "spawnflags" "3584" "origin" "432 1256 -4" "classname" "item_health" } { "classname" "item_health" "origin" "968 1944 -4" "spawnflags" "3584" } { "classname" "weapon_rocketlauncher" "origin" "-544 1368 128" } { "classname" "item_health" "origin" "-528 1088 132" "spawnflags" "3584" } { "light" "150" "origin" "40 888 96" "classname" "light" } { "classname" "light" "origin" "-1120 1920 96" "light" "150" } { "light" "200" "origin" "-1120 1624 189" "classname" "light" } { "classname" "light" "origin" "-1232 1628 191" "light" "200" } { "light" "175" "origin" "-1296 1436 190" "classname" "light" } { "light" "100" "origin" "-1274 1490 154" "classname" "light" } { "classname" "light" "origin" "-1170 1382 154" "light" "100" } { "light" "100" "origin" "-1062 1492 154" "classname" "light" } { "classname" "light" "origin" "-1168 1594 154" "light" "100" } { "light" "75" "origin" "-1058 1508 176" "classname" "light" } { "light" "75" "origin" "-1170 1378 184" "classname" "light" } { "light" "100" "origin" "-1168 1324 202" "classname" "light" } { "classname" "light" "origin" "-1058 1464 176" "light" "75" } { "classname" "light" "origin" "-738 822 280" "light" "100" } { "light" "100" "origin" "-826 976 280" "classname" "light" } { "classname" "light" "origin" "-826 914 280" "light" "100" } { "classname" "light" "origin" "-804 1150 280" "light" "100" } { "light" "100" "origin" "-802 1086 280" "classname" "light" } { "classname" "light" "origin" "-674 1156 280" "light" "100" } { "light" "100" "origin" "-612 1156 280" "classname" "light" } { "classname" "light" "origin" "-744 960 164" "light" "100" } { "style" "2" "classname" "light" "origin" "404 2560 452" "light" "200" } { "light" "175" "origin" "344 2264 304" "classname" "light" } { "light" "150" "origin" "96 2352 304" "classname" "light" } { "targetname" "t128" "angle" "90" "classname" "func_door_secret" "model" "*46" } { "target" "t128" "wait" "3" "angle" "-2" "classname" "func_button" "model" "*47" } { "lip" "6" "target" "t128" "angle" "-1" "classname" "func_button" "model" "*48" } { "light" "200" "origin" "626 2378 316" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "626 2182 316" "light" "200" } { "light" "500" "origin" "296 2548 772" "classname" "light" } { "style" "2" "light" "300" "origin" "-544 2040 -198" "classname" "light" } { "light" "175" "origin" "-432 2040 -198" "classname" "light" } { "classname" "light" "origin" "-664 2048 -198" "light" "175" } { "target" "t115" "classname" "trigger_teleport" "model" "*49" } { "light" "200" "origin" "-544 1716 -216" "classname" "light" "style" "2" } { "angle" "180" "classname" "func_door_secret" "model" "*50" } { "classname" "trigger_secret" "model" "*51" } { "classname" "trigger_secret" "model" "*52" } { "classname" "monster_demon1" "origin" "-640 1496 -24" "angle" "180" "target" "t110" "spawnflags" "1" } { "classname" "monster_knight" "origin" "256 2552 424" "angle" "180" "targetname" "t114" } { "classname" "monster_knight" "origin" "368 2640 424" "angle" "180" "spawnflags" "256" } { "spawnflags" "256" "angle" "180" "origin" "368 2456 424" "classname" "monster_knight" } { "wait" "-1" "spawnflags" "2064" "angle" "0" "classname" "func_door" "model" "*53" } { "wait" "-1" "sounds" "3" "spawnflags" "2064" "angle" "180" "classname" "func_door" "model" "*54" } { "map" "e1m6" "classname" "trigger_changelevel" "model" "*55" } { "origin" "-464 176 152" "classname" "item_health" } { "origin" "-496 216 152" "classname" "item_health" } { "targetname" "t126" "angle" "90" "origin" "-768 1960 332" "classname" "monster_knight" } { "classname" "item_spikes" "origin" "424 2248 244" "spawnflags" "1" } { "classname" "trigger_teleport" "spawnflags" "770" "target" "t129" "targetname" "t51" "model" "*56" } { "targetname" "t51" "spawnflags" "770" "classname" "trigger_teleport" "target" "t130" "model" "*57" } { "classname" "monster_wizard" "origin" "-512 -40 184" "angle" "90" "spawnflags" "768" "targetname" "t51" } { "spawnflags" "768" "angle" "90" "origin" "-600 -40 184" "classname" "monster_wizard" "targetname" "t51" } { "classname" "info_teleport_destination" "origin" "-272 288 400" "angle" "135" "spawnflags" "768" "targetname" "t129" } { "spawnflags" "768" "angle" "45" "origin" "-792 296 400" "classname" "info_teleport_destination" "targetname" "t130" } { "targetname" "t131" "target" "t133" "spawnflags" "770" "classname" "trigger_teleport" "model" "*58" } { "targetname" "t131" "classname" "trigger_teleport" "spawnflags" "258" "target" "t132" "model" "*59" } { "targetname" "t131" "spawnflags" "768" "angle" "180" "origin" "368 848 384" "classname" "monster_wizard" } { "targetname" "t131" "classname" "monster_wizard" "origin" "368 760 384" "angle" "180" "spawnflags" "256" } { "target" "t131" "spawnflags" "256" "classname" "trigger_once" "model" "*60" } { "targetname" "t132" "spawnflags" "256" "angle" "180" "origin" "-224 696 552" "classname" "info_teleport_destination" } { "targetname" "t133" "spawnflags" "768" "angle" "45" "origin" "-888 448 360" "classname" "info_teleport_destination" } { "targetname" "t134" "lip" "4" "speed" "150" "wait" "-1" "angle" "-1" "classname" "func_door" "sounds" "1" "model" "*61" } { "targetname" "t134" "spawnflags" "768" "angle" "0" "origin" "-288 2544 424" "classname" "monster_ogre" } { "target" "t134" "spawnflags" "768" "classname" "trigger_once" "model" "*62" } { "spawnflags" "1024" "target" "t134" "origin" "-328 2480 416" "classname" "trigger_relay" } { "light" "150" "origin" "-320 2552 528" "classname" "light" } { "spawnflags" "768" "angle" "90" "origin" "712 1328 16" "classname" "monster_ogre" } { "classname" "monster_demon1" "origin" "-1448 2168 24" "spawnflags" "768" "angle" "0" } { "classname" "monster_knight" "origin" "-512 2216 312" "angle" "90" "spawnflags" "769" } { "classname" "item_shells" "origin" "-944 2120 128" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "-48 2104 264" "angle" "0" "spawnflags" "769" "targetname" "t135" } { "classname" "trigger_once" "spawnflags" "768" "target" "t135" "model" "*63" } { "classname" "trigger_once" "spawnflags" "768" "target" "t137" "model" "*64" } { "targetname" "t137" "classname" "trigger_teleport" "spawnflags" "770" "target" "t138" "model" "*65" } { "spawnflags" "770" "classname" "trigger_teleport" "target" "t136" "targetname" "t137" "model" "*66" } { "classname" "monster_wizard" "origin" "88 -64 152" "angle" "90" "spawnflags" "768" "targetname" "t137" } { "spawnflags" "768" "angle" "90" "origin" "0 -64 152" "classname" "monster_wizard" "targetname" "t137" } { "classname" "info_teleport_destination" "origin" "-96 1456 168" "angle" "90" "spawnflags" "768" "targetname" "t136" } { "classname" "info_teleport_destination" "origin" "104 1624 232" "angle" "135" "spawnflags" "768" "targetname" "t138" } { "spawnflags" "1" "origin" "-220 1828 88" "classname" "item_shells" } { "spawnflags" "256" "targetname" "t140" "target" "t139" "origin" "-800 784 328" "classname" "path_corner" } { "spawnflags" "256" "target" "t140" "targetname" "t139" "classname" "path_corner" "origin" "-296 784 328" } { "target" "t139" "spawnflags" "257" "angle" "0" "origin" "-528 784 344" "classname" "monster_demon1" } { "spawnflags" "769" "angle" "270" "origin" "-224 896 344" "classname" "monster_knight" } { "spawnflags" "3584" "origin" "256 1944 -4" "classname" "item_health" } { "classname" "item_health" "origin" "256 1904 -4" "spawnflags" "3584" } { "targetname" "t144" "target" "t143" "spawnflags" "770" "classname" "trigger_teleport" "model" "*67" } { "targetname" "t144" "target" "t141" "classname" "trigger_teleport" "spawnflags" "770" "model" "*68" } { "targetname" "t144" "target" "t142" "spawnflags" "770" "classname" "trigger_teleport" "model" "*69" } { "targetname" "t144" "spawnflags" "768" "angle" "90" "origin" "596 1096 32" "classname" "monster_demon1" } { "targetname" "t144" "spawnflags" "768" "classname" "monster_demon1" "origin" "696 1096 32" "angle" "90" } { "targetname" "t144" "spawnflags" "768" "angle" "90" "origin" "792 1096 32" "classname" "monster_demon1" } { "targetname" "t141" "spawnflags" "768" "angle" "90" "origin" "712 1376 0" "classname" "info_teleport_destination" } { "targetname" "t142" "spawnflags" "768" "angle" "180" "origin" "936 1576 0" "classname" "info_teleport_destination" } { "targetname" "t143" "spawnflags" "768" "angle" "0" "origin" "496 1672 0" "classname" "info_teleport_destination" } { "classname" "item_spikes" "origin" "896 1296 12" "spawnflags" "3585" } { "spawnflags" "2049" "origin" "944 1296 12" "classname" "item_spikes" } { "targetname" "t35" "angle" "270" "spawnflags" "3072" "origin" "712 1908 24" "classname" "monster_shambler" } { "classname" "item_armorInv" //Q-Man "origin" "-1536 2080 128" "spawnflags" "1792" } { "light" "200" "origin" "-150 32 108" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "-184 160 -16" "classname" "light" } { "classname" "trigger_secret" "model" "*70" } { "spawnflags" "2" "origin" "-200 56 56" "classname" "item_health" } { "classname" "monster_ogre" "origin" "-416 1896 -240" "angle" "180" "spawnflags" "768" } { "angle" "0" "origin" "-672 1888 -240" "classname" "monster_ogre" "spawnflags" "768" } { "classname" "item_shells" "origin" "-1248 2256 0" "spawnflags" "1" } { "classname" "item_shells" "origin" "-680 784 320" "spawnflags" "768" } { "classname" "item_spikes" "origin" "-640 784 320" "spawnflags" "768" } { "classname" "item_shells" "origin" "480 1328 -4" "spawnflags" "2817" } { "classname" "item_rockets" "origin" "280 2664 404" "spawnflags" "2048" } { "classname" "item_spikes" "origin" "-136 56 56" "spawnflags" "1" } { "spawnflags" "3584" "origin" "920 1944 -4" "classname" "item_health" } { "classname" "item_health" "origin" "872 1944 -4" "spawnflags" "3584" } { "spawnflags" "2048" "origin" "416 1808 12" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "416 1760 12" "spawnflags" "2048" } { "classname" "item_health" "origin" "-560 1732 -240" "spawnflags" "2" //Q-Man } { "spawnflags" "2816" "origin" "-808 1608 -48" "classname" "item_shells" } { "origin" "-224 936 344" "classname" "item_artifact_super_damage" } { "classname" "info_intermission" "origin" "64 264 592" "mangle" "24 130 0" } { "classname" "item_armor2" "origin" "624 2216 248" } { "classname" "trigger_teleport" "target" "t115" "model" "*71" } { "mangle" "20 135 0" "origin" "-296 1264 416" "classname" "info_intermission" } { "mangle" "20 225 0" "origin" "128 1832 248" "classname" "info_intermission" } { "mangle" "15 90 0" "origin" "-1536 1432 200" "classname" "info_intermission" } { "classname" "trigger_secret" "model" "*72" } { "classname" "item_health" "origin" "-936 1904 128" "spawnflags" "1" } { "classname" "func_wall" "spawnflags" "1792" "model" "*73" } { "classname" "item_shells" "origin" "-296 1600 -48" "spawnflags" "2048" } { "origin" "-560 1424 128" "classname" "item_rockets" } { "origin" "-488 712 128" "classname" "item_health" } { "spawnflags" "2049" "origin" "-808 1548 132" "classname" "item_health" } { "classname" "info_player_coop" "origin" "-528 192 176" "angle" "90" } { "angle" "90" "origin" "-624 192 176" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-680 192 176" "angle" "90" } { "classname" "trigger_secret" "model" "*74" } { "classname" "ambient_drip" "origin" "-158 98 120" } { "origin" "-918 386 120" "classname" "ambient_swamp2" } { "classname" "ambient_swamp2" "origin" "50 650 120" } { "origin" "10 362 120" "classname" "ambient_swamp1" } { "classname" "ambient_swamp1" "origin" "-486 322 120" } //Q-Man { "classname" "item_flag_team1" "origin" "704 1616 20" } { "classname" "info_player_team1" "origin" "706 1681 20" } { "classname" "info_player_team1" "origin" "704 1528 20" "angle" "90" } { "classname" "info_player_team1" "origin" "500 1811 16" } { "classname" "info_player_team1" "origin" "533 1421 16" } { "classname" "info_player_team1" "origin" "297 1834 16" } { "classname" "info_player_team1" "origin" "121 1620 16" "angle" "180" } { "classname" "item_flag_team2" "origin" "313 2543 424" } { "classname" "info_player_team2" "origin" "339 2455 424" } { "classname" "info_player_team2" "origin" "339 2643 424" } { "classname" "info_player_team2" "origin" "141 2561 424" } { "classname" "info_player_team2" "origin" "-127 2551 344" } { "classname" "info_player_team2" "origin" "-42 2214 264" } { "classname" "info_player_team2" "origin" "189 2263 264" } { "classname" "item_rockets" "origin" "-662 236 171" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "881 1769 16" } { "classname" "weapon_supernailgun" "origin" "704 1872 16" } { "classname" "item_spikes" "origin" "704 1920 16" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "-264 2547 424" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m6.ent000066400000000000000000001136661475442401000252110ustar00rootroot00000000000000{ "worldtype" "1" "wad" "gfx/metal.wad" "classname" "worldspawn" "sounds" "4" "message" "The Door To Chthon" } { "classname" "func_plat" "model" "*1" } { "classname" "light" "origin" "-64 896 456" "light" "400" } { "classname" "light" "origin" "-64 512 456" "light" "400" } { "classname" "light_flame_small_white" "origin" "370 802 18" } { "origin" "370 610 18" "classname" "light_flame_small_white" } { "classname" "light_flame_small_white" "origin" "50 898 18" } { "origin" "50 722 18" "classname" "light_flame_small_white" } { "wait" "-1" "classname" "func_door" "angle" "90" "spawnflags" "2056" "sounds" "4" "model" "*2" } { "wait" "-1" "classname" "func_door" "angle" "270" "spawnflags" "2056" "model" "*3" } { "classname" "light" "origin" "520 904 272" "light" "400" } { "classname" "light" "origin" "520 504 272" "light" "400" } { "classname" "light" "origin" "472 824 480" } { "classname" "light" "origin" "472 632 480" } { "classname" "light" "origin" "320 872 480" "light" "400" } { "classname" "light" "origin" "320 536 480" "light" "400" } { "classname" "light" "origin" "168 568 304" "light" "200" } { "classname" "light" "origin" "168 840 304" "light" "200" } { "classname" "light" "origin" "224 320 8" "light" "250" } { "target" "t98" "spawnflags" "2048" "classname" "item_key2" "origin" "224 120 56" "sounds" "2" } { "classname" "func_door" "angle" "90" "wait" "-1" "targetname" "t1" "lip" "48" "sounds" "4" "model" "*4" } { "classname" "func_button" "angle" "-2" "target" "t1" "wait" "-1" "model" "*5" } { "classname" "light" "origin" "0 320 176" "target" "t2" } { "classname" "info_null" "origin" "68 316 20" "targetname" "t2" } { "classname" "light" "origin" "224 144 168" } { "classname" "light" "origin" "224 416 416" "light" "500" } { "light" "500" "classname" "light" "origin" "224 216 416" } { "classname" "light_flame_small_white" "origin" "-142 498 18" } { "light" "400" "origin" "208 856 104" "classname" "light" "style" "2" "target" "t63" } { "style" "32" "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t3" "model" "*6" } { "classname" "light" "origin" "-192 1152 -48" "light" "400" } { "classname" "light" "origin" "-512 1152 -48" "light" "400" } { "classname" "light" "origin" "-512 1408 -48" "light" "400" } { "classname" "light" "origin" "-192 1408 -48" "light" "400" } { "classname" "light" "origin" "-384 1280 32" } { "style" "32" "classname" "light" "origin" "-48 1280 160" "targetname" "t3" "spawnflags" "1" "light" "200" } { "targetname" "t88" "spawnflags" "32" "message" "This door is opened elsewhere." "classname" "func_door" "angle" "90" "sounds" "1" "model" "*7" } { "classname" "light" "origin" "-192 1280 -168" "light" "250" } { "classname" "light" "origin" "-24 1296 -248" } { "wait" "-1" "angle" "-2" "spawnflags" "4" "targetname" "t5" "lip" "160" "classname" "func_door" "sounds" "1" "model" "*8" } { "wait" "-1" "spawnflags" "4" "targetname" "t5" "lip" "144" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*9" } { "wait" "10" "delay" "3" "target" "t5" "classname" "trigger_once" "model" "*10" } { "spawnflags" "4" "targetname" "t5" "lip" "128" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*11" } { "spawnflags" "4" "lip" "112" "wait" "-1" "angle" "-2" "targetname" "t5" "classname" "func_door" "sounds" "1" "model" "*12" } { "spawnflags" "4" "targetname" "t5" "wait" "-1" "angle" "-2" "lip" "96" "classname" "func_door" "sounds" "1" "model" "*13" } { "spawnflags" "4" "lip" "80" "angle" "-2" "wait" "-1" "targetname" "t5" "classname" "func_door" "sounds" "1" "model" "*14" } { "spawnflags" "4" "lip" "64" "targetname" "t5" "angle" "-2" "wait" "-1" "classname" "func_door" "sounds" "1" "model" "*15" } { "spawnflags" "4" "angle" "-2" "targetname" "t5" "wait" "-1" "lip" "48" "classname" "func_door" "sounds" "1" "model" "*16" } { "origin" "-512 1280 -448" "classname" "light" } { "style" "33" "spawnflags" "2048" "classname" "item_key1" "origin" "-696 1280 -232" "sounds" "2" "target" "t34" } { "targetname" "t11" "classname" "monster_ogre" "origin" "-642 1278 -232" "angle" "180" "spawnflags" "256" } { "targetname" "t11" "classname" "monster_ogre" "origin" "-362 1590 -232" "angle" "90" } { "targetname" "t11" "classname" "monster_ogre" "origin" "-314 1014 -232" "angle" "270" "spawnflags" "768" } { "classname" "func_plat" "model" "*17" } { "origin" "-504 1784 -192" "classname" "light" } { "light" "200" "origin" "-704 1952 -352" "classname" "light" } { "classname" "info_teleport_destination" "origin" "-32 1280 -328" "angle" "180" "targetname" "t6" } { "classname" "light" "origin" "-320 832 -192" } { "wait" "-1" "targetname" "t3" "angle" "-1" "classname" "func_door" "sounds" "3" "model" "*18" } { "targetname" "t87" "wait" "-1" "angle" "-1" "classname" "func_door" "sounds" "3" "model" "*19" } { "light" "300" "origin" "344 1424 216" "classname" "light" } { "target" "t7" "angle" "270" "origin" "286 782 24" "classname" "monster_ogre" } { "target" "t7" "targetname" "t8" "angle" "180" "origin" "200 584 8" "classname" "path_corner" } { "target" "t8" "targetname" "t9" "angle" "0" "origin" "-64 584 8" "classname" "path_corner" } { "target" "t8" "targetname" "t7" "angle" "270" "origin" "200 1032 8" "classname" "path_corner" } { "targetname" "t82" "angle" "0" "origin" "22 1278 24" "classname" "monster_ogre" "spawnflags" "256" } { "angle" "180" "origin" "398 1454 24" "classname" "monster_ogre" "targetname" "t82" } { "spawnflags" "32" "message" "This door is opened elsewhere." "angle" "270" "classname" "func_door" "model" "*20" } { "origin" "-96 1240 480" "classname" "light" } { "origin" "-96 1320 480" "classname" "light" } { "light" "200" "origin" "-96 1184 264" "classname" "light" } { "light" "200" "origin" "-96 1344 264" "classname" "light" } { "light" "200" "origin" "-480 1360 416" "classname" "light" } { "light" "200" "origin" "-248 1192 416" "classname" "light" } { "light" "200" "origin" "-480 1200 416" "classname" "light" } { "light" "200" "origin" "-232 1392 416" "classname" "light" } { "target" "t11" "classname" "trigger_once" "model" "*21" } { "target" "t12" "classname" "trigger_teleport" "model" "*22" } { "targetname" "t12" "angle" "180" "origin" "352 868 12" "classname" "info_teleport_destination" } { "origin" "-96 1280 216" "classname" "weapon_supernailgun" } { "target" "t13" "origin" "-256 1648 -248" "classname" "light" } { "targetname" "t13" "origin" "-252 1660 -132" "classname" "info_null" } { "targetname" "t14" "origin" "-388 1660 -132" "classname" "info_null" } { "targetname" "t15" "origin" "-764 1660 -132" "classname" "info_null" } { "target" "t14" "origin" "-384 1648 -248" "classname" "light" } { "target" "t15" "origin" "-752 1648 -248" "classname" "light" } { "target" "t16" "origin" "-512 1648 -248" "classname" "light" } { "target" "t17" "origin" "-632 1648 -248" "classname" "light" } { "targetname" "t16" "origin" "-516 1660 -140" "classname" "info_null" } { "targetname" "t17" "origin" "-636 1660 -140" "classname" "info_null" } { "targetname" "t21" "origin" "-764 1532 -132" "classname" "info_null" } { "targetname" "t22" "origin" "-764 1412 -132" "classname" "info_null" } { "targetname" "t23" "origin" "-764 1284 -132" "classname" "info_null" } { "targetname" "t20" "origin" "-764 1148 -132" "classname" "info_null" } { "targetname" "t19" "origin" "-764 1028 -132" "classname" "info_null" } { "targetname" "t18" "origin" "-764 964 -132" "classname" "info_null" } { "target" "t21" "origin" "-744 1528 -248" "classname" "light" } { "target" "t22" "origin" "-752 1408 -248" "classname" "light" } { "target" "t23" "origin" "-752 1280 -248" "classname" "light" } { "target" "t20" "origin" "-752 1144 -248" "classname" "light" } { "target" "t19" "origin" "-752 1024 -248" "classname" "light" } { "target" "t18" "origin" "-752 976 -248" "classname" "light" } { "targetname" "t25" "origin" "-636 964 -132" "classname" "info_null" } { "targetname" "t26" "origin" "-516 964 -132" "classname" "info_null" } { "targetname" "t27" "origin" "-388 964 -132" "classname" "info_null" } { "targetname" "t28" "origin" "-252 964 -132" "classname" "info_null" } { "targetname" "t29" "origin" "-196 964 -132" "classname" "info_null" } { "targetname" "t24" "origin" "-196 1660 -132" "classname" "info_null" } { "target" "t24" "origin" "-200 1656 -248" "classname" "light" } { "target" "t29" "origin" "-200 968 -248" "classname" "light" } { "target" "t28" "origin" "-248 968 -248" "classname" "light" } { "target" "t27" "origin" "-392 968 -248" "classname" "light" } { "target" "t26" "origin" "-512 968 -248" "classname" "light" } { "target" "t25" "origin" "-640 968 -248" "classname" "light" } { "light" "150" "origin" "-320 1592 -248" "classname" "light" } { "light" "150" "origin" "-448 1592 -248" "classname" "light" } { "light" "150" "origin" "-576 1592 -248" "classname" "light" } { "light" "150" "origin" "-696 1592 -248" "classname" "light" } { "light" "150" "origin" "-696 1464 -248" "classname" "light" } { "light" "150" "origin" "-696 1336 -248" "classname" "light" } { "light" "150" "origin" "-696 1208 -248" "classname" "light" } { "light" "150" "origin" "-696 1056 -248" "classname" "light" } { "light" "150" "origin" "-568 1032 -248" "classname" "light" } { "light" "150" "origin" "-440 1032 -248" "classname" "light" } { "light" "150" "origin" "-248 1032 -248" "classname" "light" } { "wait" "5" "spawnflags" "4" "targetname" "t31" "lip" "-16" "angle" "-2" "classname" "func_door" "model" "*23" } { "wait" "5" "targetname" "t31" "spawnflags" "4" "lip" "-48" "angle" "-2" "classname" "func_door" "model" "*24" } { "wait" "8" "target" "t31" "classname" "trigger_multiple" "health" "1" "model" "*25" } { "wait" "5" "targetname" "t31" "spawnflags" "4" "lip" "-80" "angle" "-2" "classname" "func_door" "model" "*26" } { "wait" "5" "lip" "-112" "spawnflags" "4" "targetname" "t31" "angle" "-2" "classname" "func_door" "model" "*27" } { "target" "t32" "classname" "trigger_teleport" "model" "*28" } { "angle" "0" "targetname" "t32" "origin" "-96 800 208" "classname" "info_teleport_destination" } { "classname" "light" "origin" "-512 64 128" "light" "250" } { "angle" "270" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*29" } { "wait" "-1" "classname" "func_door" "angle" "90" "spawnflags" "2064" "sounds" "4" "model" "*30" } { "style" "33" "light" "200" "classname" "light" "origin" "-384 880 96" "targetname" "t34" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "-506 566 24" "angle" "90" "spawnflags" "1281" } { "classname" "func_door" "angle" "180" "wait" "-1" "sounds" "1" "model" "*31" } { "classname" "item_health" "origin" "472 1496 0" } { "classname" "item_health" "origin" "432 1496 0" } { "classname" "item_health" "origin" "-152 712 192" } { "classname" "item_health" "origin" "-152 888 192" } { "classname" "trigger_teleport" "target" "t53" "model" "*32" } { "classname" "item_health" "origin" "-648 552 304" "spawnflags" "2" } { "classname" "func_door" "angle" "180" "wait" "-1" "targetname" "t44" "model" "*33" } { "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t44" "model" "*34" } { "classname" "func_door" "angle" "0" "wait" "-1" "targetname" "t44" "model" "*35" } { "classname" "func_door" "angle" "180" "wait" "-1" "model" "*36" } { "classname" "func_door" "angle" "0" "wait" "-1" "targetname" "t44" "model" "*37" } { "origin" "-480 1432 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-480 1280 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-480 1128 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-336 1432 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-336 1120 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-192 1128 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "origin" "-192 1432 -344" "classname" "misc_fireball" "speed" "1000" "spawnflags" "2048" } { "wait" "-1" "classname" "func_button" "angle" "180" "target" "t44" "model" "*38" } { "classname" "func_train" "angle" "0" "target" "t45" "speed" "50" "dmg" "1000" "delay" "5" "targetname" "t48" "sounds" "1" "model" "*39" } { "classname" "path_corner" "origin" "-768 1088 -512" "angle" "90" "targetname" "t45" "target" "t46" } { "classname" "path_corner" "origin" "-768 2000 -512" "targetname" "t46" "target" "t47" } { "classname" "item_health" "origin" "-720 1968 -512" "spawnflags" "2" } { "classname" "light" "origin" "-704 2016 -432" } { "classname" "path_corner" "origin" "-768 2000 -512" "targetname" "t47" "target" "t45" } { "classname" "monster_ogre" "origin" "-456 1552 88" "angle" "270" "targetname" "t44" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-240 1552 88" "angle" "270" "targetname" "t44" } { "light" "200" "classname" "light" "origin" "-704 1072 -440" } { "classname" "func_door" "angle" "-2" "wait" "30" "targetname" "t48" "speed" "400" "sounds" "1" "spawnflags" "1" "model" "*40" } { "classname" "trigger_once" "target" "t48" "model" "*41" } { "classname" "monster_ogre" "origin" "-864 1584 -488" "angle" "270" "target" "t49" "targetname" "t48" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "-864 1424 -488" "angle" "270" "target" "t49" "targetname" "t48" "spawnflags" "768" } { "classname" "trigger_counter" "targetname" "t49" "target" "t50" "model" "*42" } { "sounds" "3" "targetname" "t83" "spawnflags" "2048" "classname" "func_door" "angle" "-1" "wait" "-1" "model" "*43" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t51" "speed" "200" "sounds" "1" "model" "*44" } { "classname" "monster_ogre" "origin" "-704 848 24" "angle" "0" "targetname" "t51" } { "classname" "trigger_once" "target" "t51" "model" "*45" } { "classname" "light" "origin" "-656 848 120" "light" "200" } { "classname" "func_door" "angle" "90" "wait" "-1" "lip" "80" "model" "*46" } { "classname" "func_door" "angle" "270" "wait" "-1" "targetname" "t52" "lip" "80" "model" "*47" } { "classname" "monster_zombie" "origin" "-624 352 296" "angle" "90" "targetname" "t52" } { "classname" "monster_zombie" "origin" "-880 368 304" "angle" "90" "targetname" "t52" } { "classname" "monster_zombie" "origin" "-496 352 296" "angle" "90" "targetname" "t52" } { "classname" "monster_zombie" "origin" "-624 480 296" "angle" "270" "targetname" "t52" "spawnflags" "768" } { "classname" "monster_zombie" "origin" "-880 464 304" "angle" "270" "targetname" "t52" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "-496 480 296" "angle" "270" "targetname" "t52" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "-648 248 312" "angle" "90" "targetname" "t53" } { "classname" "light" "origin" "-560 592 392" "light" "200" } { "classname" "light" "origin" "-568 232 392" "light" "200" } { "classname" "light" "origin" "-288 616 -112" } { "classname" "light" "origin" "-392 616 -112" } { "classname" "light" "origin" "-384 224 -112" } { "classname" "light" "origin" "-216 224 -112" } { "classname" "func_button" "angle" "180" "wait" "-1" "target" "t70" "model" "*48" } { "classname" "light_flame_small_white" "origin" "-990 546 40" } { "classname" "light" "origin" "-928 480 200" "light" "200" } { "origin" "-990 290 40" "classname" "light_flame_small_white" } { "classname" "light" "origin" "-928 352 200" "light" "200" } { "classname" "func_door" "angle" "90" "targetname" "t52" "wait" "-1" "model" "*49" } { "classname" "func_door" "angle" "270" "wait" "-1" "model" "*50" } { "classname" "light" "origin" "-880 416 360" "light" "200" } { "light" "400" "origin" "-336 608 448" "classname" "light" } { "light" "400" "origin" "-328 480 448" "classname" "light" } { "light" "400" "origin" "-304 344 448" "classname" "light" } { "light" "400" "origin" "-280 216 448" "classname" "light" } { "light" "200" "origin" "-232 200 168" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "-696 416 168" "light" "200" } { "light" "150" "origin" "-192 320 72" "classname" "light" } { "origin" "-480 392 224" "classname" "light" } { "light" "200" "origin" "-744 416 168" "classname" "light_flame_small_yellow" } { "light" "200" "origin" "-616 632 168" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "-416 632 168" "light" "200" } { "light" "150" "origin" "-664 600 64" "classname" "light" } { "light" "150" "origin" "-664 232 64" "classname" "light" } { "light" "150" "origin" "-504 608 64" "classname" "light" } { "wait" "-1" "targetname" "t52" "angle" "-1" "classname" "func_door" "sounds" "4" "model" "*51" } { "light" "150" "origin" "-376 432 -104" "classname" "light" } { "light" "150" "origin" "-272 336 -192" "classname" "light" } { "light" "250" "origin" "-512 392 -104" "classname" "light" } { "light" "150" "origin" "-512 96 0" "classname" "light" } { "light" "200" "origin" "-240 440 168" "classname" "light_flame_small_yellow" } { "light" "100" "origin" "-672 416 24" "classname" "light" } { "light" "100" "origin" "-776 424 24" "classname" "light" } { "classname" "item_shells" "origin" "-512 992 -256" } { "classname" "light" "origin" "-96 248 80" "light" "200" } { "classname" "light" "origin" "-96 392 80" "light" "200" } { "classname" "info_player_deathmatch" "origin" "-928 416 24" "angle" "0" } { "classname" "weapon_supershotgun" "origin" "-800 416 0" "spawnflags" "1792" } { "classname" "light" "origin" "-544 1800 -376" "light" "200" } { "classname" "info_player_deathmatch" "origin" "-704 1536 -232" "angle" "270" } { "classname" "weapon_rocketlauncher" "origin" "-696 1008 -256" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "216 1488 24" "angle" "270" } { "classname" "item_rockets" "origin" "-40 880 192" } { "classname" "item_shells" "origin" "-48 816 192" } { "classname" "light" "origin" "64 832 -192" "light" "200" } { "classname" "trigger_teleport" "target" "t12" "model" "*52" } { "classname" "trap_spikeshooter" "origin" "-88 748 -216" "angle" "90" "targetname" "t62" } { "classname" "trap_spikeshooter" "origin" "-128 916 -216" "angle" "270" "targetname" "t62" } { "classname" "trap_spikeshooter" "origin" "-296 916 -72" "angle" "270" "targetname" "t62" } { "classname" "trap_spikeshooter" "origin" "-264 748 -72" "angle" "90" "targetname" "t62" } { "classname" "trigger_multiple" "wait" "1" "target" "t62" "model" "*53" } { "classname" "trap_spikeshooter" "origin" "-168 748 -216" "angle" "90" "targetname" "t62" } { "classname" "trap_spikeshooter" "origin" "-184 832 -216" "angle" "0" "targetname" "t62" } { "classname" "trap_spikeshooter" "origin" "-232 916 -72" "angle" "270" "targetname" "t62" } { "targetname" "t48" "classname" "monster_ogre" "origin" "-864 1504 -488" "spawnflags" "1024" "target" "t50" } { "classname" "info_null" "origin" "196 860 20" "targetname" "t63" } { "classname" "item_health" "origin" "-672 832 0" } { "style" "33" "light" "200" "spawnflags" "1" "targetname" "t34" "origin" "-104 832 -192" "classname" "light" } { "style" "33" "light" "150" "spawnflags" "1" "targetname" "t34" "origin" "-264 832 -48" "classname" "light" } { "speed" "400" "angle" "-1" "origin" "288 408 -40" "classname" "misc_fireball" "spawnflags" "2048" } { "speed" "400" "angle" "-1" "origin" "288 240 -40" "classname" "misc_fireball" "spawnflags" "2048" } { "speed" "400" "angle" "-1" "origin" "160 408 -40" "classname" "misc_fireball" "spawnflags" "2048" } { "speed" "400" "angle" "-1" "origin" "160 232 -40" "classname" "misc_fireball" "spawnflags" "2048" } { "light" "100" "origin" "224 -24 24" "classname" "light" } { "light" "100" "origin" "224 24 24" "classname" "light" } { "light" "100" "origin" "224 72 24" "classname" "light" } { "light" "100" "origin" "224 128 24" "classname" "light" } { "light" "100" "origin" "224 184 24" "classname" "light" } { "spawnflags" "1792" "origin" "-720 1920 -512" "classname" "item_rockets" } { "spawnflags" "1793" "origin" "-488 1552 64" "classname" "item_spikes" } { "spawnflags" "1792" "origin" "224 120 32" "classname" "item_armor2" } { "spawnflags" "1792" "origin" "-608 1280 -256" "classname" "item_armor2" } { "wait" "1" "target" "t62" "classname" "trigger_multiple" "model" "*54" } { "spawnflags" "2048" "classname" "func_wall" "model" "*55" } { "classname" "trigger_once" "targetname" "t70" "target" "t52" "delay" "3" "model" "*56" } { "classname" "func_door" "angle" "-2" "lip" "-8" "wait" "-1" "speed" "400" "targetname" "t48" "model" "*57" } { "lip" "10" "targetname" "t48" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*58" } { "classname" "light_flame_small_yellow" "origin" "736 416 40" } { "classname" "light_flame_small_yellow" "origin" "736 160 40" } { "classname" "light" "origin" "680 368 160" "light" "200" } { "classname" "light" "origin" "680 208 160" "light" "200" } { "style" "34" "spawnflags" "1" "targetname" "t73" "light" "100" "origin" "832 288 96" "classname" "light" } { "style" "35" "spawnflags" "1" "targetname" "t76" "light" "200" "origin" "1024 288 96" "classname" "light" } { "light" "100" "origin" "400 384 168" "classname" "light" } { "classname" "light" "origin" "400 272 168" "light" "100" } { "light" "100" "origin" "400 144 168" "classname" "light" } { "origin" "416 160 40" "classname" "light_flame_small_yellow" } { "light" "200" "origin" "472 216 160" "classname" "light" } { "sounds" "1" "target" "t71" "wait" "-1" "angle" "-2" "classname" "func_button" "spawnflags" "2048" "model" "*59" } { "speed" "75" "sounds" "3" "wait" "-1" "targetname" "t71" "angle" "270" "classname" "func_door" "model" "*60" } { "speed" "75" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*61" } { "style" "2" "target" "t72" "origin" "656 288 104" "classname" "light" } { "targetname" "t72" "origin" "676 292 12" "classname" "info_null" } { "style" "34" "sounds" "3" "delay" "1" "target" "t73" "targetname" "t71" "classname" "trigger_once" "model" "*62" } { "style" "36" "sounds" "3" "delay" "2" "target" "t74" "targetname" "t71" "classname" "trigger_once" "model" "*63" } { "style" "37" "sounds" "3" "delay" "3" "target" "t75" "targetname" "t71" "classname" "trigger_once" "model" "*64" } { "style" "35" "sounds" "3" "delay" "4" "target" "t76" "targetname" "t71" "classname" "trigger_once" "model" "*65" } { "style" "36" "spawnflags" "1" "targetname" "t74" "classname" "light" "origin" "880 288 96" "light" "140" } { "style" "37" "spawnflags" "1" "targetname" "t75" "light" "100" "origin" "928 288 96" "classname" "light" } { "classname" "info_player_start" "origin" "-96 800 224" "angle" "0" } { "classname" "light" "origin" "-352 1552 168" "target" "t79" } { "classname" "info_null" "origin" "-356 1532 68" "targetname" "t79" } { "sounds" "1" "classname" "trigger_secret" "model" "*66" } { "classname" "trigger_once" "target" "t82" "model" "*67" } { "speed" "400" "origin" "-376 568 -120" "classname" "misc_fireball" "spawnflags" "2048" } { "classname" "misc_fireball" "origin" "-304 480 -120" "speed" "400" "spawnflags" "2048" } { "speed" "400" "origin" "-384 256 -120" "classname" "misc_fireball" "spawnflags" "2048" } { "classname" "misc_fireball" "origin" "-288 224 -120" "speed" "400" "spawnflags" "2048" } { "angle" "180" "origin" "488 768 24" "classname" "monster_ogre" } { "angle" "180" "origin" "488 640 24" "classname" "monster_ogre" "spawnflags" "256" } { "light" "200" "origin" "480 504 80" "classname" "light" } { "sounds" "3" "target" "t83" "targetname" "t50" "classname" "trigger_once" "model" "*68" } { "light" "200" "origin" "104 1264 -48" "classname" "light" } { "light" "200" "origin" "224 1176 -48" "classname" "light" } { "light" "200" "origin" "216 1296 -48" "classname" "light" } { "style" "32" "targetname" "t3" "spawnflags" "1" "light" "200" "origin" "192 1056 232" "classname" "light" } { "style" "32" "spawnflags" "1" "targetname" "t3" "classname" "light" "origin" "192 1184 232" "light" "200" } { "style" "32" "spawnflags" "1" "targetname" "t3" "classname" "light" "origin" "-32 1280 232" "light" "200" } { "style" "32" "targetname" "t3" "spawnflags" "1" "light" "200" "origin" "96 1272 232" "classname" "light" } { "light" "150" "origin" "192 1264 16" "classname" "light" } { "light" "200" "origin" "-128 1280 64" "classname" "light" } { "classname" "light" "origin" "320 1280 64" "light" "150" } { "classname" "light" "origin" "-80 608 352" "light" "150" } { "light" "150" "origin" "-80 800 352" "classname" "light" } { "classname" "light" "origin" "80 688 24" "light" "100" } { "light" "100" "origin" "80 864 24" "classname" "light" } { "classname" "light" "origin" "-112 528 24" "light" "100" } { "light" "150" "origin" "304 608 352" "classname" "light" } { "classname" "light" "origin" "304 800 352" "light" "150" } { "light" "100" "origin" "328 800 24" "classname" "light" } { "classname" "light" "origin" "336 608 24" "light" "100" } { "classname" "func_wall" "spawnflags" "2048" "model" "*69" } { "classname" "func_wall" "spawnflags" "2048" "model" "*70" } { "classname" "light" "origin" "192 984 304" "light" "150" } { "light" "150" "origin" "192 1128 304" "classname" "light" } { "classname" "light" "origin" "192 1280 304" "light" "150" } { "light" "150" "origin" "32 1280 304" "classname" "light" } { "style" "32" "classname" "light" "origin" "192 1008 40" "light" "150" "spawnflags" "1" "targetname" "t3" } { "classname" "func_door" "angle" "-2" "targetname" "t84" "sounds" "1" "model" "*71" } { "classname" "func_plat" "model" "*72" } { "classname" "trigger_multiple" "health" "1" "target" "t84" "model" "*73" } { "classname" "light" "origin" "544 1504 24" "light" "200" } { "light" "200" "origin" "192 1504 24" "classname" "light" } { "classname" "light" "origin" "544 1280 24" "light" "200" } { "classname" "light" "origin" "544 1504 344" "light" "200" } { "light" "200" "origin" "544 1304 344" "classname" "light" } { "light" "200" "origin" "352 1440 344" "classname" "light" } { "classname" "light" "origin" "624 1440 176" "light" "200" } { "classname" "light" "origin" "624 1440 256" "light" "200" } { "classname" "light" "origin" "672 1440 336" "light" "150" } { "angle" "270" "target" "t88" "classname" "func_button" "wait" "2" "model" "*74" } { "light" "200" "style" "2" "target" "t85" "origin" "448 1312 72" "classname" "light" } { "angle" "270" "targetname" "t85" "origin" "448 1260 52" "classname" "info_null" } { "light" "150" "origin" "452 1252 20" "classname" "light" } { "classname" "func_wall" "spawnflags" "2048" "model" "*75" } { "angle" "270" "targetname" "t86" "origin" "-580 1276 36" "classname" "info_null" } { "style" "2" "target" "t86" "light" "200" "origin" "-528 1272 40" "classname" "light" } { "sounds" "1" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*76" } { "target" "t88" "targetname" "t44" "classname" "trigger_once" "model" "*77" } { "target" "t88" "targetname" "t34" "classname" "trigger_once" "model" "*78" } { "lip" "-2" "wait" "-1" "targetname" "t52" "angle" "180" "classname" "func_door" "model" "*79" } { "lip" "3" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*80" } { "spawnflags" "1" "origin" "-528 48 -81" "classname" "item_rockets" } { "sounds" "1" "classname" "trigger_secret" "model" "*81" } { "style" "33" "targetname" "t34" "spawnflags" "1" "origin" "-384 784 96" "classname" "light" "light" "200" } { "style" "33" "light" "200" "spawnflags" "1" "targetname" "t34" "origin" "-192 896 96" "classname" "light" } { "style" "33" "spawnflags" "1" "targetname" "t34" "light" "200" "origin" "-192 776 96" "classname" "light" } { "style" "33" "spawnflags" "1" "light" "175" "targetname" "t34" "origin" "-512 720 96" "classname" "light" } { "light" "125" "origin" "-104 832 144" "classname" "light" } { "classname" "light" "origin" "-288 832 144" "light" "125" } { "classname" "trigger_secret" "model" "*82" } { "classname" "light" "origin" "-704 1760 -352" "light" "200" } { "light" "200" "origin" "-704 1568 -352" "classname" "light" } { "classname" "light" "origin" "-704 1376 -352" "light" "200" } { "light" "200" "origin" "-704 1176 -440" "classname" "light" } { "classname" "light" "origin" "-848 1568 -400" "light" "200" } { "light" "200" "origin" "-864 1392 -400" "classname" "light" } { "spawnflags" "1" "classname" "item_spikes" "origin" "-208 608 0" } { "classname" "monster_ogre" "origin" "-128 576 24" "angle" "0" "spawnflags" "768" } { "classname" "trigger_monsterjump" "model" "*83" } { "classname" "monster_demon1" "origin" "-504 504 24" "spawnflags" "769" "angle" "90" } { "targetname" "t90" "target" "t89" "classname" "trigger_teleport" "spawnflags" "2" "model" "*84" } { "spawnflags" "768" "targetname" "t90" "angle" "0" "origin" "-944 1888 -544" "classname" "monster_ogre" } { "angle" "270" "targetname" "t89" "origin" "-704 1856 -504" "classname" "info_teleport_destination" } { "target" "t90" "classname" "trigger_once" "model" "*85" } { "targetname" "t1" "wait" "-1" "angle" "180" "classname" "func_door" "message" "This door is opened elsewhere..." "model" "*86" } { "wait" "-1" "angle" "0" "classname" "func_door" "sounds" "4" "model" "*87" } { "spawnflags" "769" "angle" "0" "origin" "-864 496 24" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "-864 320 24" "angle" "0" "spawnflags" "257" } { "targetname" "t94" "angle" "270" "origin" "16 1832 32" "classname" "monster_wizard" } { "targetname" "t94" "classname" "monster_wizard" "origin" "104 1832 32" "angle" "270" } { "targetname" "t94" "angle" "270" "origin" "184 1832 32" "classname" "monster_wizard" } { "targetname" "t94" "target" "t91" "classname" "trigger_teleport" "spawnflags" "2" "model" "*88" } { "targetname" "t94" "target" "t93" "classname" "trigger_teleport" "spawnflags" "2" "model" "*89" } { "targetname" "t94" "target" "t92" "classname" "trigger_teleport" "spawnflags" "2" "model" "*90" } { "targetname" "t93" "angle" "0" "origin" "-392 1412 344" "classname" "info_teleport_destination" } { "targetname" "t92" "classname" "info_teleport_destination" "origin" "-456 1296 296" "angle" "0" } { "targetname" "t91" "angle" "0" "origin" "-388 1168 184" "classname" "info_teleport_destination" } { "target" "t94" "classname" "trigger_once" "model" "*91" } { "target" "t96" "classname" "trigger_once" "model" "*92" } { "spawnflags" "256" "targetname" "t96" "angle" "270" "origin" "584 1112 32" "classname" "monster_ogre" } { "targetname" "t96" "target" "t95" "classname" "trigger_teleport" "spawnflags" "2" "model" "*93" } { "targetname" "t95" "angle" "180" "origin" "272 704 16" "classname" "info_teleport_destination" } { "classname" "monster_demon1" "origin" "-48 320 24" "angle" "180" "spawnflags" "768" } { "classname" "monster_shambler" "origin" "728 880 32" "angle" "270" "targetname" "t98" "spawnflags" "768" } { "targetname" "t98" "classname" "trigger_teleport" "target" "t97" "spawnflags" "2" "model" "*94" } { "classname" "info_teleport_destination" "origin" "224 608 8" "angle" "270" "targetname" "t97" } { "classname" "monster_demon1" "origin" "728 880 32" "angle" "270" "spawnflags" "1280" "targetname" "t98" } { "classname" "monster_shambler" "origin" "1048 288 24" "angle" "0" "targetname" "t76" "target" "t99" } { "style" "35" "classname" "light" "origin" "1216 352 -56" "targetname" "t76" "spawnflags" "1" } { "style" "35" "origin" "1216 224 -56" "classname" "light" "targetname" "t76" "spawnflags" "1" } { "style" "35" "classname" "light" "origin" "1088 192 96" "targetname" "t76" "spawnflags" "1" "light" "150" } { "style" "35" "origin" "1088 384 96" "classname" "light" "targetname" "t76" "spawnflags" "1" "light" "150" } { "classname" "light" "origin" "480 424 80" "light" "200" } { "classname" "light" "origin" "672 288 0" "light" "150" } { "classname" "light" "origin" "616 192 24" "light" "150" } { "classname" "trigger_changelevel" "map" "e1m7" "model" "*95" } { "classname" "trigger_multiple" "targetname" "t71" "target" "t99" "model" "*96" } { "classname" "info_intermission" "origin" "48 912 248" "mangle" "20 315 0" } { "spawnflags" "3072" "origin" "-208 656 0" "classname" "item_health" } { "classname" "item_shells" "origin" "536 1296 8" } { "classname" "item_spikes" "origin" "-112 1168 216" "spawnflags" "3073" } { "classname" "item_health" "origin" "-648 224 0" } { "origin" "-688 224 0" "classname" "item_health" } { "classname" "item_rockets" "origin" "-696 600 0" } { "classname" "item_health" "origin" "-152 344 0" } { "origin" "-112 344 0" "classname" "item_health" "spawnflags" "3072" } { "classname" "trigger_once" "target" "t87" "model" "*97" } { "spawnflags" "2048" "classname" "func_door" "targetname" "t34" "angle" "-2" "wait" "-1" "speed" "50" "sounds" "4" "message" "These bars are opened elsewhere..." "model" "*98" } { "classname" "trigger_relay" "origin" "-728 1240 -240" "targetname" "t34" "message" "Your way has been lit..." } { "classname" "item_artifact_super_damage" "origin" "448 1296 208" } { "classname" "item_health" "origin" "-368 1520 64" "spawnflags" "2" } { "classname" "item_armor2" "origin" "-504 1280 0" } { "classname" "light" "origin" "-288 928 -200" "light" "125" } { "light" "125" "origin" "-352 928 -200" "classname" "light" } { "classname" "trigger_teleport" "target" "t100" "model" "*99" } { "classname" "info_teleport_destination" "origin" "-96 1408 216" "targetname" "t100" "angle" "270" } { "classname" "trigger_secret" "model" "*100" } { "classname" "item_spikes" "origin" "400 280 0" "spawnflags" "1" } { "classname" "item_health" "origin" "656 136 0" } { "origin" "664 408 0" "classname" "item_health" "spawnflags" "3072" } { "classname" "item_health" "origin" "400 208 0" "spawnflags" "3072" } { "classname" "item_rockets" "origin" "400 320 0" "spawnflags" "3584" } { "classname" "item_armor2" "origin" "864 288 0" } { "classname" "item_shells" "origin" "424 848 0" } { "wait" "2" "classname" "func_button" "angle" "90" "target" "t99" "model" "*101" } { "classname" "light" "origin" "476 924 20" "light" "150" } { "classname" "light" "origin" "480 920 104" "light" "150" } { "classname" "item_spikes" "origin" "-488 120 80" "spawnflags" "1" } { "classname" "item_health" "origin" "-488 80 80" "spawnflags" "3584" } { "classname" "item_spikes" "origin" "-944 528 0" } { "classname" "func_door" "angle" "-1" "spawnflags" "32" "message" "This door is opened elsewhere..." "targetname" "t99" "sounds" "4" "speed" "200" "dmg" "50" "model" "*102" } { "classname" "item_rockets" "origin" "-56 1360 -336" } { "classname" "item_health" "origin" "-56 1168 -336" "spawnflags" "1024" } { "classname" "item_spikes" "origin" "-240 1600 -256" } { "classname" "item_health" "origin" "-760 1592 -256" "spawnflags" "3073" } { "spawnflags" "3073" "origin" "-760 1552 -256" "classname" "item_health" } { "angle" "0" "origin" "-72 744 224" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-80 872 224" "angle" "0" } { "classname" "item_spikes" "origin" "-320 1520 64" "spawnflags" "2817" } { "style" "33" "target" "t34" "spawnflags" "1792" "classname" "trigger_once" "model" "*103" } { "spawnflags" "1792" "classname" "func_wall" "model" "*104" } { "spawnflags" "1792" "classname" "func_wall" "model" "*105" } { "classname" "func_button" "angle" "-2" "sounds" "1" "target" "t71" "spawnflags" "1792" "model" "*106" } { "classname" "weapon_rocketlauncher" "origin" "488 1456 0" "spawnflags" "2048" } { "angle" "270" "origin" "-24 888 32" "classname" "info_player_coop" } { "classname" "weapon_supernailgun" "origin" "560 288 0" "spawnflags" "3584" } { "spawnflags" "1792" "origin" "-40 1280 -336" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "1056 296 8" "classname" "weapon_supernailgun" } { "angle" "90" "origin" "544 176 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-88 504 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-640 416 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-448 1280 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "352 1296 24" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "480 824 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-224 1016 -232" "classname" "info_player_deathmatch" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "1100 296 48" "classname" "item_flag_team1" } { "angle" "90" "origin" "600 196 24" "classname" "info_player_team1" } { "angle" "90" "origin" "600 296 24" "classname" "info_player_team1" } { "angle" "90" "origin" "600 396 24" "classname" "info_player_team1" } { "angle" "90" "origin" "500 196 24" "classname" "info_player_team1" } { "angle" "90" "origin" "500 296 24" "classname" "info_player_team1" } { "angle" "90" "origin" "500 396 24" "classname" "info_player_team1" } // team2 { "origin" "-1004 416 44" "classname" "item_flag_team2" } { "angle" "0" "origin" "-904 316 24" "classname" "info_player_team2" } { "angle" "0" "origin" "-904 416 24" "classname" "info_player_team2" } { "angle" "0" "origin" "-904 516 24" "classname" "info_player_team2" } { "angle" "0" "origin" "-804 316 24" "classname" "info_player_team2" } { "angle" "0" "origin" "-804 416 24" "classname" "info_player_team2" } { "angle" "0" "origin" "-804 516 24" "classname" "info_player_team2" } // base one weapons upgrade //{ //"classname" "item_health" //"origin" "-488 2064 1220" //} //{ //"origin" "-488 2112 1220" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "-488 2160 1220" //} //{ //"origin" "-72 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-120 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-168 2064 1220" //"classname" "item_shells" //} //{ //"origin" "-72 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-120 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-168 2112 1220" //"classname" "item_spikes" //} //{ //"origin" "-72 2160 1220" //"classname" "weapon_supershotgun" //} //{ //"origin" "-120 2160 1220" //"classname" "item_armor2" //} //{ //"origin" "-168 2160 1220" //"classname" "weapon_supernailgun" //} // //// base two weapons upgrade //{ //"classname" "item_shells" //"origin" "1240 768 1384" //} //{ //"classname" "item_shells" //"origin" "1192 768 1384" //} //{ //"classname" "item_shells" //"origin" "1144 768 1384" //} //{ //"classname" "item_spikes" //"origin" "1240 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1192 816 1384" //} //{ //"classname" "item_spikes" //"origin" "1144 816 1384" //} //{ //"origin" "1240 864 1384" //"classname" "weapon_supershotgun" //} //{ //"classname" "item_armor2" //"origin" "1192 864 1384" //} //{ //"classname" "weapon_supernailgun" //"origin" "1144 864 1384" //} //{ //"origin" "1240 912 1384" //"classname" "item_health" //} //{ //"classname" "item_health" //"origin" "1192 912 1384" //} //{ //"classname" "item_health" //"origin" "1144 912 1384" //} // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m7.ent000066400000000000000000000334131475442401000252010ustar00rootroot00000000000000{ "wad" "gfx/metal.wad" "classname" "worldspawn" "worldtype" "1" "sounds" "7" "message" "The House of Chthon" } { "angle" "0" "origin" "-448 64 56" "classname" "info_player_start" } { "origin" "256 256 80" "classname" "light" } { "classname" "light" "origin" "480 448 256" } { "origin" "488 -320 256" "classname" "light" } { "classname" "light" "origin" "1024 -320 256" } { "origin" "1024 448 256" "classname" "light" } { "classname" "light" "origin" "-280 408 312" } { "origin" "-256 -256 320" "classname" "light" } { "classname" "light" "origin" "832 256 80" } { "origin" "-256 64 120" "classname" "light" } { "classname" "light" "origin" "-512 64 120" } { "origin" "832 -128 80" "classname" "light" } { "classname" "light" "origin" "576 -128 80" } { "origin" "256 -128 80" "classname" "light" } { "classname" "light" "origin" "64 -128 80" } { "origin" "64 256 80" "classname" "light" } { "classname" "light" "origin" "-64 208 80" } { "origin" "-64 -80 80" "classname" "light" } { "origin" "360 -56 80" "classname" "light" } { "classname" "light" "origin" "360 184 80" } { "origin" "864 64 232" "classname" "light" } { "classname" "light" "origin" "-320 64 224" "light" "200" } { "origin" "1024 88 -56" "classname" "light" } { "origin" "0 328 256" "classname" "light" } { "classname" "light" "origin" "0 -200 256" } { "light" "200" "origin" "-128 64 224" "classname" "light" } { "classname" "light" "origin" "64 64 288" "light" "200" } { "classname" "monster_boss" "origin" "304 64 -48" "angle" "180" "targetname" "t4" "target" "t10" } { "light" "300" "origin" "352 64 472" "classname" "light" } { "origin" "-158 354 116" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "-192 384 112" "classname" "light" } { "classname" "light" "origin" "-96 416 112" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "-158 -222 116" } { "classname" "light" "origin" "-192 -256 112" "light" "150" } { "light" "150" "origin" "-96 -288 112" "classname" "light" } { "origin" "1216 64 184" "classname" "light" } { "origin" "930 -222 52" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "922 346 52" } { "classname" "light" "origin" "984 408 56" "light" "150" } { "light" "150" "origin" "984 -280 56" "classname" "light" } { "classname" "light" "origin" "872 -304 56" "light" "150" } { "light" "150" "origin" "872 424 56" "classname" "light" } { "classname" "light" "origin" "1024 40 -56" } { "classname" "light" "origin" "1024 64 -24" "light" "150" } { "classname" "func_plat" "height" "176" "model" "*1" } { "light" "150" "origin" "1024 288 56" "classname" "light" } { "classname" "light" "origin" "1024 -160 56" "light" "150" } { "classname" "light" "origin" "768 352 88" "light" "150" } { "light" "150" "origin" "512 352 88" "classname" "light" } { "classname" "light" "origin" "192 352 88" "light" "150" } { "light" "150" "origin" "64 352 88" "classname" "light" } { "light" "150" "origin" "768 -224 88" "classname" "light" } { "classname" "light" "origin" "512 -224 88" "light" "150" } { "light" "150" "origin" "192 -224 88" "classname" "light" } { "classname" "light" "origin" "64 -224 88" "light" "150" } { "classname" "light" "origin" "80 64 448" } { "origin" "768 64 448" "classname" "light" } { "classname" "light" "origin" "640 64 448" } { "origin" "448 64 448" "classname" "light" } { "classname" "light" "origin" "256 64 448" } { "classname" "weapon_supershotgun" "origin" "-160 64 208" "spawnflags" "1792" } { "classname" "item_health" "origin" "-312 -312 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-312 -280 208" "classname" "item_health" } { "classname" "item_health" "origin" "-280 -312 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-312 408 208" "classname" "item_health" } { "classname" "item_health" "origin" "-312 376 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-280 408 208" "classname" "item_health" } { "classname" "item_health" "origin" "1048 472 192" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "1048 440 192" "classname" "item_health" } { "classname" "item_health" "origin" "1048 -376 192" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "1048 -344 192" "classname" "item_health" } { "classname" "item_shells" "origin" "48 432 32" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "752 432 32" "classname" "item_shells" } { "classname" "item_shells" "origin" "48 -336 32" "spawnflags" "1793" } { "classname" "item_shells" "origin" "752 -336 32" "spawnflags" "1793" } { "classname" "item_rockets" "origin" "1008 -272 192" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "1008 368 192" "classname" "item_rockets" } { "classname" "weapon_supernailgun" "origin" "1120 64 -32" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "344 392 32" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "344 -296 32" "classname" "item_spikes" } { "classname" "weapon_grenadelauncher" "origin" "-392 64 32" "spawnflags" "1792" } { "classname" "func_wall" "spawnflags" "1792" "model" "*2" } { "classname" "info_player_deathmatch" "origin" "704 -360 280" "angle" "90" } { "spawnflags" "1792" "classname" "func_wall" "model" "*3" } { "angle" "90" "origin" "128 -360 280" "classname" "info_player_deathmatch" } { "classname" "func_wall" "spawnflags" "1792" "model" "*4" } { "spawnflags" "1792" "classname" "func_wall" "model" "*5" } { "classname" "info_player_deathmatch" "origin" "128 488 280" "angle" "270" } { "angle" "270" "origin" "704 488 280" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "origin" "-256 64 64" } { "classname" "info_player_deathmatch" "origin" "-256 64 240" "angle" "0" } { "spawnflags" "1792" "classname" "func_wall" "model" "*6" } { "classname" "func_wall" "spawnflags" "1792" "model" "*7" } { "angle" "180" "origin" "1024 64 176" "classname" "info_player_deathmatch" } { "origin" "-480 208 120" "classname" "light" } { "classname" "info_teleport_destination" "origin" "-256 64 224" "targetname" "t8" "angle" "0" "spawnflags" "1792" } { "light" "250" "origin" "712 64 16" "classname" "light" } { "origin" "560 -48 0" "targetname" "t10" "target" "t9" "classname" "trigger_relay" } { "wait" "-1" "spawnflags" "1" "targetname" "t9" "angle" "270" "classname" "func_door" "model" "*8" } { "wait" "-1" "spawnflags" "1" "targetname" "t9" "angle" "90" "classname" "func_door" "model" "*9" } { "light" "200" "classname" "light" "origin" "840 64 -976" } { "classname" "light" "origin" "832 64 -704" } { "classname" "light" "origin" "840 80 -576" } { "classname" "light" "origin" "824 48 -448" } { "classname" "light" "origin" "840 56 -288" } { "classname" "light" "origin" "816 72 -160" } { "light" "150" "origin" "720 112 -920" "classname" "light" } { "classname" "light" "origin" "720 16 -920" "light" "150" } { "target" "t4" "spawnflags" "2049" "origin" "8 64 24" "classname" "item_sigil" } { "light" "200" "origin" "576 184 0" "classname" "light" } { "classname" "light" "origin" "576 -8 0" "light" "200" } { "mangle" "20 315 0" "origin" "-16 384 368" "classname" "info_intermission" } { "classname" "func_door" "spawnflags" "1" "targetname" "t12" "angle" "-1" "lip" "64" "wait" "20" "target" "lightning" "model" "*10" } { "classname" "func_door" "spawnflags" "1" "targetname" "t13" "angle" "-1" "lip" "64" "wait" "20" "target" "lightning" "model" "*11" } { "angle" "-2" "classname" "func_button" "target" "t13" "spawnflags" "2816" "model" "*12" } { "classname" "func_button" "angle" "-2" "target" "t14" "model" "*13" } { "classname" "event_lightning" "origin" "768 -40 224" "targetname" "t14" } { "spawnflags" "1026" "origin" "976 48 -32" "classname" "item_health" } { "light" "250" "origin" "1064 56 -1008" "classname" "light" } { "light" "250" "origin" "662 160 -1044" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "670 -32 -1044" "light" "250" } { "light" "150" "origin" "896 56 -816" "classname" "light" } { "classname" "light" "origin" "760 64 -816" "light" "150" } { "map" "start" "classname" "trigger_changelevel" "target" "t18" "model" "*14" } { "target" "t15" "classname" "trigger_teleport" "model" "*15" } { "targetname" "t15" "angle" "180" "origin" "944 56 -952" "classname" "info_teleport_destination" } { "angle" "0" "origin" "-472 136 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-480 -8 56" "angle" "0" } { "angle" "270" "origin" "-256 208 56" "classname" "info_player_coop" } { "classname" "light" "origin" "224 -320 200" "light" "150" } { "light" "150" "origin" "224 448 200" "classname" "light" } { "spawnflags" "1792" "target" "t9" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*16" } { "classname" "func_button" "angle" "-2" "target" "t13" "spawnflags" "1024" "model" "*17" } { "classname" "func_wall" "spawnflags" "1024" "model" "*18" } { "classname" "func_wall" "spawnflags" "2816" "model" "*19" } { "classname" "item_spikes" "origin" "328 392 32" "spawnflags" "1793" } { "spawnflags" "2816" "classname" "func_button" "angle" "-2" "target" "t12" "model" "*20" } { "spawnflags" "1024" "angle" "-2" "classname" "func_button" "target" "t12" "model" "*21" } { "spawnflags" "1024" "classname" "func_wall" "model" "*22" } { "spawnflags" "2816" "classname" "func_wall" "model" "*23" } { "classname" "monster_shambler" "origin" "1544 344 24" } { "origin" "1632 344 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1848 344 24" } { "origin" "1760 344 24" "classname" "monster_shambler" } { "classname" "trigger_teleport" "targetname" "t17" "target" "t19" "model" "*24" } { "classname" "trigger_teleport" "targetname" "t17" "target" "t20" "model" "*25" } { "classname" "trigger_once" "targetname" "t16" "target" "t27" "delay" "4.8" "model" "*26" } { "classname" "trigger_once" "targetname" "t16" "target" "t22" "delay" "2.8" "model" "*27" } { "classname" "trigger_once" "targetname" "t16" "target" "t17" "delay" "0.2" "model" "*28" } { "classname" "trigger_once" "targetname" "t16" "target" "t21" "delay" "2" "model" "*29" } { "classname" "trigger_relay" "origin" "1512 128 32" "target" "t16" "targetname" "t18" } { "classname" "info_teleport_destination" "origin" "128 192 320" "targetname" "t19" } { "origin" "128 -64 320" "classname" "info_teleport_destination" "targetname" "t20" } { "origin" "1848 224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1760 224 24" } { "origin" "1632 224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1544 224 24" } { "origin" "1848 -224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1760 -224 24" } { "origin" "1632 -224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1544 -224 24" } { "classname" "trigger_teleport" "targetname" "t21" "target" "t25" "model" "*30" } { "classname" "trigger_teleport" "targetname" "t21" "target" "t26" "model" "*31" } { "classname" "trigger_teleport" "targetname" "t22" "target" "t24" "model" "*32" } { "classname" "trigger_teleport" "targetname" "t22" "target" "t23" "model" "*33" } { "classname" "info_teleport_destination" "origin" "352 128 224" "angle" "180" "targetname" "t23" } { "origin" "352 -32 224" "classname" "info_teleport_destination" "angle" "180" "targetname" "t24" } { "classname" "info_teleport_destination" "origin" "576 -96 312" "angle" "180" "targetname" "t26" } { "origin" "672 88 312" "classname" "info_teleport_destination" "angle" "180" "targetname" "t25" } { "classname" "monster_zombie" "origin" "1760 128 24" } { "origin" "1824 128 24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1568 128 24" } { "origin" "1632 128 24" "classname" "monster_zombie" } { "classname" "trigger_teleport" "targetname" "t27" "target" "t29" "model" "*34" } { "classname" "trigger_teleport" "targetname" "t27" "target" "t28" "model" "*35" } { "classname" "info_teleport_destination" "origin" "248 352 216" "angle" "180" "targetname" "t29" } { "classname" "info_teleport_destination" "origin" "560 -224 216" "angle" "180" "targetname" "t28" } { "classname" "monster_zombie" "origin" "1824 64 24" } { "origin" "1760 64 24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1632 64 24" } { "origin" "1568 64 24" "classname" "monster_zombie" } { "classname" "trigger_teleport" "targetname" "t30" "target" "t32" "model" "*36" } { "classname" "trigger_teleport" "targetname" "t30" "target" "t31" "model" "*37" } { "classname" "trigger_once" "targetname" "t16" "target" "t30" "delay" "6.3" "model" "*38" } { "classname" "info_teleport_destination" "origin" "688 352 200" "angle" "180" "targetname" "t31" } { "classname" "info_teleport_destination" "origin" "128 -224 200" "angle" "180" "targetname" "t32" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "targetname" "t9" "spawnflags" "2048" "model" "*39" } { "spawnflags" "1792" "origin" "984 -328 192" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "984 440 192" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "-224 376 192" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "-216 -288 192" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "352 456 32" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "0 64 24" "classname" "item_artifact_super_damage" } // ================================ // begin extra BSP entity list for e1m7 // ================================ { "classname" "item_flag_team1" "origin" "839 62 148" } { "classname" "item_flag_team2" "origin" "-532 57 32" } { "classname" "info_player_team1" "origin" "839 62 164" } { "classname" "info_player_team2" "origin" "-472 -3 56" } { "classname" "info_player_team2" "origin" "-472 57 56" } { "classname" "info_player_team2" "origin" "-472 117 56" } { "classname" "info_player_team2" "origin" "-532 57 56" } { "classname" "info_player_team2" "origin" "-592 57 56" } // ================================ // end extra BSP entity list for e1m7 // ================================QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e1m8.ent000066400000000000000000001101721475442401000252000ustar00rootroot00000000000000{ "sounds" "10" "worldtype" "1" "classname" "worldspawn" "wad" "gfx/metal.wad" "message" "Ziggurat Vertigo" } { "light" "500" "origin" "384 64 -752" "classname" "light" } { "angle" "225" "origin" "1024 720 -104" "classname" "info_player_start" } { "classname" "light" "origin" "128 384 -752" "light" "500" } { "light" "500" "origin" "384 576 -752" "classname" "light" } { "classname" "light" "origin" "960 64 -752" "light" "500" } { "light" "500" "origin" "1216 384 -752" "classname" "light" } { "classname" "light" "origin" "960 704 -704" "light" "200" } { "light" "500" "origin" "960 576 -752" "classname" "light" } { "classname" "light" "origin" "680 704 -704" "light" "200" } { "light" "500" "origin" "680 40 -752" "classname" "light" } { "classname" "light" "origin" "672 376 -752" "light" "500" } { "origin" "136 136 -712" "classname" "light" } { "origin" "136 560 -712" "classname" "light" } { "origin" "1200 568 -712" "classname" "light" } { "classname" "func_plat" "speed" "500" "model" "*1" } { "classname" "light" "origin" "1216 704 -568" "light" "150" } { "classname" "light" "origin" "1216 704 -440" "light" "150" } { "classname" "light" "origin" "1216 704 -312" "light" "150" } { "classname" "light" "origin" "1216 704 -176" "light" "150" } { "classname" "light" "origin" "1216 704 -48" "light" "150" } { "classname" "func_plat" "speed" "500" "model" "*2" } { "classname" "light" "origin" "152 -632 -712" } { "classname" "light" "origin" "128 -704 -568" "light" "150" } { "classname" "light" "origin" "128 -704 -440" "light" "150" } { "classname" "light" "origin" "128 -704 -312" "light" "150" } { "classname" "light" "origin" "128 -704 -176" "light" "150" } { "classname" "light" "origin" "128 -704 -48" "light" "150" } { "speed" "500" "classname" "func_plat" "model" "*3" } { "origin" "1272 -632 -712" "classname" "light" } { "light" "150" "origin" "1248 -704 -568" "classname" "light" } { "light" "150" "origin" "1248 -704 -440" "classname" "light" } { "light" "150" "origin" "1248 -704 -312" "classname" "light" } { "light" "150" "origin" "1248 -704 -176" "classname" "light" } { "light" "150" "origin" "1248 -704 -48" "classname" "light" } { "classname" "light" "origin" "600 -392 64" "light" "400" } { "classname" "light" "origin" "1136 -232 -184" "light" "500" } { "classname" "light" "origin" "992 -96 -744" "light" "500" } { "classname" "light" "origin" "1280 -368 -696" "light" "500" } { "classname" "light" "origin" "416 -104 -704" "light" "500" } { "classname" "light" "origin" "296 -480 -744" "light" "500" } { "light" "300" "origin" "688 -240 -520" "classname" "light" } { "origin" "672 248 -544" "classname" "light" } { "origin" "712 520 96" "classname" "light" } { "origin" "424 -256 -32" "classname" "light" } { "origin" "592 -112 -48" "classname" "light" } { "origin" "144 512 -40" "classname" "light" } { "origin" "464 64 -64" "classname" "light" } { "origin" "888 64 -64" "classname" "light" } { "origin" "624 240 -160" "classname" "light" } { "origin" "472 360 -64" "classname" "light" } { "origin" "880 368 -64" "classname" "light" } { "origin" "64 360 -248" "classname" "light" } { "origin" "360 704 -248" "classname" "light" } { "origin" "416 696 -320" "classname" "weapon_grenadelauncher" "spawnflags" "1792" } { "origin" "48 352 -320" "classname" "item_rockets" } { "origin" "672 80 -496" "classname" "light" } { "spawnflags" "1" "origin" "656 72 -576" "classname" "item_spikes" } { "origin" "1264 -128 -576" "classname" "weapon_rocketlauncher" "spawnflags" "1792" } { "origin" "976 -112 -736" "classname" "item_rockets" } { "origin" "704 -272 256" "classname" "weapon_supershotgun" "spawnflags" "1792" } { "origin" "1248 -736 184" "classname" "item_armor2" } { "origin" "144 -744 192" "classname" "item_health" } { "origin" "80 -744 192" "classname" "item_health" } { "spawnflags" "2" "origin" "656 112 256" "classname" "item_health" } { "origin" "24 -136 -624" "classname" "item_health" } { "origin" "80 -136 -624" "classname" "item_health" } { "origin" "24 40 -624" "classname" "item_health" } { "origin" "80 40 -624" "classname" "item_health" } { "origin" "1164 176 0" "classname" "item_spikes" "spawnflags" "1" } { "origin" "864 208 0" "classname" "item_health" } { "classname" "item_health" "origin" "560 224 0" } { "origin" "608 224 0" "classname" "item_health" } { "origin" "96 528 152" "classname" "weapon_supernailgun" "spawnflags" "1792" } { "spawnflags" "1" "origin" "1200 728 192" "classname" "item_spikes" } { "origin" "1216 64 216" "classname" "item_armor2" "spawnflags" "3584" } { "light" "200" "origin" "320 128 88" "classname" "light" } { "light" "200" "origin" "320 352 88" "classname" "light" } { "spawnflags" "1792" "origin" "320 72 0" "classname" "weapon_nailgun" } { "origin" "672 192 112" "classname" "light" } { "spawnflags" "2" "origin" "688 -856 -368" "classname" "item_health" } { "origin" "720 -720 48" "classname" "weapon_rocketlauncher" "spawnflags" "1536" } { "origin" "672 -160 -128" "classname" "item_health" } { "origin" "608 -160 -128" "classname" "item_health" } { "angle" "0" "origin" "1000 -136 -712" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "384 -256 -712" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "672 48 -552" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "880 128 24" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "672 720 -688" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "720 -656 -712" "classname" "info_player_deathmatch" } { "origin" "56 -136 -736" "classname" "item_shells" } { "origin" "880 -720 -736" "classname" "item_shells" } { "origin" "32 704 -736" "classname" "item_shells" } { "origin" "1280 152 -576" "classname" "item_shells" } { "origin" "1264 -288 -576" "classname" "item_shells" } { "spawnflags" "1" "origin" "128 -168 -320" "classname" "item_spikes" } { "origin" "176 -144 -320" "classname" "item_rockets" } { "light" "200" "origin" "1144 -232 88" "classname" "light" } { "light" "200" "origin" "1032 88 88" "classname" "light" } { "origin" "984 512 152" "classname" "item_rockets" } { "origin" "1248 -144 152" "classname" "item_shells" } { "classname" "light" "origin" "448 696 -704" "light" "200" } { "classname" "light" "origin" "296 32 -704" "light" "200" } { "classname" "light" "origin" "536 32 -648" "light" "200" } { "classname" "light" "origin" "832 32 -648" "light" "200" } { "spawnflags" "2048" "targetname" "t2" "classname" "func_door" "angle" "-1" "wait" "-1" "message" "These bars are opened elsewhere..." "sounds" "4" "model" "*4" } { "message" "These bars are opened elsewhere..." "targetname" "t2" "classname" "func_door" "angle" "-1" "wait" "-1" "sounds" "4" "spawnflags" "2048" "model" "*5" } { "light" "200" "origin" "672 256 -408" "classname" "light" } { "classname" "light" "origin" "64 264 -352" "light" "200" } { "classname" "light" "origin" "504 712 -352" "light" "200" } { "classname" "light" "origin" "1024 360 64" "light" "200" } { "classname" "light" "origin" "88 528 64" "light" "200" } { "angle" "90" "origin" "272 40 -96" "classname" "monster_ogre" } { "lip" "0" "speed" "400" "wait" "-1" "angle" "270" "classname" "func_door" "model" "*6" } { "light" "150" "origin" "64 -56 -680" "classname" "light" } { "light" "150" "origin" "672 0 -632" "classname" "light" } { "angle" "270" "origin" "1216 488 24" "classname" "monster_ogre" } { "angle" "90" "origin" "1024 368 24" "classname" "monster_ogre" } { "wait" "-1" "target" "t2" "angle" "270" "classname" "func_button" "spawnflags" "2048" "model" "*7" } { "light" "150" "origin" "672 48 312" "classname" "light" } { "light" "200" "origin" "1040 656 -88" "classname" "light" } { "light" "200" "origin" "1320 360 -256" "classname" "light" } { "speed" "150" "origin" "320 -136 -776" "classname" "misc_fireball" "spawnflags" "2048" } { "speed" "150" "origin" "832 536 -752" "classname" "misc_fireball" "spawnflags" "2048" } { "speed" "150" "origin" "1048 416 -752" "classname" "misc_fireball" "spawnflags" "2048" } { "classname" "misc_fireball" "origin" "576 576 -752" "speed" "150" "spawnflags" "2048" } { "speed" "150" "origin" "392 536 -752" "classname" "misc_fireball" "spawnflags" "2048" } { "classname" "misc_fireball" "origin" "296 336 -752" "speed" "150" "spawnflags" "2048" } { "angle" "0" "origin" "80 520 24" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "90" "origin" "592 240 280" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "752 240 280" "angle" "90" } { "spawnflags" "256" "angle" "90" "origin" "328 200 176" "classname" "monster_ogre" "target" "t41" } { "classname" "monster_ogre" "origin" "1024 88 176" "angle" "90" "target" "t43" } { "spawnflags" "256" "angle" "225" "origin" "1216 680 216" "classname" "monster_ogre" } { "origin" "800 -720 -288" "classname" "light" } { "spawnflags" "769" "angle" "225" "origin" "848 -144 -552" "classname" "monster_ogre" } { "angle" "315" "origin" "560 -144 -552" "classname" "monster_ogre" } { "angle" "225" "origin" "848 -144 -712" "classname" "monster_ogre" "spawnflags" "256" } { "light" "500" "origin" "128 -248 48" "classname" "light" } { "light" "200" "origin" "544 -224 -320" "classname" "light" } { "light" "200" "origin" "776 -224 -320" "classname" "light" } { "light" "150" "origin" "720 -680 -704" "classname" "light" } { "light" "150" "origin" "728 -504 -704" "classname" "light" } { "light" "150" "origin" "864 -704 -704" "classname" "light" } { "classname" "light" "origin" "312 -704 -704" "light" "150" } { "light" "150" "origin" "72 -128 -584" "classname" "light" } { "classname" "light" "origin" "64 56 -584" "light" "150" } { "message" "These bars are opened elsewhere..." "angle" "-1" "targetname" "t3" "wait" "-1" "classname" "func_door" "sounds" "4" "spawnflags" "2048" "model" "*8" } { "message" "These bars are opened elsewhere..." "targetname" "t3" "wait" "-1" "angle" "-1" "classname" "func_door" "sounds" "4" "spawnflags" "2048" "model" "*9" } { "target" "t3" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*10" } { "light" "200" "origin" "544 -304 -528" "classname" "light" } { "light" "150" "origin" "880 120 32" "classname" "light" } { "origin" "672 536 -712" "classname" "item_artifact_invulnerability" } { "classname" "item_artifact_invulnerability" "origin" "64 -176 -288" "spawnflags" "256" } { "classname" "func_button" "angle" "90" "target" "t4" "wait" "-1" "spawnflags" "2048" "model" "*11" } { "classname" "monster_shambler" "origin" "608 -424 280" "angle" "315" "target" "t35" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "720 -664 80" "angle" "0" } { "classname" "monster_ogre" "origin" "448 -672 -104" "angle" "0" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "72 -256 -296" "angle" "315" } { "classname" "monster_ogre" "origin" "184 -512 24" "angle" "0" "target" "t51" } { "classname" "monster_ogre" "origin" "472 -384 -104" "angle" "270" "spawnflags" "256" "target" "t50" } { "classname" "monster_ogre" "origin" "736 -448 72" "angle" "270" } { "origin" "1512 -240 64" "classname" "light" } { "origin" "1608 -240 64" "classname" "light" } { "light" "150" "origin" "1360 -240 64" "classname" "light" } { "angle" "270" "origin" "1264 -320 24" "classname" "monster_ogre" "spawnflags" "256" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "1008 -248 24" "angle" "90" "target" "t54" } { "spawnflags" "1" "angle" "270" "origin" "1024 88 24" "classname" "monster_ogre" } { "map" "e1m5" "classname" "trigger_changelevel" "model" "*12" } { "wait" "-1" "angle" "90" "targetname" "t4" "classname" "func_door" "sounds" "1" "message" "This door is opened elsewhere..." "spawnflags" "2048" "model" "*13" } { "spawnflags" "2048" "targetname" "t4" "wait" "-1" "angle" "180" "classname" "func_door" "sounds" "1" "message" "This door is opened elsewhere..." "model" "*14" } { "targetname" "t4" "wait" "-1" "angle" "-1" "classname" "func_door" "message" "This door is opened elsewhere..." "spawnflags" "2048" "model" "*15" } { "light" "400" "angle" "90" "target" "t7" "origin" "48 592 160" "classname" "light" } { "light" "400" "angle" "90" "target" "t8" "origin" "48 464 160" "classname" "light" } { "targetname" "t7" "origin" "12 596 540" "classname" "info_null" } { "targetname" "t8" "classname" "info_null" "origin" "12 468 540" } { "light" "200" "origin" "48 520 192" "classname" "light" } { "light" "400" "target" "t10" "angle" "90" "origin" "272 48 160" "classname" "light" } { "light" "400" "target" "t9" "angle" "90" "classname" "light" "origin" "368 48 160" } { "targetname" "t10" "origin" "276 12 540" "classname" "info_null" } { "targetname" "t9" "classname" "info_null" "origin" "364 12 540" } { "classname" "light" "origin" "320 64 192" "light" "200" } { "target" "t11" "angle" "90" "light" "400" "origin" "560 272 264" "classname" "light" } { "target" "t12" "angle" "90" "classname" "light" "origin" "784 272 264" "light" "400" } { "targetname" "t11" "origin" "548 284 556" "classname" "info_null" } { "targetname" "t12" "classname" "info_null" "origin" "796 284 556" } { "target" "t13" "angle" "90" "light" "400" "origin" "976 16 160" "classname" "light" } { "target" "t14" "angle" "90" "classname" "light" "origin" "1072 16 160" "light" "400" } { "light" "200" "origin" "1024 40 192" "classname" "light" } { "targetname" "t13" "origin" "972 4 540" "classname" "info_null" } { "targetname" "t14" "classname" "info_null" "origin" "1076 4 540" } { "target" "t16" "angle" "90" "light" "400" "origin" "1136 16 224" "classname" "light" } { "angle" "90" "target" "t15" "classname" "light" "origin" "1296 16 224" } { "origin" "1216 32 256" "classname" "light" } { "targetname" "t16" "origin" "1140 4 540" "classname" "info_null" } { "targetname" "t15" "classname" "info_null" "origin" "1292 4 540" } { "light" "200" "origin" "672 264 296" "classname" "light" } { "light" "400" "target" "t17" "angle" "90" "origin" "1168 752 200" "classname" "light" } { "light" "400" "angle" "90" "target" "t18" "classname" "light" "origin" "1264 752 200" } { "light" "200" "origin" "1216 720 264" "classname" "light" } { "targetname" "t17" "origin" "1164 764 548" "classname" "info_null" } { "targetname" "t18" "classname" "info_null" "origin" "1268 764 548" } { "target" "t19" "angle" "90" "light" "400" "origin" "1072 464 160" "classname" "light" } { "target" "t20" "angle" "90" "classname" "light" "origin" "1072 592 160" "light" "400" } { "light" "200" "origin" "1048 528 200" "classname" "light" } { "targetname" "t20" "origin" "1084 580 548" "classname" "info_null" } { "targetname" "t19" "classname" "info_null" "origin" "1084 476 548" } { "target" "t22" "angle" "90" "light" "400" "origin" "624 16 400" "classname" "light" } { "target" "t21" "angle" "90" "classname" "light" "origin" "720 16 400" "light" "400" } { "light" "200" "origin" "672 40 440" "classname" "light" } { "targetname" "t22" "origin" "612 4 556" "classname" "info_null" } { "targetname" "t21" "classname" "info_null" "origin" "732 4 556" } { "target" "t23" "angle" "90" "origin" "272 752 16" "classname" "light" } { "target" "t24" "classname" "light" "origin" "496 752 16" "angle" "90" } { "target" "t25" "angle" "90" "origin" "688 752 16" "classname" "light" } { "target" "t26" "classname" "light" "origin" "880 752 16" "angle" "90" } { "target" "t27" "angle" "90" "origin" "1104 752 16" "classname" "light" } { "targetname" "t27" "origin" "1092 764 516" "classname" "info_null" } { "targetname" "t26" "classname" "info_null" "origin" "868 764 516" } { "targetname" "t25" "origin" "700 764 516" "classname" "info_null" } { "targetname" "t24" "classname" "info_null" "origin" "508 764 516" } { "targetname" "t23" "origin" "284 764 516" "classname" "info_null" } { "light" "150" "origin" "304 720 32" "classname" "light" } { "classname" "light" "origin" "472 720 32" "light" "150" } { "light" "150" "origin" "664 712 32" "classname" "light" } { "classname" "light" "origin" "848 720 32" "light" "150" } { "light" "150" "origin" "1072 720 32" "classname" "light" } { "light" "175" "origin" "96 728 504" "classname" "light" } { "classname" "light" "origin" "224 728 504" "light" "175" } { "light" "175" "origin" "352 728 504" "classname" "light" } { "classname" "light" "origin" "480 728 504" "light" "175" } { "light" "175" "origin" "608 728 504" "classname" "light" } { "classname" "light" "origin" "736 728 504" "light" "175" } { "light" "175" "origin" "872 728 504" "classname" "light" } { "classname" "light" "origin" "992 728 504" "light" "175" } { "light" "175" "origin" "1112 728 504" "classname" "light" } { "classname" "light" "origin" "1224 728 504" "light" "175" } { "classname" "light" "origin" "40 576 504" "light" "175" } { "light" "175" "origin" "40 464 504" "classname" "light" } { "classname" "light" "origin" "40 384 504" "light" "175" } { "light" "175" "origin" "40 280 504" "classname" "light" } { "classname" "light" "origin" "40 160 504" "light" "175" } { "light" "175" "origin" "40 72 504" "classname" "light" } { "light" "175" "origin" "1304 632 504" "classname" "light" } { "classname" "light" "origin" "1304 536 504" "light" "175" } { "light" "175" "origin" "1304 456 504" "classname" "light" } { "classname" "light" "origin" "1304 360 504" "light" "175" } { "light" "175" "origin" "1304 256 504" "classname" "light" } { "classname" "light" "origin" "1304 136 504" "light" "175" } { "classname" "light" "origin" "1024 192 192" "light" "200" } { "light" "200" "origin" "1024 376 192" "classname" "light" } { "classname" "light" "origin" "120 88 536" "light" "175" } { "light" "175" "origin" "128 192 536" "classname" "light" } { "classname" "light" "origin" "128 320 536" "light" "175" } { "light" "175" "origin" "128 416 536" "classname" "light" } { "classname" "light" "origin" "128 600 536" "light" "175" } { "light" "175" "origin" "256 640 536" "classname" "light" } { "classname" "light" "origin" "448 640 536" "light" "175" } { "light" "175" "origin" "640 640 536" "classname" "light" } { "classname" "light" "origin" "832 640 536" "light" "175" } { "light" "175" "origin" "960 640 536" "classname" "light" } { "classname" "light" "origin" "1120 640 536" "light" "175" } { "light" "175" "origin" "1232 576 536" "classname" "light" } { "classname" "light" "origin" "1240 448 536" "light" "175" } { "light" "175" "origin" "1240 320 536" "classname" "light" } { "classname" "light" "origin" "1240 184 536" "light" "175" } { "light" "175" "origin" "1240 48 536" "classname" "light" } { "classname" "light" "origin" "872 560 192" "light" "200" } { "light" "200" "origin" "688 568 192" "classname" "light" } { "classname" "light" "origin" "512 568 192" "light" "200" } { "light" "200" "origin" "320 512 192" "classname" "light" } { "classname" "light" "origin" "320 320 192" "light" "200" } { "mangle" "30 315 0" "origin" "144 592 -112" "classname" "info_intermission" } { "classname" "info_player_coop" "origin" "824 720 -712" "angle" "270" } { "angle" "270" "origin" "880 720 -712" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "568 720 -712" "angle" "270" } { "origin" "672 312 -736" "classname" "item_armor2" } { "origin" "264 96 0" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "344 96 0" } { "spawnflags" "1" "origin" "264 256 0" "classname" "item_health" } { "classname" "item_health" "origin" "264 208 0" "spawnflags" "1" } { "light" "250" "origin" "1200 368 56" "classname" "light" } { "light" "200" "origin" "1216 200 72" "classname" "light" } { "light" "150" "origin" "152 696 72" "classname" "light" } { "classname" "light" "origin" "232 696 72" "light" "150" } { "light" "175" "origin" "192 680 240" "classname" "light" } { "light" "200" "origin" "1216 560 80" "classname" "light" } { "classname" "light" "origin" "1216 696 80" "light" "150" } { "light" "250" "origin" "944 80 24" "classname" "light" } { "classname" "light" "origin" "976 240 24" "light" "250" } { "light" "250" "origin" "1296 -112 24" "classname" "light" } { "classname" "light" "origin" "944 -368 24" "light" "250" } { "light" "250" "origin" "1296 -368 24" "classname" "light" } { "light" "250" "origin" "944 -80 24" "classname" "light" } { "light" "150" "origin" "1472 -168 64" "classname" "light" } { "classname" "light" "origin" "1480 -304 64" "light" "150" } { "classname" "info_null" "origin" "1332 -596 540" } { "origin" "1332 -468 540" "classname" "info_null" } { "classname" "light" "origin" "1248 -728 504" "light" "175" } { "light" "175" "origin" "1120 -728 504" "classname" "light" } { "classname" "light" "origin" "992 -728 504" "light" "175" } { "light" "175" "origin" "864 -728 504" "classname" "light" } { "classname" "light" "origin" "736 -728 504" "light" "175" } { "light" "175" "origin" "608 -728 504" "classname" "light" } { "classname" "light" "origin" "472 -728 504" "light" "175" } { "light" "175" "origin" "352 -728 504" "classname" "light" } { "classname" "light" "origin" "232 -728 504" "light" "175" } { "light" "175" "origin" "120 -728 504" "classname" "light" } { "light" "175" "origin" "1304 -576 504" "classname" "light" } { "classname" "light" "origin" "1304 -464 504" "light" "175" } { "light" "175" "origin" "1304 -384 504" "classname" "light" } { "classname" "light" "origin" "1304 -280 504" "light" "175" } { "light" "175" "origin" "1304 -160 504" "classname" "light" } { "classname" "light" "origin" "40 -632 504" "light" "175" } { "light" "175" "origin" "40 -536 504" "classname" "light" } { "classname" "light" "origin" "40 -456 504" "light" "175" } { "light" "175" "origin" "40 -360 504" "classname" "light" } { "classname" "light" "origin" "40 -256 504" "light" "175" } { "light" "175" "origin" "40 -136 504" "classname" "light" } { "classname" "light" "origin" "1216 -192 536" "light" "175" } { "light" "175" "origin" "1216 -320 536" "classname" "light" } { "classname" "light" "origin" "1216 -416 536" "light" "175" } { "light" "175" "origin" "1216 -600 536" "classname" "light" } { "classname" "light" "origin" "1088 -640 536" "light" "175" } { "light" "175" "origin" "896 -640 536" "classname" "light" } { "classname" "light" "origin" "704 -640 536" "light" "175" } { "light" "175" "origin" "512 -640 536" "classname" "light" } { "classname" "light" "origin" "384 -640 536" "light" "175" } { "light" "175" "origin" "224 -640 536" "classname" "light" } { "classname" "light" "origin" "112 -576 536" "light" "175" } { "light" "175" "origin" "104 -448 536" "classname" "light" } { "classname" "light" "origin" "104 -320 536" "light" "175" } { "light" "175" "origin" "104 -184 536" "classname" "light" } { "classname" "light" "origin" "400 -112 288" "light" "300" "target" "t28" } { "light" "250" "origin" "400 -560 288" "classname" "light" } { "classname" "light" "origin" "784 -560 288" "light" "250" } { "light" "300" "origin" "784 -120 288" "classname" "light" "target" "t29" } { "classname" "light" "origin" "592 -352 408" "light" "300" } { "classname" "info_null" "origin" "400 -80 372" "targetname" "t28" } { "origin" "784 -80 372" "classname" "info_null" "targetname" "t29" } { "classname" "light" "origin" "592 -184 304" "light" "150" } { "classname" "light" "origin" "736 -128 -80" "light" "150" } { "classname" "light" "origin" "784 -88 40" "light" "200" } { "classname" "light" "origin" "760 -528 96" "light" "150" } { "classname" "light" "origin" "944 -112 188" "light" "250" } { "light" "250" "origin" "944 -368 188" "classname" "light" } { "classname" "light" "origin" "1296 -368 188" "light" "250" } { "light" "250" "origin" "1296 -112 188" "classname" "light" } { "classname" "light" "origin" "1168 -444 136" "light" "150" } { "light" "150" "origin" "1328 -442 136" "classname" "light" } { "classname" "light" "origin" "784 -120 288" "light" "200" } { "classname" "light" "origin" "400 -112 288" "light" "200" } { "classname" "light" "origin" "888 -512 48" "light" "250" } { "classname" "light" "origin" "1040 -512 48" "light" "200" } { "classname" "light" "origin" "720 -720 88" "light" "250" } { "classname" "light" "origin" "448 -688 -56" "light" "200" } { "classname" "light" "origin" "232 -560 288" } { "classname" "light" "origin" "448 -688 128" "light" "250" } { "origin" "1264 -488 -128" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "1216 -488 -128" } { "classname" "light" "origin" "1240 -512 -88" "light" "150" } { "light" "150" "origin" "1088 -512 -88" "classname" "light" } { "classname" "light" "origin" "768 -496 -64" "light" "150" } { "classname" "light" "origin" "1300 -748 212" "light" "250" } { "classname" "light" "origin" "1136 -704 76" "light" "250" } { "classname" "light" "origin" "304 -680 -232" "light" "225" } { "light" "225" "origin" "424 -680 -232" "classname" "light" } { "classname" "item_health" "origin" "432 -240 256" } { "origin" "432 -296 256" "classname" "item_health" } { "classname" "item_spikes" "origin" "80 560 152" } { "classname" "light" "origin" "32 720 128" "light" "150" } { "classname" "light" "origin" "672 344 224" "light" "150" } { "light" "150" "origin" "800 344 224" "classname" "light" } { "light" "150" "origin" "544 344 224" "classname" "light" } { "classname" "light" "origin" "480 256 224" "light" "150" } { "light" "150" "origin" "480 152 224" "classname" "light" } { "classname" "light" "origin" "480 48 224" "light" "150" } { "light" "150" "origin" "864 288 224" "classname" "light" } { "classname" "light" "origin" "864 200 224" "light" "150" } { "light" "150" "origin" "864 88 224" "classname" "light" } { "classname" "light" "origin" "32 720 -248" "light" "150" } { "classname" "item_health" "origin" "48 720 -320" } { "origin" "96 720 -320" "classname" "item_health" } { "classname" "item_shells" "origin" "48 400 -320" "spawnflags" "2049" } { "classname" "item_health" "origin" "1088 -304 -576" } { "origin" "1040 -304 -576" "classname" "item_health" } { "classname" "item_health" "origin" "848 -328 -736" "spawnflags" "3073" } { "spawnflags" "3073" "origin" "848 -280 -736" "classname" "item_health" } { "classname" "item_health" "origin" "1248 -192 152" } { "origin" "1248 -240 152" "classname" "item_health" "spawnflags" "3072" } { "classname" "item_spikes" "origin" "280 -488 0" "spawnflags" "2049" } { "classname" "light" "origin" "856 -144 -664" "light" "150" } { "light" "150" "origin" "856 -312 -664" "classname" "light" } { "classname" "light" "origin" "528 -296 -664" "light" "150" } { "light" "150" "origin" "520 -160 -664" "classname" "light" } { "classname" "light" "origin" "1208 104 56" "light" "150" } { "classname" "light" "origin" "1328 56 40" "light" "200" } { "classname" "light" "origin" "1328 16 -528" "light" "200" } { "light" "200" "origin" "1272 160 -488" "classname" "light" } { "classname" "light" "origin" "1176 72 -488" "light" "200" } { "light" "200" "origin" "1104 248 -488" "classname" "light" } { "classname" "light" "origin" "1200 208 -672" "light" "150" } { "light" "150" "origin" "1096 112 -672" "classname" "light" } { "classname" "item_spikes" "origin" "1280 112 -576" } { "classname" "func_wall" "spawnflags" "2048" "model" "*16" } { "classname" "weapon_rocketlauncher" "origin" "672 360 0" "spawnflags" "2048" } { "classname" "light" "origin" "1240 -584 112" } { "origin" "1168 -488 -128" "classname" "item_spikes" "spawnflags" "3072" } { "classname" "func_door" "angle" "0" "wait" "-1" "sounds" "1" "spawnflags" "2064" "model" "*17" } { "classname" "func_door" "angle" "180" "wait" "-1" "spawnflags" "2064" "model" "*18" } { "classname" "item_key1" "origin" "672 152 52" "target" "t33" "spawnflags" "2048" } { "targetname" "t33" "classname" "trigger_teleport" "spawnflags" "2" "target" "t34" "model" "*19" } { "targetname" "t33" "spawnflags" "258" "classname" "trigger_teleport" "target" "t31" "model" "*20" } { "targetname" "t33" "classname" "trigger_teleport" "spawnflags" "2" "target" "t30" "model" "*21" } { "classname" "info_teleport_destination" "origin" "720 -216 96" "targetname" "t30" "angle" "90" } { "classname" "info_teleport_destination" "origin" "552 -280 96" "targetname" "t31" "spawnflags" "256" "angle" "90" } { "classname" "monster_wizard" "origin" "608 -1008 40" "angle" "90" "spawnflags" "256" "targetname" "t33" } { "angle" "90" "origin" "680 -1008 40" "classname" "monster_wizard" "targetname" "t33" } { "classname" "monster_wizard" "origin" "552 -1008 40" "angle" "90" "targetname" "t33" } { "classname" "info_teleport_destination" "origin" "536 -472 -24" "angle" "90" "targetname" "t34" } { "classname" "item_spikes" "origin" "760 40 0" } { "classname" "item_health" "origin" "1120 48 -576" } { "classname" "item_health" "origin" "1048 616 -736" "spawnflags" "3584" } { "classname" "light" "origin" "160 88 144" "light" "200" } { "light" "200" "origin" "168 256 144" "classname" "light" } { "classname" "light" "origin" "120 360 144" "light" "200" } { "classname" "light" "origin" "752 120 328" "light" "150" } { "light" "150" "origin" "592 120 328" "classname" "light" } { "classname" "path_corner" "origin" "448 -512 264" "targetname" "t35" "target" "t36" } { "origin" "736 -520 264" "classname" "path_corner" "targetname" "t36" "target" "t37" } { "classname" "path_corner" "origin" "736 -336 264" "targetname" "t37" "target" "t38" } { "origin" "440 -336 264" "classname" "path_corner" "targetname" "t38" "target" "t35" } { "classname" "path_corner" "origin" "1008 -232 160" "spawnflags" "768" "targetname" "t39" "target" "t40" } { "spawnflags" "768" "origin" "1208 -232 160" "classname" "path_corner" "targetname" "t40" "target" "t39" } { "classname" "monster_shambler" "origin" "1120 -224 176" "spawnflags" "768" "target" "t39" } { "classname" "path_corner" "origin" "328 440 160" "targetname" "t42" "target" "t41" "spawnflags" "256" } { "origin" "328 240 160" "classname" "path_corner" "targetname" "t41" "target" "t42" "spawnflags" "256" } { "classname" "path_corner" "origin" "1024 152 160" "targetname" "t43" "target" "t44" } { "origin" "1016 416 160" "classname" "path_corner" "targetname" "t44" "target" "t43" } { "classname" "path_corner" "origin" "536 -128 -384" "targetname" "t47" "target" "t48" "spawnflags" "256" } { "origin" "544 -288 -384" "classname" "path_corner" "targetname" "t46" "target" "t47" "spawnflags" "256" } { "origin" "816 -144 -384" "classname" "path_corner" "targetname" "t48" "target" "t45" "spawnflags" "256" } { "classname" "path_corner" "origin" "816 -296 -384" "targetname" "t45" "target" "t46" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "704 -160 -368" "angle" "270" "spawnflags" "256" "target" "t45" } { "classname" "item_spikes" "origin" "608 -240 -392" "spawnflags" "1" } { "spawnflags" "2817" "origin" "664 -240 -392" "classname" "item_spikes" } { "classname" "path_corner" "origin" "464 -304 -120" "targetname" "t49" "target" "t50" } { "origin" "464 -472 -120" "classname" "path_corner" "target" "t49" "targetname" "t50" } { "classname" "path_corner" "origin" "272 -512 8" "targetname" "t51" "target" "t52" } { "origin" "88 -512 8" "classname" "path_corner" "targetname" "t52" "target" "t51" } { "classname" "light" "origin" "128 -680 96" } { "classname" "info_intermission" "origin" "1232 -656 464" "mangle" "20 140 0" } { "classname" "path_corner" "origin" "1008 -320 8" "target" "t53" "targetname" "t54" "spawnflags" "256" } { "origin" "1008 -128 8" "classname" "path_corner" "targetname" "t53" "target" "t54" "spawnflags" "256" } { "classname" "item_spikes" "origin" "1272 -520 0" } { "classname" "func_door_secret" "angle" "270" "spawnflags" "3" "model" "*22" } { "classname" "trigger_secret" "model" "*23" } { "spawnflags" "1" "classname" "item_spikes" "origin" "1216 176 0" } { "classname" "item_artifact_invisibility" "origin" "1208 92 24" "spawnflags" "1792" } { "light" "150" "origin" "624 968 -672" "classname" "light" } { "classname" "light" "origin" "720 968 -672" "light" "150" } { "light" "150" "origin" "776 808 -672" "classname" "light" } { "classname" "light" "origin" "568 808 -672" "light" "150" } { "light" "250" "origin" "664 832 -744" "classname" "light" } { "light" "150" "origin" "672 832 -888" "classname" "light" } { "classname" "light" "origin" "672 728 -888" "light" "150" } { "light" "150" "origin" "672 608 -888" "classname" "light" } { "classname" "trigger_secret" "model" "*24" } { "origin" "672 920 -728" "classname" "item_artifact_super_damage" } { "origin" "768 976 -752" "classname" "item_health" } { "classname" "item_health" "origin" "552 984 -752" } { "targetname" "t55" "angle" "270" "origin" "672 720 -720" "classname" "info_teleport_destination" } { "target" "t55" "classname" "trigger_teleport" "model" "*25" } { "classname" "light" "origin" "1024 728 -120" "light" "150" } { "classname" "monster_ogre" "origin" "600 -496 280" "spawnflags" "1536" "angle" "0" "target" "t35" } { "classname" "path_corner" "origin" "144 -264 -728" "spawnflags" "768" "targetname" "t56" "target" "t57" } { "spawnflags" "768" "origin" "320 -264 -728" "classname" "path_corner" "targetname" "t57" "target" "t56" } { "classname" "monster_ogre" "origin" "240 -256 -712" "angle" "180" "spawnflags" "768" "target" "t56" } { "classname" "path_corner" "origin" "808 -696 -728" "targetname" "t59" "target" "t58" "spawnflags" "768" } { "origin" "504 -696 -728" "classname" "path_corner" "targetname" "t58" "target" "t59" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "552 -696 -712" "angle" "180" "spawnflags" "768" "target" "t58" } { "spawnflags" "1792" "classname" "func_wall" "model" "*26" } { "classname" "func_wall" "spawnflags" "2048" "model" "*27" } { "spawnflags" "1792" "origin" "672 256 -472" "classname" "weapon_supernailgun" } { "target" "t45" "spawnflags" "768" "angle" "270" "origin" "816 -240 -368" "classname" "monster_shambler" } { "angle" "225" "origin" "1312 728 392" "classname" "monster_wizard" "spawnflags" "256" } { "angle" "315" "origin" "32 728 392" "classname" "monster_wizard" } { "target" "t61" "targetname" "t60" "origin" "1208 -144 256" "classname" "path_corner" } { "targetname" "t61" "target" "t60" "classname" "path_corner" "origin" "1032 -400 256" } { "target" "t61" "angle" "225" "origin" "1144 -216 272" "classname" "monster_wizard" } { "spawnflags" "256" "targetname" "t63" "target" "t62" "origin" "288 -136 128" "classname" "path_corner" } { "spawnflags" "256" "target" "t63" "targetname" "t62" "classname" "path_corner" "origin" "288 -336 128" } { "spawnflags" "256" "target" "t62" "origin" "280 -384 144" "classname" "monster_wizard" } { "classname" "item_health" "origin" "1160 48 216" "spawnflags" "2305" } { "classname" "light" "origin" "1024 720 -744" "light" "125" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "592 -150 300" "classname" "item_flag_team1" "angle" "180" } { "angle" "270" "origin" "492 -220 280" "classname" "info_player_team1" } { "angle" "270" "origin" "592 -220 280" "classname" "info_player_team1" } { "angle" "270" "origin" "692 -220 280" "classname" "info_player_team1" } { "angle" "270" "origin" "492 -320 280" "classname" "info_player_team1" } { "angle" "270" "origin" "592 -320 280" "classname" "info_player_team1" } { "angle" "270" "origin" "692 -320 280" "classname" "info_player_team1" } // base one weapons upgrade { "classname" "item_health" "origin" "542 -400 280" } { "origin" "592 -400 280" "classname" "item_health" } { "classname" "item_health" "origin" "642 -400 280" } { "origin" "542 -450 280" "classname" "item_shells" } { "origin" "592 -450 280" "classname" "item_shells" } { "origin" "642 -450 280" "classname" "item_shells" } { "origin" "542 -500 280" "classname" "item_spikes" } { "origin" "592 -500 280" "classname" "item_spikes" } { "origin" "642 -500 280" "classname" "item_spikes" } { "origin" "542 -550 280" "classname" "weapon_supershotgun" } { "origin" "592 -550 280" "classname" "item_armor2" } { "origin" "642 -550 280" "classname" "weapon_supernailgun" } // team2 { "origin" "672 132 300" "classname" "item_flag_team2" } { "angle" "0" "origin" "572 200 280" "classname" "info_player_team2" } { "angle" "0" "origin" "672 200 280" "classname" "info_player_team2" } { "angle" "0" "origin" "772 200 280" "classname" "info_player_team2" } { "angle" "0" "origin" "572 300 280" "classname" "info_player_team2" } { "angle" "0" "origin" "672 300 280" "classname" "info_player_team2" } { "angle" "0" "origin" "772 300 280" "classname" "info_player_team2" } // base two weapons upgrade { "classname" "item_health" "origin" "622 420 280" } { "classname" "item_health" "origin" "672 420 280" } { "classname" "item_health" "origin" "722 420 280" } { "origin" "622 470 280" "classname" "item_shells" } { "origin" "672 470 280" "classname" "item_shells" } { "origin" "722 470 280" "classname" "item_shells" } { "origin" "622 520 280" "classname" "item_spikes" } { "origin" "672 520 280" "classname" "item_spikes" } { "origin" "722 520 280" "classname" "item_spikes" } { "origin" "622 570 280" "classname" "weapon_supershotgun" } { "origin" "672 570 280" "classname" "item_armor2" } { "origin" "722 570 280" "classname" "weapon_supernailgun" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m1.ent000066400000000000000000001043341475442401000251750ustar00rootroot00000000000000{ "message" "the Installation" "sounds" "6" "worldtype" "2" "wad" "gfx/base.wad" "classname" "worldspawn" } { "light" "220" "origin" "576 120 40" "classname" "light" } { "angle" "90" "origin" "544 -808 72" "classname" "info_player_start" } { "light" "300" "origin" "576 -192 136" "classname" "light" } { "light" "200" "origin" "800 400 64" "classname" "light" } { "light" "250" "origin" "576 232 -184" "classname" "light" } { "light" "150" "origin" "576 448 -184" "classname" "light" } { "light" "200" "origin" "736 400 -56" "classname" "light" } { "light" "200" "origin" "736 560 -56" "classname" "light" } { "light" "200" "origin" "704 256 -56" "classname" "light" } { "light" "200" "origin" "448 256 -56" "classname" "light" } { "light" "300" "origin" "576 320 152" "classname" "light" } { "light" "300" "origin" "576 576 152" "classname" "light" } { "origin" "992 -96 264" "classname" "light" } { "light" "200" "origin" "784 -192 160" "classname" "light" } { "origin" "1224 -104 208" "classname" "light" "light" "170" } { "light" "200" "origin" "992 -104 96" "classname" "light" } { "light" "150" "origin" "1216 192 40" "classname" "light" } { "classname" "light" "origin" "1600 -256 272" "light" "250" } { "classname" "light" "origin" "1600 -264 56" "light" "250" } { "classname" "light" "origin" "2080 -224 272" "light" "250" } { "classname" "light" "origin" "2080 -232 96" "light" "250" } { "classname" "light" "origin" "1792 -128 208" "light" "150" } { "classname" "light" "origin" "1984 96 208" "light" "150" } { "classname" "light" "origin" "1472 -128 208" "light" "150" } { "classname" "light" "origin" "1504 160 328" "light" "500" } { "classname" "light" "origin" "1696 160 328" "light" "500" } { "classname" "light" "origin" "1048 384 -208" "light" "250" } { "classname" "light" "origin" "1544 472 328" "light" "350" } { "light" "250" "classname" "light_fluorospark" "origin" "1712 432 296" } { "classname" "light" "origin" "1952 576 296" } { "classname" "light" "origin" "1832 432 160" "light" "160" } { "classname" "light" "origin" "1736 672 160" "light" "150" } { "classname" "light" "origin" "1856 560 72" "light" "250" } { "light" "200" "classname" "light_fluoro" "origin" "1776 808 16" } { "light" "200" "classname" "light_fluoro" "origin" "1904 808 16" } { "light" "200" "classname" "light" "origin" "1848 936 120" } { "light" "150" "classname" "light" "origin" "1800 1080 -88" } { "light" "150" "classname" "light" "origin" "1896 1080 -88" } { "classname" "light" "origin" "1640 832 200" "light" "250" } { "classname" "light" "origin" "2056 832 200" "light" "250" } { "light" "200" "classname" "light" "origin" "1576 1056 224" } { "style" "10" "classname" "light_fluorospark" "origin" "2120 1056 224" } { "classname" "light" "origin" "1760 1264 216" "light" "150" } { "classname" "light" "origin" "1944 1264 216" "light" "150" } { "classname" "light" "origin" "1848 1232 120" "light" "150" } { "classname" "light" "origin" "1664 888 40" "light" "150" } { "classname" "light" "origin" "2032 888 40" "light" "150" } { "classname" "light" "origin" "1496 1072 -72" } { "classname" "light" "origin" "2200 1072 -72" } { "classname" "light" "origin" "1704 1792 -24" } { "classname" "light" "origin" "1848 1504 -24" } { "classname" "light" "origin" "1920 1728 -8" "light" "250" } { "classname" "light" "origin" "1720 408 64" "light" "200" } { "classname" "light" "origin" "1624 296 -120" } { "classname" "light" "origin" "1760 432 -120" } { "classname" "light" "origin" "1976 576 -184" } { "classname" "light" "origin" "1888 -32 -176" } { "classname" "light" "origin" "2016 576 32" "light" "150" } { "classname" "light" "origin" "1984 376 32" "light" "150" } { "classname" "light" "origin" "1984 184 32" "light" "150" } { "classname" "light" "origin" "1984 -72 32" "light" "150" } { "classname" "light" "origin" "1840 -128 32" "light" "150" } { "classname" "light" "origin" "1608 -128 32" "light" "150" } { "classname" "light" "origin" "1224 0 32" "light" "200" } { "classname" "light" "origin" "1168 344 48" "light" "250" } { "classname" "light" "origin" "1216 640 8" "light" "250" } { "classname" "light" "origin" "1368 528 -232" } { "style" "10" "classname" "light_fluorospark" "origin" "704 -440 72" "light" "200" } { "classname" "light" "origin" "832 -520 72" "light" "200" } { "classname" "light" "origin" "1056 -312 72" "light" "250" } { "classname" "light" "origin" "784 1064 200" } { "classname" "light" "origin" "368 1064 200" } { "classname" "light" "origin" "992 960 184" "light" "150" } { "classname" "light" "origin" "1120 824 184" "light" "170" } { "classname" "light" "origin" "976 1232 112" "light" "250" } { "classname" "light" "origin" "976 944 88" "light" "250" } { "origin" "880 816 -56" "classname" "light" "light" "250" } { "origin" "960 1072 -56" "classname" "light" "light" "250" } { "origin" "848 1328 -56" "classname" "light" "light" "250" } { "light" "200" "origin" "176 976 88" "classname" "light" } { "light" "200" "origin" "176 1232 88" "classname" "light" } { "origin" "192 1072 -56" "classname" "light" "light" "250" } { "origin" "304 1328 -56" "classname" "light" "light" "250" } { "origin" "272 816 -56" "classname" "light" "light" "250" } { "light" "200" "origin" "416 560 -56" "classname" "light" } { "light" "200" "origin" "408 400 -56" "classname" "light" } { "origin" "936 688 48" "classname" "light_fluoro" } { "light" "400" "origin" "576 768 192" "classname" "light" } { "light" "200" "origin" "576 1064 -176" "classname" "light" } { "light" "300" "origin" "576 1856 152" "classname" "light" } { "light" "300" "origin" "448 1856 152" "classname" "light" } { "light" "300" "origin" "704 1856 152" "classname" "light" } { "origin" "728 1856 0" "classname" "light" } { "light" "200" "origin" "576 1464 -200" "classname" "light" } { "light" "200" "origin" "576 1448 -416" "classname" "light" } { "light" "250" "origin" "576 1160 -480" "classname" "light" } { "classname" "light" "origin" "496 1440 48" "light" "250" } { "classname" "light" "origin" "576 1352 192" } { "classname" "light" "origin" "576 1328 16" "light" "150" } { "classname" "info_teleport_destination" "origin" "576 -272 8" "angle" "90" "targetname" "t1" } { "classname" "trigger_teleport" "target" "t1" "model" "*1" } { "classname" "light" "origin" "1128 1784 328" "light" "500" } { "sounds" "1" "classname" "func_plat" "model" "*2" } { "sounds" "1" "classname" "func_plat" "model" "*3" } { "light" "200" "classname" "light" "origin" "976 1696 224" } { "classname" "light_fluoro" "origin" "1320 1584 64" "light" "250" } { "classname" "light" "origin" "976 1760 64" "light" "150" } { "style" "32" "targetname" "t58" "classname" "light" "origin" "1296 1968 136" } { "classname" "light" "origin" "1176 1856 64" "light" "200" } { "light" "200" "classname" "light" "origin" "1280 1576 240" } { "classname" "func_illusionary" "model" "*4" } { "classname" "light" "origin" "2240 1080 224" "light" "250" } { "classname" "light_fluoro" "origin" "536 1568 408" "light" "150" } { "classname" "light_fluoro" "origin" "616 1568 408" "light" "150" } { "classname" "light" "origin" "576 1608 408" "light" "150" } { "classname" "light" "origin" "576 1528 408" "light" "150" } { "light" "200" "origin" "1072 1576 240" "classname" "light" } { "light" "200" "origin" "840 1576 240" "classname" "light" } { "origin" "760 1584 64" "classname" "light_fluoro" } { "light" "200" "origin" "792 1432 64" "classname" "light" } { "light" "150" "origin" "968 1968 56" "classname" "light" } { "spawnflags" "2056" "angle" "90" "classname" "func_door" "wait" "-1" "speed" "400" "model" "*5" } { "angle" "270" "classname" "func_door" "spawnflags" "2056" "wait" "-1" "speed" "400" "sounds" "2" "model" "*6" } { "light" "200" "origin" "456 1432 -56" "classname" "light" } { "light" "200" "origin" "696 1432 -56" "classname" "light" } { "angle" "-2" "sounds" "2" "targetname" "t2" "classname" "func_door" "wait" "5" "model" "*7" } { "light" "200" "origin" "256 1568 280" "classname" "light" } { "light" "200" "origin" "344 1568 72" "classname" "light" } { "light" "270" "classname" "light" "origin" "272 400 104" } { "light" "270" "classname" "light" "origin" "272 688 104" } { "light" "230" "classname" "light" "origin" "32 112 144" } { "light" "230" "classname" "light" "origin" "-160 112 144" } { "light" "200" "classname" "light" "origin" "-160 -48 144" } { "light" "200" "classname" "light" "origin" "32 -48 144" } { "classname" "light" "origin" "16 448 104" "light" "250" } { "sounds" "1" "classname" "func_plat" "model" "*8" } { "light" "200" "origin" "256 -192 136" "classname" "light" } { "light" "250" "origin" "256 48 -72" "classname" "light" } { "light" "250" "origin" "576 48 -176" "classname" "light" } { "sounds" "2" "lip" "2" "angle" "-1" "classname" "func_door" "model" "*9" } { "sounds" "0" "lip" "-1" "angle" "-2" "classname" "func_door" "model" "*10" } { "sounds" "0" "lip" "2" "angle" "90" "classname" "func_door" "model" "*11" } { "sounds" "0" "lip" "2" "angle" "270" "classname" "func_door" "model" "*12" } { "sounds" "2" "lip" "2" "angle" "-1" "classname" "func_door" "model" "*13" } { "sounds" "0" "lip" "-1" "angle" "-2" "classname" "func_door" "model" "*14" } { "sounds" "0" "lip" "2" "angle" "90" "classname" "func_door" "model" "*15" } { "sounds" "0" "lip" "2" "angle" "270" "classname" "func_door" "model" "*16" } { "target" "t3" "classname" "trigger_teleport" "model" "*17" } { "targetname" "t3" "angle" "270" "origin" "1848 808 -40" "classname" "info_teleport_destination" } { "origin" "1616 -304 -32" "classname" "item_health" } { "origin" "1552 -304 -32" "classname" "item_health" } { "origin" "2024 -288 -32" "classname" "item_health" } { "origin" "2112 -192 -32" "classname" "item_health" } { "origin" "2072 -240 -32" "classname" "item_armor1" } { "origin" "1736 512 112" "classname" "misc_explobox2" } { "origin" "1728 656 112" "classname" "item_shells" } { "spawnflags" "1793" "origin" "1832 576 224" "classname" "item_rockets" } { "spawnflags" "1" "origin" "2000 664 -56" "classname" "item_spikes" } { "origin" "1008 352 -256" "classname" "item_spikes" } { "spawnflags" "1" "origin" "600 1920 -56" "classname" "item_rockets" } { "spawnflags" "1" "origin" "512 1872 -56" "classname" "item_spikes" } { "spawnflags" "1" "origin" "400 1752 -56" "classname" "item_shells" } { "spawnflags" "1" "origin" "416 1928 -56" "classname" "item_health" } { "spawnflags" "1792" "origin" "1080 1880 0" "classname" "item_armorInv" } { "spawnflags" "1793" "origin" "1152 1752 32" "classname" "item_rockets" } { "spawnflags" "1" "origin" "1000 1600 160" "classname" "item_health" } { "spawnflags" "1" "origin" "1128 1544 168" "classname" "item_health" } { "origin" "784 1520 160" "classname" "item_shells" } { "angle" "90" "spawnflags" "4" "classname" "func_door_secret" "model" "*18" } { "spawnflags" "1" "origin" "928 1048 128" "classname" "item_spikes" } { "origin" "944 928 128" "classname" "item_rockets" "spawnflags" "1792" } { "spawnflags" "2" "origin" "560 1416 -96" "classname" "item_health" } { "light" "200" "origin" "288 -192 -72" "classname" "light" } { "spawnflags" "1792" "origin" "1808 1792 -80" "classname" "item_armorInv" } { "origin" "1896 1776 -80" "classname" "item_health" } { "origin" "1944 1656 -80" "classname" "item_health" } { "origin" "1728 1656 -80" "classname" "item_health" } { "origin" "1984 1816 -80" "classname" "item_health" } { "spawnflags" "2" "origin" "2200 1104 160" "classname" "item_health" } { "spawnflags" "1" "origin" "1616 1088 32" "classname" "item_spikes" } { "spawnflags" "1536" "origin" "1400 -136 112" "classname" "item_shells" } { "spawnflags" "1536" "origin" "1968 32 112" "classname" "item_shells" } { "spawnflags" "1536" "origin" "1184 64 112" "classname" "item_shells" } { "angle" "90" "origin" "-64 88 -40" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "2032 1136 56" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "1744 672 248" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "1024 936 152" "classname" "info_player_deathmatch" } { "origin" "832 1576 184" "classname" "info_player_deathmatch" } { "origin" "456 1568 176" "classname" "weapon_supershotgun" } { "origin" "256 416 0" "classname" "item_rockets" "spawnflags" "1792" } { "origin" "256 544 0" "classname" "item_spikes" } { "origin" "144 1088 0" "classname" "item_shells" } { "spawnflags" "2048" "origin" "1088 1880 0" "classname" "item_armor2" } { "spawnflags" "1792" "classname" "weapon_supershotgun" "origin" "1728 1728 -80" } { "classname" "weapon_grenadelauncher" "origin" "648 1776 -56" } { "classname" "weapon_rocketlauncher" "origin" "1952 -96 112" "spawnflags" "1792" } { "light" "250" "classname" "light" "origin" "1200 544 40" } { "classname" "light" "origin" "1024 544 40" "light" "200" } { "sounds" "1" "classname" "func_plat" "spawnflags" "1" "model" "*19" } { "classname" "light" "origin" "1360 616 120" "light" "150" } { "classname" "light" "origin" "1216 528 216" "light" "170" } { "classname" "item_armorInv" "origin" "1256 664 -32" } { "spawnflags" "2048" "sounds" "3" "classname" "item_key2" "origin" "1848 1320 72" } { "classname" "light" "origin" "1848 560 160" "light" "200" } { "sounds" "3" "classname" "item_armor1" "origin" "1848 416 224" } { "classname" "light" "origin" "1752 672 304" "light" "200" } { "classname" "item_spikes" "origin" "1056 352 -256" } { "spawnflags" "2048" "origin" "1752 1800 -80" "classname" "item_shells" } { "spawnflags" "2048" "origin" "560 200 -96" "classname" "item_shells" } { "origin" "510 -194 24" "classname" "monster_enforcer" } { "target" "t6" "targetname" "t5" "origin" "896 -256 -24" "classname" "path_corner" } { "target" "t7" "targetname" "t6" "classname" "path_corner" "origin" "1088 -256 -24" } { "target" "t8" "targetname" "t7" "origin" "1088 64 -24" "classname" "path_corner" } { "targetname" "t8" "target" "t5" "classname" "path_corner" "origin" "896 0 -24" } { "target" "t8" "origin" "984 48 -8" "classname" "monster_army" } { "spawnflags" "768" "target" "t5" "origin" "928 -128 -8" "classname" "monster_army" } { "target" "t7" "spawnflags" "768" "origin" "1056 -184 -8" "classname" "monster_army" } { "light" "170" "origin" "1024 288 64" "classname" "light" } { "classname" "light" "origin" "576 664 -8" "light" "150" } { "classname" "path_corner" "origin" "1320 88 -24" "targetname" "t9" "target" "t18" } { "origin" "1648 432 -40" "classname" "path_corner" "target" "t9" "targetname" "t10" } { "classname" "monster_army" "origin" "1680 352 -8" "target" "t10" } { "classname" "monster_dog" "origin" "1408 144 -8" "target" "t18" "spawnflags" "256" } { "classname" "light" "origin" "992 56 72" "light" "200" } { "classname" "monster_enforcer" "origin" "902 358 24" "spawnflags" "256" } { "classname" "path_corner" "origin" "1680 1064 40" "targetname" "t11" "target" "t12" } { "origin" "2016 1064 40" "classname" "path_corner" "targetname" "t12" "target" "t13" } { "classname" "path_corner" "origin" "1848 1248 40" "target" "t11" "targetname" "t13" } { "classname" "monster_army" "origin" "1680 1120 56" "target" "t11" "spawnflags" "256" } { "classname" "monster_dog" "origin" "1920 1064 56" "target" "t12" } { "classname" "monster_enforcer" "origin" "1918 1246 56" "target" "t13" "spawnflags" "768" } { "classname" "monster_enforcer" "origin" "1662 790 -8" "spawnflags" "768" } { "classname" "monster_enforcer" "origin" "254 430 24" "spawnflags" "256" "target" "t14" } { "classname" "path_corner" "origin" "232 320 8" "targetname" "t14" "target" "t16" } { "origin" "288 760 8" "classname" "path_corner" "target" "t14" "targetname" "t15" } { "classname" "monster_army" "origin" "256 608 24" "target" "t15" "spawnflags" "256" } { "classname" "item_health" "origin" "880 72 -32" } { "origin" "400 384 8" "classname" "path_corner" "targetname" "t16" "target" "t15" } { "classname" "item_health" "origin" "1232 304 -32" } { "sounds" "2" "classname" "func_door" "spawnflags" "1" "angle" "-1" "targetname" "t17" "wait" "8" "model" "*20" } { "sounds" "2" "classname" "func_door" "angle" "-1" "spawnflags" "1" "targetname" "t17" "wait" "8" "model" "*21" } { "classname" "trigger_once" "target" "t17" "model" "*22" } { "classname" "path_corner" "origin" "1392 8 -24" "targetname" "t18" "target" "t19" } { "origin" "1728 344 -24" "classname" "path_corner" "targetname" "t19" "target" "t10" } { "light" "150" "origin" "2048 824 8" "classname" "light" } { "classname" "light" "origin" "1648 824 8" "light" "150" } { "spawnflags" "2048" "wait" "-1" "classname" "func_button" "target" "t20" "angle" "180" "model" "*23" } { "targetname" "t58" "spawnflags" "2049" "classname" "func_door_secret" "angle" "180" "model" "*24" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "5" "targetname" "t21" "wait" "6" "model" "*25" } { "classname" "light" "origin" "576 2168 16" } { "classname" "trigger_multiple" "target" "t21" "health" "50" "model" "*26" } { "targetname" "t27" "target" "t22" "origin" "360 1400 8" "classname" "path_corner" } { "target" "t23" "targetname" "t22" "classname" "path_corner" "origin" "240 1400 8" } { "target" "t24" "targetname" "t23" "origin" "112 1208 8" "classname" "path_corner" } { "target" "t25" "targetname" "t24" "classname" "path_corner" "origin" "120 896 8" } { "target" "t26" "targetname" "t25" "origin" "224 912 8" "classname" "path_corner" } { "target" "t27" "targetname" "t26" "classname" "path_corner" "origin" "224 1200 8" } { "target" "t26" "origin" "182 998 24" "classname" "monster_enforcer" } { "target" "t23" "origin" "176 1256 24" "classname" "monster_army" } { "target" "t22" "spawnflags" "256" "origin" "272 1368 24" "classname" "monster_army" } { "target" "t25" "spawnflags" "768" "origin" "184 832 24" "classname" "monster_dog" } { "angle" "180" "spawnflags" "768" "origin" "432 1568 24" "classname" "monster_dog" } { "target" "t29" "targetname" "t28" "origin" "784 1576 168" "classname" "path_corner" } { "targetname" "t29" "target" "t28" "classname" "path_corner" "origin" "1288 1576 168" } { "spawnflags" "1536" "target" "t29" "origin" "1216 1576 184" "classname" "monster_army" } { "spawnflags" "1280" "target" "t29" "origin" "1080 1576 184" "classname" "monster_dog" } { "spawnflags" "768" "target" "t28" "origin" "902 1574 184" "classname" "monster_enforcer" } { "spawnflags" "256" "angle" "270" "origin" "974 1966 152" "classname" "monster_enforcer" } { "targetname" "t58" "angle" "270" "origin" "976 1720 24" "classname" "monster_dog" } { "targetname" "t58" "spawnflags" "256" "classname" "monster_dog" "origin" "976 1808 24" "angle" "270" } { "spawnflags" "768" "angle" "270" "origin" "1288 1872 24" "classname" "monster_dog" } { "angle" "270" "origin" "1288 1744 24" "classname" "monster_army" } { "target" "t34" "targetname" "t33" "origin" "808 1368 8" "classname" "path_corner" } { "target" "t35" "targetname" "t34" "classname" "path_corner" "origin" "944 1216 8" } { "target" "t30" "targetname" "t35" "origin" "944 920 8" "classname" "path_corner" } { "target" "t33" "targetname" "t32" "classname" "path_corner" "origin" "936 1384 8" } { "target" "t32" "targetname" "t31" "origin" "1040 1216 8" "classname" "path_corner" } { "target" "t31" "targetname" "t30" "classname" "path_corner" "origin" "1040 920 8" } { "target" "t31" "origin" "1040 1168 24" "classname" "monster_army" } { "target" "t35" "origin" "950 1134 24" "classname" "monster_enforcer" } { "origin" "920 200 0" "classname" "item_health" } { "spawnflags" "1" "origin" "832 216 0" "classname" "item_health" } { "spawnflags" "1" "origin" "1752 360 -32" "classname" "item_shells" } { "origin" "1696 1240 32" "classname" "item_health" } { "target" "t39" "targetname" "t38" "origin" "1888 -128 120" "classname" "path_corner" } { "targetname" "t39" "target" "t38" "classname" "path_corner" "origin" "1216 -128 120" } { "spawnflags" "256" "target" "t38" "origin" "1720 -128 136" "classname" "monster_army" } { "target" "t41" "targetname" "t40" "origin" "1984 0 120" "classname" "path_corner" } { "targetname" "t41" "target" "t40" "classname" "path_corner" "origin" "1984 448 120" } { "spawnflags" "768" "target" "t41" "origin" "1982 262 136" "classname" "monster_enforcer" } { "spawnflags" "768" "angle" "315" "origin" "1110 838 136" "classname" "monster_enforcer" } { "origin" "1360 544 -16" "classname" "weapon_nailgun" } { "targetname" "t42" "origin" "1356 548 -12" "classname" "info_null" } { "target" "t42" "origin" "1360 544 112" "classname" "light" } { "target" "t47" "angle" "90" "origin" "1742 454 248" "classname" "monster_enforcer" } { "origin" "1208 552 112" "classname" "item_health" } { "spawnflags" "1024" "classname" "item_health" "origin" "1176 448 112" } { "spawnflags" "257" "origin" "1208 328 112" "classname" "item_health" } { "angle" "135" "origin" "6 150 -24" "classname" "monster_enforcer" } { "spawnflags" "768" "classname" "monster_enforcer" "origin" "30 38 -24" "angle" "90" } { "spawnflags" "256" "angle" "90" "origin" "-154 38 -24" "classname" "monster_enforcer" } { "angle" "90" "origin" "1288 1824 248" "classname" "monster_army" } { "origin" "472 1608 0" "classname" "item_health" } { "classname" "item_health" "origin" "472 1504 0" } { "spawnflags" "1" "origin" "952 1976 0" "classname" "item_shells" } { "targetname" "t43" "angle" "180" "origin" "1856 432 136" "classname" "monster_army" } { "sounds" "2" "wait" "5" "targetname" "t43" "angle" "-1" "spawnflags" "2049" "classname" "func_door" "model" "*27" } { "sounds" "2" "dmg" "30" "wait" "10" "speed" "500" "targetname" "t44" "angle" "180" "spawnflags" "2049" "classname" "func_door" "model" "*28" } { "wait" "10" "sounds" "2" "speed" "500" "targetname" "t44" "spawnflags" "2049" "angle" "180" "classname" "func_door" "model" "*29" } { "target" "t44" "classname" "trigger_once" "spawnflags" "2048" "model" "*30" } { "spawnflags" "2048" "sounds" "2" "classname" "func_door" "angle" "-1" "targetname" "t44" "wait" "-1" "message" "This barrier opens elsewhere..." "model" "*31" } { "classname" "item_shells" "origin" "1056 -400 -24" "spawnflags" "1" } { "classname" "info_null" "origin" "452 1564 164" "targetname" "t46" } { "classname" "light" "origin" "488 1568 304" "target" "t46" } { "spawnflags" "2048" "classname" "func_train" "targetname" "t47" "target" "t50" "sounds" "1" "model" "*32" } { "classname" "light" "origin" "1504 640 272" "light" "200" } { "classname" "path_corner" "origin" "1680 592 224" "target" "t48" "targetname" "t50" } { "origin" "1664 592 232" "classname" "path_corner" "targetname" "t48" "target" "t51" } { "classname" "path_corner" "origin" "1616 600 312" "targetname" "t49" "target" "t51" } { "origin" "1664 592 304" "classname" "path_corner" "targetname" "t51" "target" "t49" "wait" "-1" } { "light" "200" "origin" "1352 648 272" "classname" "light" } { "classname" "light" "origin" "1392 832 256" "light" "200" } { "angle" "-2" "targetname" "t56" "classname" "func_door" "sounds" "2" "wait" "5" "model" "*33" } { "classname" "light" "origin" "1176 1024 64" "light" "150" } { "classname" "light" "origin" "1312 1024 248" "light" "200" } { "light" "150" "origin" "1296 1024 104" "classname" "light" } { "light" "120" "classname" "light" "origin" "832 -192 56" } { "sounds" "2" "classname" "func_door" "angle" "-1" "targetname" "t52" "wait" "-1" "spawnflags" "2048" "model" "*34" } { "sounds" "2" "classname" "func_door" "angle" "-1" "targetname" "t52" "wait" "-1" "spawnflags" "2048" "model" "*35" } { "classname" "item_health" "origin" "1432 632 224" "spawnflags" "1" } { "origin" "1512 616 224" "classname" "item_health" "spawnflags" "1024" } { "classname" "item_health" "origin" "1320 616 224" } { "sounds" "2" "wait" "-1" "targetname" "t55" "spawnflags" "1" "angle" "180" "classname" "func_door" "model" "*36" } { "wait" "-1" "targetname" "t55" "spawnflags" "3" "angle" "180" "classname" "func_door_secret" "model" "*37" } { "spawnflags" "3" "targetname" "t55" "angle" "180" "classname" "func_door_secret" "model" "*38" } { "spawnflags" "1792" "target" "t55" "classname" "trigger_once" "model" "*39" } { "target" "t43" "classname" "trigger_once" "model" "*40" } { "classname" "func_wall" "spawnflags" "2048" "model" "*41" } { "classname" "func_wall" "spawnflags" "2048" "model" "*42" } { "classname" "func_wall" "spawnflags" "2048" "model" "*43" } { "classname" "trigger_once" "target" "t44" "model" "*44" } { "target" "t57" "classname" "trigger_teleport" "spawnflags" "1792" "model" "*45" } { "targetname" "t57" "angle" "270" "origin" "1216 416 120" "classname" "info_teleport_destination" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "1800 424 112" } { "light" "200" "origin" "2216 1464 -136" "classname" "light" } { "classname" "light" "origin" "1480 1464 -136" "light" "200" } { "light" "150" "origin" "1328 672 56" "classname" "light" } { "light" "170" "origin" "1224 336 216" "classname" "light" } { "light" "150" "origin" "2000 328 264" "classname" "light" } { "light" "200" "origin" "1560 640 152" "classname" "light" } { "light" "150" "origin" "1848 672 248" "classname" "light" } { "light" "120" "origin" "1840 520 272" "classname" "light" } { "light" "150" "origin" "984 1576 72" "classname" "light" } { "light" "150" "origin" "984 1968 200" "classname" "light" } { "light" "200" "origin" "624 1664 240" "classname" "light" } { "classname" "light" "origin" "624 1488 240" "light" "200" } { "light" "200" "origin" "616 1568 264" "classname" "light" } { "light" "200" "origin" "-64 280 40" "classname" "light" } { "light" "200" "origin" "576 744 -184" "classname" "light" } { "origin" "352 1064 -184" "classname" "light" } { "classname" "light" "origin" "800 1064 -184" } { "origin" "576 1272 -184" "classname" "light" } { "light" "200" "origin" "432 1856 32" "classname" "light" } { "light" "200" "origin" "264 -48 56" "classname" "light" } { "classname" "light" "origin" "264 152 56" "light" "200" } { "light" "150" "origin" "1976 -120 184" "classname" "light" } { "origin" "1368 24 -216" "classname" "light" } { "origin" "1608 72 -216" "classname" "light" } { "light" "200" "origin" "1216 656 200" "classname" "light" } { "origin" "576 1464 -488" "classname" "item_artifact_envirosuit" } { "target" "t56" "angle" "90" "classname" "func_button" "model" "*46" } { "classname" "trigger_secret" "model" "*47" } { "classname" "trigger_secret" "model" "*48" } { "classname" "trigger_secret" "model" "*49" } { "classname" "trigger_secret" "model" "*50" } { "classname" "trigger_secret" "model" "*51" } { "classname" "trigger_secret" "model" "*52" } { "style" "32" "target" "t58" "targetname" "t20" "classname" "trigger_once" "model" "*53" } { "light" "150" "origin" "1912 872 8" "classname" "light" } { "classname" "light" "origin" "1784 872 8" "light" "150" } { "targetname" "t59" "origin" "1848 1320 52" "classname" "info_null" } { "light" "400" "target" "t59" "origin" "1848 1320 224" "classname" "light" } { "light" "150" "origin" "1712 1208 104" "classname" "light" } { "classname" "light" "origin" "1984 1208 104" "light" "150" } { "light" "150" "origin" "1848 1064 104" "classname" "light" } { "origin" "1800 904 -88" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "1896 904 -88" } { "classname" "light" "origin" "872 232 64" "light" "150" } { "light" "170" "origin" "296 1376 48" "classname" "light" } { "light" "170" "classname" "light" "origin" "576 768 -120" } { "origin" "576 704 -120" "classname" "light" "light" "170" } { "target" "t2" "classname" "func_button" "angle" "270" "model" "*54" } { "targetname" "t60" "classname" "func_door_secret" "angle" "90" "spawnflags" "3" "model" "*55" } { "targetname" "t60" "classname" "monster_enforcer" "origin" "-32 1120 24" "angle" "0" } { "targetname" "t60" "spawnflags" "256" "angle" "0" "origin" "-32 1056 24" "classname" "monster_enforcer" } { "targetname" "t60" "spawnflags" "256" "angle" "0" "origin" "32 1120 24" "classname" "monster_enforcer" } { "targetname" "t60" "spawnflags" "768" "classname" "monster_enforcer" "origin" "32 1056 24" "angle" "0" } { "target" "t60" "spawnflags" "2048" "classname" "trigger_once" "model" "*56" } { "light" "150" "origin" "0 1088 56" "classname" "light" } { "sounds" "2" "speed" "400" "wait" "-1" "classname" "func_door" "angle" "90" "spawnflags" "2064" "model" "*57" } { "speed" "400" "wait" "-1" "spawnflags" "2064" "classname" "func_door" "angle" "270" "model" "*58" } { "classname" "light" "origin" "504 1656 240" "light" "200" } { "light" "200" "origin" "504 1496 240" "classname" "light" } { "classname" "light" "origin" "256 1568 64" "light" "200" } { "spawnflags" "2048" "classname" "func_wall" "model" "*59" } { "light" "200" "origin" "104 1096 64" "classname" "light" } { "light" "200" "origin" "168 888 64" "classname" "light" } { "light" "100" "origin" "1312 1624 360" "classname" "light" } { "classname" "light" "origin" "1216 1624 360" "light" "100" } { "light" "100" "origin" "1120 1624 360" "classname" "light" } { "classname" "light" "origin" "1024 1624 360" "light" "100" } { "light" "100" "origin" "928 1624 360" "classname" "light" } { "classname" "light" "origin" "832 1624 360" "light" "100" } { "light" "100" "origin" "832 1528 360" "classname" "light" } { "classname" "light" "origin" "928 1528 360" "light" "100" } { "light" "100" "origin" "1024 1528 360" "classname" "light" } { "classname" "light" "origin" "1120 1528 360" "light" "100" } { "light" "100" "origin" "1216 1528 360" "classname" "light" } { "classname" "light" "origin" "1312 1528 360" "light" "100" } { "origin" "576 2168 -32" "classname" "item_artifact_invulnerability" } { "spawnflags" "1" "angle" "270" "classname" "func_door_secret" "model" "*60" } { "light" "200" "origin" "856 2024 56" "classname" "light" } { "origin" "864 2072 24" "classname" "item_artifact_super_damage" } { "classname" "trigger_secret" "model" "*61" } { "light" "250" "origin" "544 -752 88" "classname" "light" } { "classname" "light" "origin" "552 -512 88" "light" "250" } { "spawnflags" "2816" "origin" "576 -96 24" "classname" "item_key1" } { "wait" "-1" "speed" "300" "classname" "func_door" "angle" "-1" "targetname" "t62" "sounds" "2" "model" "*62" } { "classname" "monster_enforcer" "origin" "1848 776 120" "angle" "90" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t62" "model" "*63" } { "classname" "light" "origin" "888 1576 64" "light" "200" } { "spawnflags" "2048" "target" "t63" "classname" "trigger_once" "model" "*64" } { "spawnflags" "2048" "speed" "600" "targetname" "t63" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*65" } { "spawnflags" "2" "target" "t66" "classname" "trigger_teleport" "model" "*66" } { "spawnflags" "2" "target" "t65" "classname" "trigger_teleport" "model" "*67" } { "spawnflags" "2" "target" "t64" "classname" "trigger_teleport" "model" "*68" } { "targetname" "t63" "origin" "2336 -352 136" "classname" "monster_enforcer" } { "targetname" "t63" "spawnflags" "256" "classname" "monster_enforcer" "origin" "2336 -416 136" } { "targetname" "t63" "spawnflags" "256" "origin" "2336 -480 136" "classname" "monster_enforcer" } { "targetname" "t63" "spawnflags" "768" "classname" "monster_enforcer" "origin" "2384 -480 136" } { "targetname" "t63" "spawnflags" "768" "origin" "2384 -416 136" "classname" "monster_enforcer" } { "targetname" "t63" "spawnflags" "256" "classname" "monster_enforcer" "origin" "2384 -352 136" } { "targetname" "t65" "angle" "0" "origin" "1664 -128 120" "classname" "info_teleport_destination" } { "targetname" "t66" "classname" "info_teleport_destination" "origin" "1984 224 120" "angle" "270" } { "targetname" "t64" "angle" "315" "origin" "1544 248 -24" "classname" "info_teleport_destination" } { "light" "200" "origin" "800 -192 48" "classname" "light" } { "classname" "trigger_changelevel" "map" "e2m2" "model" "*69" } { "classname" "light" "origin" "-64 -24 40" "light" "200" } { "classname" "func_wall" "spawnflags" "1792" "model" "*70" } { "classname" "func_door" "angle" "-1" "spawnflags" "2049" "wait" "20" "speed" "400" "sounds" "2" "targetname" "t67" "model" "*71" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t67" "model" "*72" } { "classname" "trap_spikeshooter" "origin" "-200 -168 16" "spawnflags" "2" "angle" "75" "targetname" "t68" } { "angle" "105" "spawnflags" "2" "origin" "72 -168 16" "classname" "trap_spikeshooter" "targetname" "t68" } { "classname" "trigger_multiple" "target" "t68" "wait" "0.5" "model" "*73" } { "classname" "item_spikes" "origin" "-360 128 -64" "spawnflags" "1" } { "classname" "item_health" "origin" "-360 56 -64" } { "origin" "-304 -48 144" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-304 112 144" } { "light" "200" "origin" "-216 136 8" "classname" "light" } { "classname" "light" "origin" "-224 -24 8" "light" "200" } { "mangle" "20 135 0" "origin" "2000 -144 272" "classname" "info_intermission" } { "mangle" "20 90 0" "origin" "576 272 128" "classname" "info_intermission" } { "mangle" "20 45 0" "origin" "952 1696 320" "classname" "info_intermission" } { "mangle" "-20 90 0" "origin" "576 776 -72" "classname" "info_intermission" } { "angle" "90" "origin" "472 -736 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "616 -736 56" "angle" "90" } { "angle" "90" "origin" "600 -672 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "488 -672 56" "angle" "90" } { "spawnflags" "1792" "origin" "-64 144 -64" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "576 -144 0" "classname" "weapon_supernailgun" } { "classname" "item_key1" "origin" "1744 424 136" "spawnflags" "3072" } { "classname" "ambient_comp_hum" "origin" "1122 1874 96" } { "origin" "1178 1754 96" "classname" "ambient_comp_hum" } { "classname" "ambient_comp_hum" "origin" "1074 1786 96" } { "classname" "ambient_drone" "origin" "-62 -110 48" } { "target" "t2" "angle" "90" "classname" "func_button" "model" "*74" } { "target" "t56" "classname" "func_button" "angle" "90" "model" "*75" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "1800 416 244" "classname" "item_flag_team1" } { "angle" "90" "origin" "1736 410 248" "classname" "info_player_team1" } { "angle" "90" "origin" "1836 410 248" "classname" "info_player_team1" } { "angle" "90" "origin" "1736 490 248" "classname" "info_player_team1" } { "angle" "90" "origin" "1836 490 248" "classname" "info_player_team1" } { "angle" "90" "origin" "1736 570 248" "classname" "info_player_team1" } { "angle" "90" "origin" "1836 570 248" "classname" "info_player_team1" } // team2 { "origin" "-300 -25 -30" "classname" "item_flag_team2" "angle" "270" } { "angle" "0" "origin" "-142 82 -40" "classname" "info_player_team2" } { "angle" "0" "origin" "-62 82 -40" "classname" "info_player_team2" } { "angle" "0" "origin" "42 82 -40" "classname" "info_player_team2" } { "angle" "0" "origin" "-142 162 -40" "classname" "info_player_team2" } { "angle" "0" "origin" "-62 162 -40" "classname" "info_player_team2" } { "angle" "0" "origin" "42 162 -40" "classname" "info_player_team2" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m2.ent000066400000000000000000000670151475442401000252020ustar00rootroot00000000000000{ "message" "the Ogre Citadel" "sounds" "8" "wad" "gfx/wizard.wad" "classname" "worldspawn" "worldtype" "0" } { "origin" "160 -160 120" "classname" "light" } { "angle" "90" "origin" "-256 -1952 280" "classname" "info_player_start" } { "classname" "light" "origin" "160 -392 248" "light" "200" } { "classname" "light" "origin" "160 -648 184" } { "classname" "light" "origin" "-56 -392 248" "light" "200" } { "classname" "light" "origin" "376 -392 248" "light" "200" } { "classname" "light" "origin" "288 -416 -72" "light" "200" } { "classname" "light" "origin" "32 -416 -72" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "10 -270 148" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "314 -270 148" "light" "250" } { "classname" "light" "origin" "-264 -440 248" "light" "200" } { "classname" "light" "origin" "584 -440 248" "light" "200" } { "classname" "light" "origin" "544 -648 248" } { "light" "150" "origin" "648 -456 -184" "classname" "light" } { "origin" "376 -800 184" "classname" "light" } { "classname" "light" "origin" "-152 -752 184" "light" "250" } { "classname" "light" "origin" "-232 -592 184" "light" "250" } { "classname" "light" "origin" "160 112 184" } { "classname" "light" "origin" "160 352 120" } { "classname" "light" "origin" "160 216 -48" "light" "120" } { "classname" "light" "origin" "160 16 -48" "light" "120" } { "classname" "light" "origin" "160 544 144" "light" "225" } { "classname" "light" "origin" "480 576 88" } { "classname" "light" "origin" "480 448 88" } { "classname" "light" "origin" "480 576 168" "light" "250" } { "classname" "light" "origin" "480 448 168" "light" "250" } { "classname" "light" "origin" "160 896 312" "light" "350" } { "classname" "light" "origin" "288 896 312" "light" "100" } { "classname" "light" "origin" "32 896 312" "light" "100" } { "classname" "light" "origin" "160 1008 312" "light" "100" } { "classname" "light" "origin" "160 784 312" "light" "100" } { "classname" "light" "origin" "392 120 184" "light" "350" } { "classname" "light" "origin" "568 208 184" "light" "350" } { "classname" "light" "origin" "720 480 184" } { "classname" "light" "origin" "640 632 184" } { "classname" "light" "origin" "472 1152 56" } { "classname" "light" "origin" "512 896 152" } { "origin" "800 800 184" "classname" "light" } { "light" "200" "origin" "632 1264 -40" "classname" "light" } { "origin" "800 1032 184" "classname" "light" } { "origin" "760 1472 64" "classname" "light" } { "light" "200" "origin" "544 1416 56" "classname" "light" } { "origin" "672 1256 184" "classname" "light" "light" "200" } { "light" "200" "origin" "1024 1272 184" "classname" "light" } { "light" "200" "origin" "992 1440 184" "classname" "light" } { "origin" "1240 488 184" "classname" "light" } { "origin" "1280 136 176" "classname" "light" } { "origin" "160 1304 136" "classname" "light" } { "origin" "160 1648 256" "classname" "light" "light" "200" } { "origin" "240 1600 256" "classname" "light" "light" "200" } { "origin" "16 1616 168" "classname" "light" "light" "200" } { "light" "200" "origin" "-120 1304 40" "classname" "light" } { "origin" "-352 1144 16" "classname" "light" "light" "250" } { "origin" "-56 1096 64" "classname" "light" } { "light" "200" "origin" "-56 1152 280" "classname" "light" } { "light" "350" "origin" "-440 1144 200" "classname" "light" } { "light" "200" "origin" "-352 1336 -72" "classname" "light" } { "origin" "-488 368 56" "classname" "light" "light" "250" } { "light" "350" "origin" "-488 896 136" "classname" "light" } { "origin" "-216 896 184" "classname" "light" "light" "250" } { "origin" "-128 536 168" "classname" "light" "light" "200" } { "light" "150" "origin" "-104 480 32" "classname" "light" } { "light" "150" "origin" "-208 936 56" "classname" "light" } { "light" "150" "origin" "-208 736 32" "classname" "light" } { "origin" "-344 64 184" "classname" "light" } { "light" "350" "origin" "-648 384 184" "classname" "light" } { "light" "350" "origin" "-488 688 184" "classname" "light" } { "light" "150" "origin" "-680 496 -36" "classname" "light" } { "light" "350" "origin" "-600 1104 96" "classname" "light" } { "origin" "-824 896 168" "classname" "light" } { "origin" "-896 600 160" "classname" "light" } { "target" "t1" "classname" "trigger_teleport" "model" "*1" } { "spawnflags" "1792" "targetname" "t1" "origin" "-448 264 -56" "classname" "info_teleport_destination" "angle" "45" } { "light" "250" "origin" "-168 1320 160" "classname" "light" } { "origin" "-24 896 184" "classname" "light" } { "origin" "-104 896 184" "classname" "light" "light" "250" } { "spawnflags" "2" "origin" "-680 880 48" "classname" "item_health" } { "angle" "90" "origin" "-896 512 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-184 560 128" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "160 1640 160" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "1272 112 80" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "176 -784 24" "classname" "info_player_deathmatch" } { "spawnflags" "1" "origin" "208 -160 0" "classname" "item_rockets" } { "origin" "64 464 0" "classname" "item_health" } { "origin" "120 464 0" "classname" "item_health" } { "spawnflags" "1" "origin" "-8 840 64" "classname" "item_health" } { "spawnflags" "1" "origin" "-8 952 64" "classname" "item_health" } { "spawnflags" "9" "origin" "568 880 0" "classname" "item_weapon" } { "origin" "456 1104 -88" "classname" "item_health" } { "spawnflags" "1" "origin" "664 1272 -88" "classname" "item_shells" } { "angle" "225" "origin" "888 1312 120" "classname" "info_player_deathmatch" } { "origin" "1328 168 56" "classname" "item_health" } { "origin" "1328 128 56" "classname" "item_health" } { "origin" "1328 208 56" "classname" "item_health" } { "spawnflags" "1" "origin" "816 1472 0" "classname" "item_shells" } { "light" "200" "origin" "-64 -120 -56" "classname" "light" } { "light" "200" "origin" "-296 -160 -56" "classname" "light" } { "light" "200" "origin" "-296 -208 -272" "classname" "light" } { "classname" "func_plat" "model" "*2" } { "spawnflags" "2" "origin" "-192 -176 -80" "classname" "item_health" } { "light" "350" "origin" "-816 128 184" "classname" "light" } { "light" "350" "origin" "-664 -80 184" "classname" "light" } { "light" "250" "origin" "-656 112 32" "classname" "light" } { "origin" "-352 208 56" "classname" "light" "light" "250" } { "origin" "-184 504 24" "classname" "light" "light" "250" } { "classname" "item_armor1" "origin" "400 -888 0" } { "spawnflags" "1792" "classname" "item_armorInv" "origin" "-104 448 104" } { "classname" "item_armor2" "origin" "-680 496 32" } { "classname" "weapon_grenadelauncher" "origin" "168 1608 136" "spawnflags" "1792" } { "classname" "weapon_rocketlauncher" "origin" "1232 176 56" "spawnflags" "1792" } { "classname" "weapon_supernailgun" "origin" "-960 944 40" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "752 1464 0" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "160 120 24" "spawnflags" "1792" } { "classname" "item_rockets" "origin" "-224 792 104" "spawnflags" "1792" } { "classname" "item_rockets" "origin" "-640 120 -56" "spawnflags" "1792" } { "light" "200" "origin" "-70 -1126 212" "classname" "light_torch_small_walltorch" } { "light" "200" "classname" "light_torch_small_walltorch" "origin" "186 -1134 148" } { "light" "200" "origin" "138 -966 100" "classname" "light_torch_small_walltorch" } { "light" "200" "classname" "light_torch_small_walltorch" "origin" "-150 -1318 260" } { "light" "150" "origin" "184 -880 72" "classname" "light" } { "style" "6" "light" "200" "origin" "-46 -1742 340" "classname" "light_torch_small_walltorch" } { "style" "1" "light" "200" "classname" "light_torch_small_walltorch" "origin" "-486 -1726 340" } { "origin" "-272 -1544 384" "classname" "light" "light" "200" } { "style" "6" "light" "200" "classname" "light_torch_small_walltorch" "origin" "-414 -2006 340" } { "style" "1" "light" "200" "origin" "-134 -1958 340" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "-472 -1840 328" "classname" "light" } { "classname" "light" "origin" "-72 -1592 328" "light" "150" } { "light" "150" "origin" "-320 -1424 264" "classname" "light" } { "light" "150" "origin" "-256 -1952 280" "classname" "light" } { "light" "200" "classname" "light" "origin" "-272 -1720 312" } { "origin" "-232 -1280 168" "classname" "path_corner" "targetname" "t5" "target" "t6" } { "classname" "path_corner" "origin" "-64 -1176 120" "targetname" "t6" "target" "t7" } { "origin" "152 -1104 56" "classname" "path_corner" "targetname" "t7" "target" "t8" } { "classname" "path_corner" "origin" "192 -952 8" "targetname" "t8" "target" "t9" } { "origin" "184 -808 8" "classname" "path_corner" "target" "t3" "targetname" "t9" } { "classname" "path_corner" "origin" "512 -776 8" "targetname" "t3" "target" "t10" } { "origin" "-200 -648 8" "classname" "path_corner" "targetname" "t4" "target" "t11" } { "classname" "monster_knight" "origin" "-360 -1616 232" "target" "t5" "angle" "90" } { "origin" "512 -648 8" "classname" "path_corner" "targetname" "t10" "target" "t4" } { "classname" "path_corner" "origin" "-200 -776 8" "targetname" "t11" "target" "t3" } { "classname" "monster_knight" "origin" "24 -632 24" "spawnflags" "256" "target" "t4" } { "classname" "monster_knight" "origin" "336 -752 24" "spawnflags" "256" "target" "t3" } { "classname" "monster_knight" "origin" "56 -712 24" "angle" "270" "spawnflags" "768" } { "spawnflags" "768" "angle" "270" "origin" "160 -712 24" "classname" "monster_knight" } { "classname" "monster_knight" "origin" "264 -712 24" "angle" "270" "spawnflags" "768" } { "classname" "item_health" "origin" "-432 -1640 208" "spawnflags" "1" } { "classname" "item_shells" "origin" "-352 -592 0" } { "classname" "func_door" "angle" "90" "spawnflags" "1" "targetname" "t13" "wait" "-1" "sounds" "3" "dmg" "100" "model" "*3" } { "health" "1" "angle" "90" "classname" "func_button" "target" "t12" "wait" "-1" "sounds" "1" "model" "*4" } { "classname" "func_button" "angle" "90" "health" "1" "target" "t12" "wait" "-1" "sounds" "1" "model" "*5" } { "classname" "trigger_counter" "targetname" "t12" "count" "2" "target" "t13" "model" "*6" } { "classname" "monster_demon1" "origin" "160 -128 24" "angle" "270" "targetname" "t12" } { "classname" "light" "origin" "-8 -288 64" "light" "200" } { "light" "200" "origin" "328 -288 64" "classname" "light" } { "light" "200" "origin" "-296 -448 -248" "classname" "light" } { "classname" "light" "origin" "160 -368 -248" "light" "200" } { "light" "200" "origin" "616 -448 -248" "classname" "light" } { "classname" "light" "origin" "408 -456 -248" "light" "200" } { "light" "200" "origin" "-40 -424 -248" "classname" "light" } { "classname" "light" "origin" "-280 -448 32" "light" "200" } { "light" "200" "origin" "632 -424 32" "classname" "light" } { "classname" "light" "origin" "160 -480 8" "light" "150" } { "classname" "func_door" "angle" "180" "targetname" "t12" "sounds" "3" "speed" "200" "wait" "-1" "lip" "-2" "model" "*7" } { "classname" "func_door" "angle" "0" "speed" "200" "wait" "-1" "lip" "-2" "model" "*8" } { "classname" "light" "origin" "160 -304 112" "light" "170" } { "classname" "light" "origin" "160 640 104" "light" "200" } { "classname" "func_door" "angle" "-1" "targetname" "t14" "sounds" "1" "model" "*9" } { "classname" "trigger_multiple" "target" "t14" "wait" "10" "model" "*10" } { "targetname" "t28" "classname" "func_door" "angle" "-1" "wait" "-1" "sounds" "1" "speed" "200" "spawnflags" "2048" "model" "*11" } { "angle" "270" "classname" "func_button" "target" "t15" "wait" "-1" "lip" "2" "sounds" "1" "spawnflags" "2048" "model" "*12" } { "classname" "light" "origin" "-296 432 0" "light" "200" } { "light" "200" "origin" "-312 416 152" "classname" "light" } { "classname" "light" "origin" "-184 320 146" "light" "200" } { "classname" "item_key2" "origin" "-552 192 -40" "sounds" "1" "spawnflags" "2048" } { "classname" "item_spikes" "origin" "-680 88 -48" } { "classname" "func_door" "angle" "-2" "spawnflags" "33" "speed" "10" "sounds" "3" "wait" "-1" "targetname" "t16" "dmg" "100" "model" "*13" } { "sounds" "3" "classname" "func_door" "angle" "90" "spawnflags" "2056" "wait" "-1" "model" "*14" } { "spawnflags" "2056" "angle" "270" "classname" "func_door" "wait" "-1" "model" "*15" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t16" "lip" "12" "model" "*16" } { "classname" "light" "origin" "888 1080 -104" "light" "160" } { "light" "160" "origin" "888 888 -104" "classname" "light" } { "classname" "light" "origin" "880 696 -104" "light" "160" } { "light" "160" "origin" "696 888 -104" "classname" "light" } { "classname" "light" "origin" "696 1080 -104" "light" "160" } { "light" "200" "origin" "696 672 -104" "classname" "light" } { "classname" "light" "origin" "568 512 -104" "light" "200" } { "light" "160" "origin" "840 504 -104" "classname" "light" } { "classname" "light" "origin" "832 328 -104" "light" "160" } { "classname" "light" "origin" "936 512 96" "light" "200" } { "classname" "light" "origin" "-248 1080 56" "light" "150" } { "classname" "light" "origin" "888 1264 176" "light" "170" } { "classname" "func_door" "angle" "-2" "targetname" "t17" "sounds" "1" "model" "*17" } { "classname" "trigger_multiple" "target" "t17" "wait" "5" "model" "*18" } { "classname" "light" "origin" "160 120 -24" "light" "160" } { "spawnflags" "256" "classname" "trigger_multiple" "target" "t18" "targetname" "t23" "model" "*19" } { "wait" "0.5" "classname" "trap_spikeshooter" "origin" "88 368 40" "angle" "0" "targetname" "t18" } { "classname" "func_wall" "spawnflags" "2048" "model" "*20" } { "classname" "monster_demon1" "origin" "-160 608 128" "targetname" "t19" } { "classname" "trigger_once" "target" "t19" "model" "*21" } { "classname" "light" "origin" "-528 512 -104" "light" "200" } { "light" "200" "origin" "-344 592 -104" "classname" "light" } { "classname" "light" "origin" "-336 760 -104" "light" "200" } { "light" "200" "origin" "-432 856 -104" "classname" "light" } { "classname" "monster_ogre" "origin" "-416 440 -40" "spawnflags" "1536" "target" "t20" } { "classname" "monster_shambler" "origin" "-272 296 -40" "spawnflags" "256" "target" "t20" } { "classname" "path_corner" "origin" "-328 272 -56" "targetname" "t20" "target" "t21" } { "origin" "-400 480 -56" "classname" "path_corner" "target" "t20" "targetname" "t21" } { "classname" "item_health" "origin" "-600 144 -64" } { "classname" "weapon_supershotgun" "origin" "440 512 0" "spawnflags" "2048" } { "classname" "light" "origin" "-120 176 184" "light" "250" } { "origin" "-96 0 184" "classname" "light" "light" "200" } { "classname" "light" "origin" "312 116 -48" "light" "200" } { "classname" "path_corner" "origin" "8 112 32" "target" "t25" "targetname" "t24" } { "origin" "312 112 32" "classname" "path_corner" "targetname" "t25" "target" "t24" } { "classname" "monster_ogre" "origin" "112 112 48" "target" "t24" "spawnflags" "256" } { "classname" "item_shells" "origin" "88 -160 0" "spawnflags" "1" } { "light" "250" "classname" "light" "origin" "-352 144 56" } { "classname" "monster_demon1" "origin" "-80 -440 -296" "spawnflags" "256" "target" "t26" } { "classname" "path_corner" "origin" "-216 -456 -312" "targetname" "t26" "target" "t27" } { "origin" "536 -448 -312" "classname" "path_corner" "target" "t26" "targetname" "t27" } { "light" "200" "origin" "320 232 -104" "classname" "light" } { "classname" "light" "origin" "312 0 -104" "light" "200" } { "light" "160" "origin" "-8 0 -104" "classname" "light" } { "classname" "light" "origin" "-8 232 -104" "light" "200" } { "light" "200" "origin" "-16 112 -104" "classname" "light" } { "classname" "light" "origin" "-248 -8 -104" "light" "200" } { "light" "200" "origin" "-472 120 -104" "classname" "light" } { "wait" "-1" "classname" "func_door" "angle" "-1" "targetname" "t15" "sounds" "1" "spawnflags" "2048" "model" "*22" } { "classname" "func_door" "angle" "-2" "spawnflags" "2081" "targetname" "t28" "wait" "10" "speed" "200" "sounds" "1" "model" "*23" } { "classname" "trigger_once" "target" "t28" "model" "*24" } { "classname" "trigger_once" "target" "t12" "model" "*25" } { "classname" "monster_ogre" "origin" "160 1432 128" "angle" "270" } { "classname" "monster_ogre" "origin" "-216 784 128" "angle" "90" } { "classname" "info_teleport_destination" "origin" "-360 888 24" "spawnflags" "2048" "targetname" "t1" } { "classname" "monster_zombie" "origin" "-288 -232 -296" "angle" "270" } { "classname" "monster_zombie" "origin" "168 -8 -104" "angle" "90" } { "classname" "monster_ogre" "origin" "648 1232 -64" "angle" "180" } { "sounds" "1" "classname" "func_door" "angle" "-2" "targetname" "t29" "model" "*26" } { "classname" "monster_ogre" "origin" "520 752 24" "angle" "90" "spawnflags" "256" "targetname" "t29" } { "classname" "trigger_once" "target" "t29" "model" "*27" } { "classname" "weapon_nailgun" "origin" "152 1608 136" "spawnflags" "2048" } { "classname" "path_corner" "origin" "544 896 8" "targetname" "t30" "target" "t31" } { "origin" "56 896 72" "classname" "path_corner" "target" "t30" "targetname" "t31" } { "classname" "path_corner" "origin" "168 552 8" "targetname" "t32" "target" "t33" } { "origin" "168 1392 8" "classname" "path_corner" "target" "t32" "targetname" "t33" } { "classname" "monster_knight" "origin" "240 584 24" "target" "t32" } { "classname" "monster_knight" "origin" "504 960 24" "target" "t30" "spawnflags" "256" } { "classname" "monster_knight" "origin" "-16 896 88" "angle" "0" } { "classname" "monster_knight" "origin" "256 1224 24" "angle" "225" "spawnflags" "256" } { "target" "t49" "origin" "-24 1064 16" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "45" "origin" "-184 1080 128" "classname" "monster_ogre" } { "angle" "45" "origin" "-256 1216 128" "classname" "monster_knight" } { "targetname" "t16" "angle" "270" "origin" "784 520 56" "classname" "monster_demon1" } { "classname" "path_corner" "origin" "-352 888 16" "targetname" "t34" "target" "t35" } { "origin" "-120 888 8" "classname" "path_corner" "target" "t34" "targetname" "t35" } { "classname" "monster_ogre" "origin" "-184 912 24" "target" "t34" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-720 896 64" } { "classname" "monster_knight" "origin" "-344 760 24" "angle" "135" "spawnflags" "256" } { "classname" "monster_knight" "origin" "-392 584 24" "angle" "90" "spawnflags" "256" } { "angle" "90" "classname" "monster_knight" "origin" "-528 528 24" "spawnflags" "768" } { "targetname" "t37" "target" "t36" "origin" "-896 968 48" "classname" "path_corner" } { "target" "t37" "targetname" "t36" "classname" "path_corner" "origin" "-896 568 48" } { "spawnflags" "256" "target" "t36" "origin" "-840 600 24" "classname" "monster_ogre" } { "style" "32" "targetname" "t15" "light" "200" "origin" "-56 304 152" "classname" "light" } { "dmg" "100" "speed" "200" "targetname" "t15" "target" "t38" "classname" "func_train" "model" "*28" } { "target" "t39" "targetname" "t40" "origin" "-216 280 104" "classname" "path_corner" } { "target" "t40" "targetname" "t38" "classname" "path_corner" "origin" "-16 280 104" } { "target" "t38" "wait" "-1" "targetname" "t39" "origin" "-16 280 104" "classname" "path_corner" } { "angle" "180" "origin" "680 1472 24" "classname" "monster_ogre" "spawnflags" "256" } { "spawnflags" "256" "angle" "180" "origin" "864 1448 24" "classname" "monster_knight" } { "target" "t42" "targetname" "t41" "origin" "1024 1264 104" "classname" "path_corner" } { "targetname" "t42" "target" "t41" "classname" "path_corner" "origin" "704 1264 104" } { "target" "t41" "origin" "1056 1320 120" "classname" "monster_knight" } { "spawnflags" "257" "origin" "552 1280 128" "classname" "monster_knight" } { "spawnflags" "1" "origin" "432 1280 128" "classname" "monster_knight" } { "spawnflags" "2048" "angle" "0" "wait" "-1" "sounds" "0" "health" "1" "target" "t28" "classname" "func_button" "model" "*29" } { "origin" "-72 296 104" "classname" "item_health" } { "classname" "item_health" "origin" "-64 504 104" } { "origin" "-312 192 -64" "classname" "item_health" } { "spawnflags" "1" "origin" "-80 384 -64" "classname" "item_spikes" } { "origin" "-224 976 104" "classname" "item_shells" } { "target" "t666" "classname" "trigger_multiple" "wait" "10" "model" "*30" } { "target" "t45" "targetname" "t44" "origin" "984 568 8" "classname" "path_corner" } { "target" "t46" "targetname" "t45" "classname" "path_corner" "origin" "976 464 8" } { "target" "t47" "targetname" "t46" "origin" "1224 448 40" "classname" "path_corner" } { "target" "t44" "targetname" "t43" "classname" "path_corner" "origin" "1272 520 40" } { "target" "t48" "targetname" "t47" "classname" "path_corner" "origin" "1224 144 64" } { "targetname" "t48" "target" "t43" "origin" "1344 120 64" "classname" "path_corner" } { "target" "t45" "origin" "968 520 24" "classname" "monster_ogre" } { "spawnflags" "256" "target" "t43" "origin" "1312 328 80" "classname" "monster_knight" } { "spawnflags" "768" "target" "t47" "origin" "1240 296 80" "classname" "monster_ogre" } { "origin" "-360 1064 -8" "classname" "weapon_grenadelauncher" } { "target" "t50" "targetname" "t49" "origin" "-16 1168 0" "classname" "path_corner" } { "targetname" "t50" "target" "t49" "classname" "path_corner" "origin" "-232 1168 0" } { "origin" "1448 -128 -56" "classname" "light" } { "wait" "-1" "classname" "func_door" "angle" "270" "model" "*31" } { "wait" "-1" "targetname" "t52" "sounds" "3" "classname" "func_door" "angle" "90" "model" "*32" } { "classname" "light" "origin" "1984 -184 288" "light" "350" } { "classname" "light" "origin" "1760 -312 -184" "light" "200" } { "origin" "1832 -64 -184" "classname" "light" "light" "200" } { "light" "160" "origin" "1808 -296 -24" "classname" "light" } { "classname" "light" "origin" "1224 -8 -184" "light" "160" } { "light" "160" "origin" "1240 -208 -184" "classname" "light" } { "classname" "light" "origin" "1680 -104 -184" "light" "160" } { "light" "160" "origin" "1584 -304 -184" "classname" "light" } { "origin" "1592 -72 288" "classname" "light" } { "classname" "light" "origin" "1328 -232 288" } { "classname" "light" "origin" "1280 -16 327" "light" "250" } { "classname" "light" "origin" "1792 -152 88" "light" "160" } { "light" "160" "origin" "1632 -296 88" "classname" "light" } { "origin" "1696 -280 288" "classname" "light" } { "classname" "light" "origin" "1240 -224 -8" "light" "200" } { "classname" "func_wall" //"spawnflags" "3072" "model" "*33" } { "classname" "func_wall" //"spawnflags" "3072" "model" "*34" } { "classname" "func_wall" //"spawnflags" "3072" "model" "*35" } { "classname" "func_wall" //"spawnflags" "3072" "model" "*36" } { "classname" "func_wall" //"spawnflags" "3072" "model" "*37" } { "classname" "monster_ogre" "origin" "1992 -192 200" "angle" "180" "spawnflags" "256" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2" "targetname" "t51" "model" "*38" } { "classname" "trigger_multiple" "target" "t51" "model" "*39" } { "classname" "func_plat" "model" "*40" } { "classname" "light" "origin" "1480 56 -168" "light" "160" } { "origin" "1432 280 -64" "classname" "light" "light" "160" } { "light" "160" "classname" "light" "origin" "1424 280 96" } { "light" "160" "origin" "1472 232 -168" "classname" "light" } { "classname" "monster_zombie" "origin" "1592 -24 160" "angle" "180" } { "classname" "monster_zombie" "origin" "1432 -304 112" "angle" "135" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "1304 -288 112" "angle" "90" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "1576 -216 136" "angle" "180" "spawnflags" "768" } { "classname" "monster_zombie" "origin" "1928 -80 200" "spawnflags" "768" "angle" "180" } { "angle" "180" "spawnflags" "768" "origin" "1928 -280 200" "classname" "monster_zombie" } { "classname" "trigger_changelevel" "map" "e2m3" "model" "*41" } { "classname" "light" "origin" "80 1544 40" "light" "160" } { "light" "160" "origin" "-112 1544 40" "classname" "light" } { "classname" "item_shells" "origin" "1056 552 8" } { "classname" "light" "origin" "-112 1672 40" "light" "160" } { "light" "160" "origin" "88 1680 40" "classname" "light" } { "classname" "item_health" "origin" "-168 1688 -8" "spawnflags" "1" } { "classname" "monster_knight" "origin" "-112 1616 16" "angle" "45" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "1760 -208 -216" "angle" "180" } { "classname" "trigger_secret" "model" "*42" } { "classname" "trigger_secret" "model" "*43" } { "classname" "trigger_secret" "model" "*44" } { "classname" "trigger_multiple" "target" "t29" "model" "*45" } { "classname" "item_shells" "origin" "-144 -1728 288" "spawnflags" "768" } { "classname" "item_rockets" "origin" "2000 -304 176" "spawnflags" "1793" } { "classname" "item_rockets" "origin" "2000 -112 176" "spawnflags" "1793" } { "origin" "-62 -702 72" "classname" "ambient_swamp1" } { "classname" "ambient_swamp2" "origin" "386 -702 72" } { "origin" "-246 -470 -264" "classname" "ambient_swamp2" } { "classname" "ambient_swamp1" "origin" "554 -454 -264" } { "origin" "162 -430 -264" "classname" "ambient_swamp1" } { "spawnflags" "1" "origin" "-72 576 104" "classname" "item_shells" } { "spawnflags" "2048" "wait" "10" "target" "t16" "classname" "trigger_multiple" "model" "*46" } { "targetname" "t16" "sounds" "4" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*47" } { "origin" "-184 1480 168" "classname" "light" "light" "160" } { "classname" "light" "origin" "-224 1592 168" "light" "100" } { "target" "t52" "classname" "trigger_once" "model" "*48" } { "mangle" "20 30 0" "origin" "1224 -288 336" "classname" "info_intermission" } { "mangle" "20 180 0" "origin" "-352 760 240" "classname" "info_intermission" } { "mangle" "20 135 0" "origin" "480 -440 208" "classname" "info_intermission" } { "angle" "90" "origin" "-176 -1904 264" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-128 -1848 264" "angle" "90" } { "angle" "90" "origin" "-192 -1808 264" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-320 -1824 264" "angle" "90" } { "spawnflags" "1792" "classname" "func_wall" "model" "*49" } { "spawnflags" "1792" "origin" "200 -664 0" "classname" "weapon_lightning" } { "origin" "-184 1512 144" "classname" "item_artifact_super_damage" } { "classname" "item_cells" "origin" "240 -664 0" "spawnflags" "1793" } { "classname" "item_cells" "origin" "392 640 0" "spawnflags" "1793" } { "classname" "item_cells" "origin" "-168 456 104" "spawnflags" "1793" } { "classname" "func_door" "angle" "-1" "spawnflags" "1" "wait" "6" "speed" "1000" "sounds" "3" "targetname" "t15" "model" "*50" } { "classname" "weapon_grenadelauncher" "origin" "1312 280 56" "spawnflags" "3584" } { "sounds" "2" "wait" "5" "message" "Shoot the buttons..." "spawnflags" "3584" "classname" "trigger_multiple" "targetname" "t53" "model" "*51" } { "classname" "trigger_relay" "origin" "-72 -320 48" "targetname" "t13" "killtarget" "t53" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "-256 -1952 300" "classname" "item_flag_team1" } { "angle" "90" "origin" "-336 -1872 264" "classname" "info_player_team1" } { "angle" "90" "origin" "-256 -1872 264" "classname" "info_player_team1" } { "angle" "90" "origin" "-176 -1872 264" "classname" "info_player_team1" } { "angle" "90" "origin" "-346 -1724 248" "classname" "info_player_team1" } { "angle" "90" "origin" "-266 -1724 248" "classname" "info_player_team1" } { "angle" "90" "origin" "-186 -1724 248" "classname" "info_player_team1" } // team2 { "origin" "2062 -176 240" "classname" "item_flag_team2" } { "angle" "180" "origin" "1982 -276 200" "classname" "info_player_team2" } { "angle" "180" "origin" "1982 -176 200" "classname" "info_player_team2" } { "angle" "180" "origin" "1982 -76 200" "classname" "info_player_team2" } { "angle" "180" "origin" "1902 -276 200" "classname" "info_player_team2" } { "angle" "180" "origin" "1902 -176 200" "classname" "info_player_team2" } { "angle" "180" "origin" "1902 -76 200" "classname" "info_player_team2" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m3.ent000066400000000000000000001156371475442401000252070ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/jr_med.wad" "worldtype" "0" "sounds" "9" "message" "the Crypt of Decay" } { "classname" "light" "origin" "192 -648 128" } { "classname" "info_player_start" "origin" "688 -1600 -312" "angle" "180" } { "classname" "light_flame_large_yellow" "origin" "650 -438 4" } { "origin" "386 -438 4" "classname" "light_flame_large_yellow" } { "origin" "66 -886 4" "classname" "light_flame_large_yellow" } { "origin" "322 -886 4" "classname" "light_flame_large_yellow" } { "light" "250" "origin" "192 -1408 288" "classname" "light" } { "light" "250" "classname" "light" "origin" "192 -1088 288" } { "light" "250" "origin" "112 -1248 272" "classname" "light" } { "light" "250" "classname" "light" "origin" "272 -1248 272" } { "light" "200" "origin" "192 -1056 32" "classname" "light" } { "light" "150" "origin" "192 -1248 24" "classname" "light" } { "origin" "194 -1462 108" "classname" "light_flame_large_yellow" } { "origin" "194 -1030 164" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "192 -1440 32" "classname" "light" } { "sounds" "2" "classname" "func_plat" "spawnflags" "1" "model" "*1" } { "origin" "226 -1670 -212" "classname" "light_flame_large_yellow" } { "light" "150" "origin" "88 -1552 -184" "classname" "light" } { "origin" "-22 -1374 -212" "classname" "light_flame_large_yellow" } { "light" "150" "origin" "328 -1256 -184" "classname" "light" } { "light" "150" "classname" "light" "origin" "56 -1256 -184" } { "classname" "light" "origin" "248 -1480 -184" "light" "150" } { "light" "250" "origin" "552 -1608 -72" "classname" "light" } { "light" "150" "origin" "432 -1656 -224" "classname" "light" } { "light" "150" "origin" "432 -1496 -224" "classname" "light" } { "light" "100" "origin" "192 -1248 -40" "classname" "light" } { "origin" "10 -438 4" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-254 -438 4" } { "light" "150" "origin" "192 -704 -136" "classname" "light" } { "light" "250" "origin" "192 -512 -136" "classname" "light" } { "classname" "light" "origin" "416 -512 -136" "light" "150" } { "light" "150" "origin" "-32 -512 -136" "classname" "light" } { "classname" "light" "origin" "-208 -512 -136" "light" "150" } { "light" "150" "origin" "592 -512 -136" "classname" "light" } { "classname" "light" "origin" "192 -840 -136" "light" "150" } { "light" "150" "origin" "-352 -672 -168" "classname" "light" } { "classname" "light" "origin" "-320 -832 -168" "light" "150" } { "light" "150" "origin" "-320 -512 -168" "classname" "light" } { "classname" "light" "origin" "696 -512 -168" "light" "150" } { "light" "150" "origin" "736 -672 -168" "classname" "light" } { "classname" "light" "origin" "704 -832 -168" "light" "150" } { "light" "150" "origin" "512 -864 -168" "classname" "light" } { "classname" "light" "origin" "-128 -864 -168" "light" "150" } { "light" "200" "origin" "-128 -320 8" "classname" "light" } { "classname" "light" "origin" "512 -320 8" "light" "200" } { "origin" "384 -24 32" "classname" "light" } { "classname" "light" "origin" "0 -24 32" } { "light" "200" "origin" "416 -192 -8" "classname" "light" } { "classname" "light" "origin" "-32 -192 -8" "light" "200" } { "light" "200" "origin" "840 48 72" "classname" "light" } { "light" "150" "origin" "576 -24 -56" "classname" "light" } { "light" "200" "origin" "624 -24 72" "classname" "light" } { "origin" "1002 354 -60" "classname" "light_flame_large_yellow" } { "light" "100" "origin" "1000 352 -128" "classname" "light" } { "classname" "light" "origin" "736 8 72" "light" "200" } { "light" "200" "origin" "936 88 72" "classname" "light" } { "light" "150" "origin" "688 -8 -32" "classname" "light" } { "classname" "light" "origin" "784 24 -104" "light" "150" } { "light" "150" "origin" "888 72 -32" "classname" "light" } { "light" "200" "origin" "872 208 -56" "classname" "light" } { "classname" "light" "origin" "872 400 -56" "light" "200" } { "light" "200" "origin" "872 592 -56" "classname" "light" } { "classname" "light" "origin" "744 568 88" "light" "150" } { "light" "150" "origin" "744 648 88" "classname" "light" } { "classname" "light" "origin" "704 608 -80" "light" "150" } { "origin" "866 730 -60" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "864 728 -128" "light" "100" } { "sounds" "3" "wait" "-1" "targetname" "t8" "spawnflags" "2049" "angle" "0" "classname" "func_door" "model" "*2" } { "spawnflags" "2048" "angle" "90" "target" "t8" "classname" "func_button" "wait" "-1" "model" "*3" } { "origin" "520 608 -64" "classname" "light" } { "light" "400" "origin" "192 608 -24" "classname" "light" } { "sounds" "1" "wait" "-1" "angle" "270" "spawnflags" "2058" "classname" "func_door_secret" "targetname" "t9" "model" "*4" } { "light" "150" "origin" "1064 640 -112" "classname" "light" } { "targetname" "t9" "angle" "180" "origin" "1024 640 -152" "classname" "monster_zombie" } { "targetname" "t9" "angle" "180" "origin" "1120 672 -152" "classname" "monster_zombie" } { "targetname" "t9" "angle" "180" "origin" "1088 600 -152" "classname" "monster_zombie" } { "origin" "976 336 -176" "classname" "item_health" } { "light" "150" "origin" "192 608 -104" "classname" "light" } { "origin" "192 288 -64" "classname" "light" } { "classname" "light_flame_large_yellow" "origin" "66 106 4" "light" "200" } { "light" "200" "origin" "-30 106 4" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "504 120 -248" "light" "200" } { "light" "200" "origin" "704 224 -248" "classname" "light" } { "classname" "light" "origin" "704 472 -248" "light" "200" } { "light" "200" "origin" "304 112 -248" "classname" "light" } { "classname" "light" "origin" "80 112 -248" "light" "200" } { "light" "200" "origin" "720 608 -248" "classname" "light" } { "spawnflags" "2048" "sounds" "1" "wait" "-1" "targetname" "t3" "classname" "func_door" "angle" "90" "model" "*5" } { "spawnflags" "2048" "wait" "-1" "angle" "270" "classname" "func_door" "message" "This door opens nearby..." "model" "*6" } { "spawnflags" "2048" "target" "t3" "wait" "-1" "classname" "func_button" "angle" "180" "model" "*7" } { "light" "250" "origin" "-448 184 0" "classname" "light" } { "light" "150" "origin" "-552 280 -224" "classname" "light" } { "classname" "light" "origin" "-392 280 -224" "light" "150" } { "light" "150" "origin" "-416 -32 104" "classname" "light" } { "classname" "light" "origin" "-320 -32 104" "light" "150" } { "light" "150" "origin" "-224 -32 104" "classname" "light" } { "light" "250" "origin" "-352 -32 -32" "classname" "light" } { "light" "200" "origin" "-1160 88 -248" "classname" "light" } { "light" "200" "origin" "-1048 88 -32" "classname" "light" } { "light" "200" "classname" "light" "origin" "-1160 224 -32" } { "origin" "-742 658 -44" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-926 658 -44" } { "light" "200" "origin" "-736 632 -96" "classname" "light" } { "classname" "light" "origin" "-928 632 -96" "light" "200" } { "light" "150" "origin" "-600 104 -248" "classname" "light" } { "classname" "light" "origin" "-696 424 -248" "light" "150" } { "light" "150" "origin" "-1152 408 -248" "classname" "light" } { "classname" "light" "origin" "-944 432 -248" "light" "150" } { "light" "150" "origin" "-856 64 -248" "classname" "light" } { "classname" "light" "origin" "-160 152 -248" "light" "150" } { "light" "150" "origin" "-160 448 -248" "classname" "light" } { "classname" "light" "origin" "-328 464 -248" "light" "150" } { "light" "150" "origin" "-256 176 -248" "classname" "light" } { "origin" "-574 410 -172" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-470 410 -172" } { "target" "t4" "classname" "trigger_teleport" "model" "*8" } { "light" "200" "style" "2" "origin" "-760 576 -216" "classname" "light" } { "targetname" "t4" "angle" "180" "origin" "120 -32 -112" "classname" "info_teleport_destination" } { "light" "200" "origin" "-264 384 112" "classname" "light" } { "classname" "light" "origin" "-264 288 112" "light" "200" } { "light" "200" "origin" "-264 192 112" "classname" "light" } { "classname" "light" "origin" "-264 480 112" "light" "200" } { "light" "250" "origin" "-264 304 -56" "classname" "light" } { "classname" "light" "origin" "-520 424 0" "light" "250" } { "light" "200" "origin" "-1120 608 72" "classname" "light" } { "classname" "light" "origin" "-1024 584 72" "light" "200" } { "light" "200" "origin" "-928 584 72" "classname" "light" } { "classname" "light" "origin" "-832 584 72" "light" "200" } { "light" "200" "origin" "-544 584 72" "classname" "light" } { "classname" "light" "origin" "-640 584 72" "light" "200" } { "light" "150" "origin" "-480 768 56" "classname" "light" } { "classname" "light" "origin" "-384 768 56" "light" "150" } { "classname" "light" "origin" "-712 120 -32" "light" "200" } { "sounds" "3" "wait" "-1" "targetname" "t5" "spawnflags" "2049" "angle" "180" "classname" "func_door" "model" "*9" } { "spawnflags" "2048" "angle" "270" "target" "t5" "wait" "-1" "classname" "func_button" "model" "*10" } { "style" "32" "targetname" "t5" "light" "200" "origin" "-352 552 -56" "classname" "light" } { "light" "150" "origin" "-432 768 -56" "classname" "light" } { "light" "150" "origin" "-520 680 -56" "classname" "light" } { "spawnflags" "2048" "sounds" "3" "targetname" "t5" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*11" } { "sounds" "3" "targetname" "t5" "spawnflags" "2049" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*12" } { "origin" "-72 848 -56" "classname" "light" } { "origin" "-120 600 -8" "classname" "light" } { "classname" "light" "origin" "192 904 -8" } { "light" "200" "origin" "192 888 -248" "classname" "light" } { "classname" "light" "origin" "-104 600 -248" "light" "200" } { "light" "200" "origin" "376 984 -120" "classname" "light" } { "classname" "light" "origin" "504 760 -120" "light" "200" } { "light" "200" "origin" "-32 608 200" "classname" "light" } { "spawnflags" "2048" "sounds" "3" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*13" } { "origin" "-16 1456 16" "classname" "light" } { "light" "200" "origin" "384 1248 -56" "classname" "light" } { "classname" "light" "origin" "384 1440 -56" "light" "200" } { "light" "150" "origin" "256 1440 -56" "classname" "light" } { "classname" "light" "origin" "192 1248 -56" "light" "200" } { "light" "200" "origin" "384 1344 -88" "classname" "light" } { "classname" "light" "origin" "192 1152 -88" "light" "200" } { "classname" "light" "origin" "8 1456 -120" "light" "200" } { "spawnflags" "2048" "sounds" "1" "classname" "item_key2" "origin" "-16 1456 -152" } { "classname" "func_door" "angle" "-1" "targetname" "t6" "speed" "400" "wait" "-1" "sounds" "4" "model" "*14" } { "classname" "func_door" "angle" "-1" "targetname" "t6" "speed" "400" "wait" "-1" "sounds" "4" "model" "*15" } { "classname" "func_door" "angle" "-1" "targetname" "t6" "speed" "400" "wait" "-1" "sounds" "4" "spawnflags" "2048" "model" "*16" } { "classname" "trigger_once" "target" "t6" "model" "*17" } { "classname" "light" "origin" "-192 1456 -136" "light" "80" } { "classname" "light" "origin" "-16 1280 -136" "light" "80" } { "spawnflags" "768" "classname" "monster_hell_knight" "origin" "-16 1280 -168" "angle" "90" "targetname" "t6" } { "spawnflags" "256" "angle" "270" "origin" "-16 1632 -168" "classname" "monster_hell_knight" "targetname" "t6" } { "classname" "monster_hell_knight" "origin" "-192 1456 -168" "angle" "0" "targetname" "t6" } { "classname" "light" "origin" "152 1440 -56" "light" "150" } { "classname" "item_shells" "origin" "-104 1512 -192" "spawnflags" "1" } { "wait" "-1" "classname" "func_door" "angle" "0" "spawnflags" "2056" "model" "*18" } { "wait" "-1" "classname" "func_door" "angle" "180" "spawnflags" "2056" "model" "*19" } { "classname" "light" "origin" "-1120 832 -48" "light" "250" } { "classname" "light" "origin" "-1120 976 -24" "light" "250" } { "classname" "light" "origin" "-1240 1296 216" "light" "200" } { "light" "200" "origin" "-1240 1416 216" "classname" "light" } { "classname" "light" "origin" "-1240 1176 216" "light" "200" } { "classname" "light" "origin" "-712 1416 216" "light" "200" } { "light" "200" "origin" "-712 1296 216" "classname" "light" } { "classname" "light" "origin" "-712 1176 216" "light" "200" } { "light" "200" "origin" "-856 1296 216" "classname" "light" } { "classname" "light" "origin" "-1096 1296 216" "light" "200" } { "light" "200" "origin" "-976 1296 216" "classname" "light" } { "classname" "light_flame_small_white" "origin" "-1318 1514 -8" } { "origin" "-1318 1514 64" "classname" "light_flame_small_white" } { "classname" "light_flame_small_white" "origin" "-1318 1514 144" } { "origin" "-634 1078 -8" "classname" "light_flame_small_white" } { "classname" "light_flame_small_white" "origin" "-634 1078 64" } { "origin" "-634 1078 144" "classname" "light_flame_small_white" } { "classname" "func_plat" "spawnflags" "1" "model" "*20" } { "classname" "light" "origin" "-320 1536 184" "light" "250" } { "classname" "light" "origin" "-376 1312 120" "light" "250" } { "classname" "light" "origin" "-16 1536 184" "light" "200" } { "light" "200" "origin" "-560 1312 56" "classname" "light" } { "classname" "light" "origin" "24 1120 216" "light" "150" } { "classname" "light" "origin" "192 608 176" "light" "200" } { "wait" "-1" "classname" "func_door" "angle" "90" "spawnflags" "2049" "targetname" "t7" "sounds" "1" "model" "*21" } { "light" "150" "origin" "400 1104 224" "classname" "light" } { "light" "150" "origin" "-200 1056 224" "classname" "light" } { "light" "200" "origin" "192 960 224" "classname" "light" } { "light" "200" "origin" "192 784 224" "classname" "light" } { "classname" "light" "origin" "672 264 184" "light" "200" } { "light" "200" "origin" "384 184 184" "classname" "light" } { "classname" "light" "origin" "512 256 8" "light" "200" } { "classname" "light" "origin" "8 184 200" "light" "200" } { "classname" "light" "origin" "584 744 200" "light" "200" } { "classname" "light" "origin" "0 432 200" "light" "200" } { "classname" "trigger_once" "targetname" "t8" "target" "t9" "delay" "10" "model" "*22" } { "classname" "light" "origin" "192 -72 216" "light" "250" } { "classname" "light" "origin" "360 -168 360" "light" "200" } { "classname" "light" "origin" "296 -168 360" "light" "200" } { "origin" "472 -168 368" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "408 -168 360" } { "classname" "light" "origin" "384 -168 248" "light" "200" } { "classname" "light" "origin" "936 -304 328" "light" "200" } { "light" "200" "origin" "1000 -232 360" "classname" "light" } { "classname" "light" "origin" "864 -232 360" "light" "200" } { "light" "200" "origin" "864 -368 360" "classname" "light" } { "classname" "light" "origin" "1000 -368 360" "light" "200" } { "classname" "light" "origin" "736 -248 280" "light" "200" } { "light" "200" "origin" "552 -216 280" "classname" "light" } { "classname" "light" "origin" "16 144 -32" "light" "200" } { "classname" "light" "origin" "0 432 -136" "light" "200" } { "classname" "light" "origin" "192 384 184" "light" "200" } { "light" "200" "origin" "192 192 184" "classname" "light" } { "spawnflags" "2048" "classname" "func_button" "wait" "-1" "target" "t7" "model" "*23" } { "style" "33" "targetname" "t7" "classname" "light" "origin" "176 1152 200" "target" "t10" } { "classname" "info_null" "origin" "292 1152 180" "targetname" "t10" } { "classname" "light" "origin" "192 1224 200" "light" "150" } { "light" "150" "origin" "192 1376 200" "classname" "light" } { "classname" "light" "origin" "192 1536 200" "light" "200" } { "light" "150" "origin" "192 1080 200" "classname" "light" } { "classname" "weapon_nailgun" "origin" "184 -1520 -272" } { "classname" "func_button" "target" "t11" "angle" "-1" "targetname" "t12" "lip" "4" "wait" "0.1" "speed" "300" "health" "1" "model" "*24" } { "classname" "func_door" "angle" "-2" "spawnflags" "1" "targetname" "t11" "wait" "10" "model" "*25" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "8" "targetname" "t11" "model" "*26" } { "classname" "light" "origin" "1248 -288 312" "light" "150" } { "light" "200" "origin" "1176 -400 352" "classname" "light" } { "classname" "item_health" "origin" "1336 -536 256" "spawnflags" "2" } { "classname" "light" "origin" "1320 -488 352" "light" "200" } { "classname" "trigger_multiple" "target" "t11" "wait" "10" "model" "*27" } { "classname" "item_armor1" "origin" "192 -592 -64" } { "classname" "item_shells" "origin" "176 592 -160" "spawnflags" "1" } { "classname" "weapon_nailgun" "origin" "-80 1456 -192" "spawnflags" "1792" } { "classname" "weapon_rocketlauncher" "origin" "56 1144 128" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "-736 608 -280" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "1120 -384 256" "spawnflags" "1" } { "classname" "item_rockets" "origin" "840 -432 192" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-456 312 -80" } { "classname" "monster_zombie" "origin" "-1152 96 -88" "spawnflags" "256" "target" "t36" } { "origin" "-1120 32 -88" "classname" "monster_zombie" "spawnflags" "768" "target" "t36" } { "classname" "monster_zombie" "origin" "-1192 168 -88" "target" "t36" } { "classname" "monster_shambler" "origin" "-1120 1104 -56" "angle" "270" } { "classname" "monster_hell_knight" "origin" "-336 1312 8" "angle" "180" } { "classname" "monster_ogre" "origin" "-698 1446 -56" "angle" "270" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "-888 1128 8" "angle" "90" "spawnflags" "256" } { "classname" "item_health" "origin" "-336 784 -128" } { "origin" "-408 608 -128" "classname" "item_health" } { "classname" "path_corner" "origin" "-1096 584 -120" "targetname" "t13" "target" "t14" } { "origin" "-496 584 -120" "classname" "path_corner" "targetname" "t14" "target" "t13" } { "classname" "monster_demon1" "origin" "-712 576 -104" "angle" "180" "target" "t13" } { "classname" "path_corner" "origin" "-528 472 -96" "targetname" "t15" "target" "t16" } { "origin" "-368 -32 -96" "classname" "path_corner" "target" "t15" "targetname" "t16" } { "classname" "monster_ogre" "origin" "-466 262 -56" "target" "t16" "spawnflags" "256" } { "target" "t22" "targetname" "t21" "origin" "56 -184 -120" "classname" "path_corner" } { "target" "t21" "targetname" "t20" "classname" "path_corner" "origin" "-128 -224 -120" } { "target" "t20" "targetname" "t19" "origin" "-128 -504 -56" "classname" "path_corner" } { "target" "t19" "targetname" "t18" "classname" "path_corner" "origin" "512 -504 -56" } { "target" "t18" "targetname" "t17" "origin" "512 -224 -120" "classname" "path_corner" } { "targetname" "t26" "target" "t17" "classname" "path_corner" "origin" "328 -184 -120" } { "target" "t23" "targetname" "t22" "classname" "path_corner" "origin" "-128 -200 -120" } { "target" "t24" "targetname" "t23" "classname" "path_corner" "origin" "-128 -552 -56" } { "target" "t25" "targetname" "t24" "origin" "512 -552 -56" "classname" "path_corner" } { "target" "t26" "targetname" "t25" "classname" "path_corner" "origin" "512 -200 -120" } { "spawnflags" "256" "target" "t21" "origin" "0 -184 -104" "classname" "monster_hell_knight" } { "spawnflags" "1" "origin" "376 -160 -104" "classname" "monster_hell_knight" } { "spawnflags" "768" "angle" "270" "origin" "190 -706 -40" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "90" "origin" "192 -1408 24" "classname" "monster_hell_knight" } { "origin" "40 -1424 0" "classname" "item_shells" "spawnflags" "1" } { "spawnflags" "1" "origin" "304 -1096 0" "classname" "item_health" } { "origin" "328 -1280 -272" "classname" "item_health" } { "origin" "40 -1256 -272" "classname" "item_spikes" } { "target" "t28" "targetname" "t27" "origin" "864 176 -168" "classname" "path_corner" } { "target" "t27" "targetname" "t28" "classname" "path_corner" "origin" "864 616 -168" } { "target" "t27" "origin" "862 446 -152" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "180" "origin" "526 -26 -104" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "0" "origin" "-72 -24 -104" "classname" "monster_hell_knight" } { "spawnflags" "256" "origin" "-274 -34 -104" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "270" "origin" "-512 760 -104" "classname" "monster_hell_knight" } { "spawnflags" "1793" "origin" "336 1104 128" "classname" "item_rockets" } { "angle" "45" "spawnflags" "256" "origin" "104 256 -136" "classname" "monster_zombie" } { "spawnflags" "769" "angle" "90" "origin" "192 488 -136" "classname" "monster_hell_knight" } { "wait" "1" "speed" "250" "lip" "16" "spawnflags" "5" "targetname" "t29" "dmg" "20" "angle" "180" "classname" "func_door" "model" "*28" } { "wait" "1" "targetname" "t29" "speed" "250" "dmg" "20" "lip" "16" "spawnflags" "5" "classname" "func_door" "sounds" "1" "model" "*29" } { "wait" "2" "target" "t29" "classname" "trigger_multiple" "model" "*30" } { "origin" "506 1762 -124" "classname" "light_torch_small_walltorch" "style" "1" } { "classname" "light_torch_small_walltorch" "origin" "274 2010 -124" } { "light" "200" "origin" "152 1824 -40" "classname" "light" } { "classname" "light" "origin" "288 1824 -40" "light" "200" } { "light" "200" "origin" "288 1696 -40" "classname" "light" } { "classname" "light" "origin" "152 1704 -40" "light" "200" } { "light" "220" "origin" "0 1704 -40" "classname" "light" } { "angle" "180" "classname" "func_door_secret" "targetname" "t35" "spawnflags" "16" "sounds" "1" "model" "*31" } { "spawnflags" "2" "origin" "-16 1816 -192" "classname" "item_health" } { "origin" "432 1672 -320" "classname" "light" "light" "220" } { "spawnflags" "1792" "origin" "-16 1752 -192" "classname" "item_rockets" } { "angle" "270" "origin" "-192 1580 168" "classname" "trap_spikeshooter" "targetname" "t32" } { "spawnflags" "256" "classname" "trap_spikeshooter" "origin" "236 1536 168" "angle" "180" "targetname" "t32" } { "classname" "trap_spikeshooter" "origin" "0 1580 168" "angle" "270" "targetname" "t32" } { "angle" "90" "origin" "-96 1492 168" "classname" "trap_spikeshooter" "targetname" "t32" } { "classname" "trap_spikeshooter" "origin" "148 1376 168" "angle" "0" "targetname" "t33" } { "angle" "180" "origin" "236 1256 168" "classname" "trap_spikeshooter" "targetname" "t33" } { "spawnflags" "256" "classname" "trap_spikeshooter" "origin" "192 1580 168" "angle" "270" "targetname" "t33" } { "spawnflags" "257" "angle" "90" "origin" "192 -16 153" "classname" "monster_hell_knight" } { "spawnflags" "257" "angle" "180" "origin" "864 -248 217" "classname" "monster_shambler" } { "angle" "180" "origin" "464 -184 185" "classname" "monster_hell_knight" } { "classname" "monster_hell_knight" "origin" "192 -176 153" "angle" "90" "spawnflags" "1" "target" "t31" } { "spawnflags" "769" "angle" "90" "origin" "190 1166 153" "classname" "monster_ogre" } { "spawnflags" "2048" "origin" "48 1456 -192" "classname" "weapon_grenadelauncher" } { "spawnflags" "1" "origin" "-96 1376 -192" "classname" "item_rockets" } { "angle" "270" "spawnflags" "768" "classname" "monster_ogre" "origin" "862 662 -152" } { "light" "120" "origin" "192 -352 -264" "classname" "light" } { "spawnflags" "768" "origin" "326 -1490 -248" "classname" "monster_ogre" "angle" "180" "target" "t42" } { "origin" "192 552 128" "classname" "item_health" } { "spawnflags" "1024" "classname" "item_health" "origin" "176 672 128" } { "spawnflags" "1025" "origin" "184 1312 128" "classname" "item_health" } { "classname" "item_health" "origin" "-16 1480 128" "spawnflags" "1025" } { "origin" "672 -328 176" "classname" "item_health" } { "classname" "item_health" "origin" "776 -192 176" } { "origin" "784 312 -176" "classname" "item_shells" } { "spawnflags" "256" "angle" "315" "origin" "-26 1094 152" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "406 1094 152" "angle" "225" "spawnflags" "768" } { "spawnflags" "1" "origin" "-200 1128 128" "classname" "item_rockets" } { "origin" "-550 -478 212" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-550 -166 212" } { "origin" "-214 -326 252" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "-120 -176 192" "classname" "light" } { "classname" "light" "origin" "56 -176 192" "light" "150" } { "origin" "-816 1488 -80" "classname" "item_health" } { "classname" "item_health" "origin" "-752 1488 -80" } { "spawnflags" "1536" "origin" "-688 1488 -80" "classname" "item_health" } { "spawnflags" "1" "origin" "176 1264 -160" "classname" "item_shells" } { "classname" "func_door" "angle" "270" "targetname" "t31" "wait" "-1" "spawnflags" "2048" "model" "*32" } { "wait" "-1" "sounds" "1" "speed" "300" "classname" "func_door" "angle" "90" "model" "*33" } { "speed" "300" "classname" "func_door" "angle" "270" "wait" "-1" "model" "*34" } { "classname" "item_health" "origin" "400 1464 -160" "spawnflags" "1024" } { "classname" "item_health" "origin" "-1136 528 -128" } { "classname" "monster_ogre" "origin" "-370 -218 88" "targetname" "t31" "spawnflags" "1" } { "classname" "monster_hell_knight" "origin" "-64 -176 152" "angle" "0" "spawnflags" "768" "targetname" "t31" } { "classname" "item_health" "origin" "-488 -480 64" } { "classname" "light" "origin" "680 -1600 -160" } { "classname" "item_spikes" "origin" "984 -192 192" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "-490 -410 88" "angle" "45" } { "classname" "trigger_multiple" "target" "t32" "wait" "1" "spawnflags" "1024" "targetname" "t44" "model" "*35" } { "classname" "trigger_multiple" "target" "t33" "wait" "1" "spawnflags" "1024" "model" "*36" } { "classname" "item_rockets" "origin" "-96 272 -384" } //{ //"classname" "weapon_supernailgun" //"origin" "-1200 208 -112" //"spawnflags" "1792" //} { "classname" "func_door_secret" "spawnflags" "2051" "targetname" "t36" "angle" "90" "model" "*37" } { "classname" "light" "origin" "-1288 640 -80" "light" "160" } { "light" "160" "origin" "-1288 128 -80" "classname" "light" } { "classname" "light" "origin" "-1288 264 -80" "light" "160" } { "light" "160" "origin" "-1288 392 -80" "classname" "light" } { "classname" "light" "origin" "-1288 520 -80" "light" "160" } { "classname" "func_door_secret" "targetname" "t36" "angle" "270" "spawnflags" "2049" "model" "*38" } { "classname" "item_armor2" "origin" "1128 600 -176" "spawnflags" "1024" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "11" "targetname" "t34" "model" "*39" } { "classname" "light_torch_small_walltorch" "origin" "-246 -1310 -204" "light" "250" } { "classname" "trigger_once" "target" "t34" "model" "*40" } { "classname" "item_spikes" "origin" "-240 -1288 -312" "spawnflags" "1" } { "spawnflags" "1" "origin" "-240 -1368 -312" "classname" "item_spikes" } { "sounds" "3" "classname" "func_door" "angle" "-2" "spawnflags" "3585" "wait" "90" "targetname" "t6" "model" "*41" } { "sounds" "3" "classname" "func_door" "targetname" "t6" "spawnflags" "3585" "angle" "-2" "wait" "90" "model" "*42" } { "sounds" "3" "classname" "func_door" "angle" "0" "spawnflags" "1537" "targetname" "t6" "wait" "90" "model" "*43" } { "classname" "light_torch_small_walltorch" "origin" "-42 1642 -108" "light" "200" } { "classname" "item_health" "origin" "-72 560 -384" } { "origin" "-152 560 -384" "classname" "item_health" } { "targetname" "t31" "spawnflags" "513" "angle" "90" "origin" "848 -376 216" "classname" "monster_hell_knight" } { "targetname" "t31" "spawnflags" "768" "origin" "-512 -248 88" "classname" "monster_shambler" } { "spawnflags" "768" "angle" "180" "origin" "382 1246 -136" "classname" "monster_ogre" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "190 1438 -136" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "640 -1664 -312" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "-400 -240 88" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "-216 1088 152" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "-512 792 -104" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "888 624 -152" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "-96 1456 -168" "angle" "0" } { "spawnflags" "2048" "classname" "func_wall" "model" "*44" } { "spawnflags" "2048" "classname" "func_wall" "model" "*45" } { "classname" "func_plat" "height" "192" "sounds" "2" "model" "*46" } { "classname" "item_health" "origin" "-1184 72 -352" } { "classname" "light" "origin" "-952 1408 80" "light" "200" } { "classname" "light" "origin" "-1120 1176 48" "light" "250" } { "classname" "light" "origin" "-104 288 -344" "light" "200" } { "classname" "light" "origin" "-512 376 -304" "light" "200" } { "classname" "trigger_multiple" "target" "t35" "model" "*47" } { "classname" "light" "origin" "192 -376 -16" "light" "150" } { "classname" "light" "origin" "192 -328 176" "light" "150" } { "classname" "trigger_multiple" "target" "t32" "spawnflags" "768" "wait" "0.5" "model" "*48" } { "classname" "trigger_multiple" "spawnflags" "768" "wait" "0.5" "target" "t33" "targetname" "t44" "model" "*49" } { "origin" "-1176 112 -112" "classname" "item_rockets" } { "origin" "-736 544 -280" "classname" "item_armorInv" } { "classname" "func_button" "angle" "180" "target" "t36" "model" "*50" } { "classname" "info_null" "origin" "-1332 1116 -36" "targetname" "t37" } { "classname" "light" "origin" "-1296 1120 -32" "target" "t37" "angle" "60" } { "spawnflags" "2048" "classname" "func_wall" "model" "*51" } { "spawnflags" "2048" "classname" "func_wall" "model" "*52" } { "classname" "light" "origin" "192 -152 -344" "light" "160" } { "classname" "light" "origin" "192 32 -344" "light" "160" } { "classname" "light" "origin" "32 168 -344" "light" "140" } { "light" "160" "origin" "-16 408 -344" "classname" "light" } { "classname" "light" "origin" "192 368 -344" "light" "140" } { "light" "140" "origin" "448 368 -344" "classname" "light" } { "classname" "light" "origin" "528 592 -344" "light" "200" } { "light" "200" "origin" "408 808 -344" "classname" "light" } { "classname" "light" "origin" "192 832 -344" "light" "200" } { "light" "200" "origin" "-40 728 -344" "classname" "light" } { "classname" "light" "origin" "-168 632 -344" "light" "200" } { "light" "200" "origin" "-160 976 -344" "classname" "light" } { "classname" "light" "origin" "592 456 -344" "light" "200" } { "classname" "light" "origin" "192 352 -232" "light" "200" } { "light" "200" "origin" "32 264 -232" "classname" "light" } { "classname" "light" "origin" "-184 432 -336" "light" "160" } { "light" "160" "origin" "-192 144 -336" "classname" "light" } { "classname" "light" "origin" "-776 280 -312" "light" "200" } { "light" "200" "origin" "-864 432 -312" "classname" "light" } { "classname" "light" "origin" "-1096 432 -312" "light" "200" } { "light" "200" "origin" "-1168 272 -312" "classname" "light" } { "classname" "light" "origin" "-944 64 -312" "light" "200" } { "light" "200" "origin" "-664 136 -312" "classname" "light" } { "light" "200" "origin" "-1112 592 -96" "classname" "light" } { "classname" "light" "origin" "-1040 1256 -32" "light" "150" } { "light" "200" "origin" "-880 1128 80" "classname" "light" } { "classname" "light" "origin" "-712 1400 -16" "light" "200" } { "classname" "light" "origin" "104 -600 -224" "light" "200" } { "light" "200" "origin" "280 -600 -224" "classname" "light" } { "classname" "trigger_changelevel" "map" "e2m4" "model" "*53" } { "light" "160" "origin" "-312 808 -72" "classname" "light" } { "light" "200" "origin" "192 1776 -312" "classname" "light" } { "classname" "light" "origin" "-392 568 -56" "light" "160" } { "classname" "light" "origin" "-1224 1504 8" "light" "170" } { "light" "170" "origin" "-1304 1392 8" "classname" "light" } { "classname" "light" "origin" "-640 1168 -8" "light" "170" } { "light" "160" "origin" "352 -1248 56" "classname" "light" } { "classname" "light" "origin" "40 -1248 56" "light" "160" } { "light" "160" "origin" "192 -1216 -176" "classname" "light" } { "classname" "light" "origin" "24 -1376 -232" "light" "160" } { "light" "160" "origin" "224 -1624 -232" "classname" "light" } { "classname" "light" "origin" "368 -1392 -232" "light" "160" } { "classname" "light" "origin" "8 -464 -40" "light" "140" } { "light" "140" "origin" "384 -464 -40" "classname" "light" } { "classname" "light" "origin" "-544 800 -56" "light" "140" } { "classname" "trigger_secret" "model" "*54" } { "classname" "trigger_secret" "model" "*55" } { "light" "200" "origin" "760 1856 -40" "classname" "light" } { "classname" "light" "origin" "760 1664 -40" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "538 1762 -124" "style" "1" "light" "200" } { "style" "1" "classname" "light_torch_small_walltorch" "origin" "850 1930 -124" "light" "200" } { "origin" "850 1618 -124" "classname" "light_torch_small_walltorch" "style" "1" "light" "200" } { "classname" "light" "origin" "912 1856 -40" "light" "200" } { "light" "200" "origin" "912 1664 -40" "classname" "light" } { "light" "200" "origin" "1064 1776 -172" "classname" "light" } { "light" "200" "origin" "1080 1856 -40" "classname" "light" } { "classname" "light" "origin" "1080 1664 -40" "light" "200" } { "classname" "light" "origin" "1176 1776 -172" "light" "200" } { "light" "170" "origin" "672 1768 -296" "classname" "light" } { "target" "t38" "classname" "trigger_teleport" "model" "*56" } { "targetname" "t38" "origin" "1144 1776 -88" "classname" "info_teleport_destination" } { "map" "e2m7" "classname" "trigger_changelevel" "model" "*57" } { "light" "160" "origin" "840 1768 -200" "classname" "light" } { "light" "140" "origin" "408 608 -344" "classname" "light" } { "classname" "item_spikes" "origin" "-16 240 -160" "spawnflags" "2048" } { "classname" "weapon_supernailgun" "origin" "-1256 1448 -80" } { "origin" "432 1160 152" "classname" "item_artifact_super_damage" } { "message" "The portal lies beyond..." "targetname" "t40" "wait" "-1" "speed" "20" "sounds" "4" "angle" "-2" "classname" "func_door" "model" "*58" } { "origin" "432 1672 -368" "classname" "item_armor2" } { "target" "t39" "sounds" "1" "wait" "-1" "classname" "func_button" "model" "*59" } { "message" "The underwater barrier is lowered..." "target" "t40" "targetname" "t39" "spawnflags" "1" "classname" "trigger_once" "model" "*60" } { "classname" "trigger_secret" "model" "*61" } { "light" "200" "origin" "-128 -704 -224" "classname" "light" } { "classname" "light" "origin" "512 -704 -224" "light" "200" } { "light" "200" "origin" "192 -832 -224" "classname" "light" } { "mangle" "20 240 0" "origin" "400 1048 240" "classname" "info_intermission" } { "mangle" "20 145 0" "origin" "-160 144 64" "classname" "info_intermission" } { "mangle" "-20 45 0" "origin" "-320 -824 -144" "classname" "info_intermission" } { "classname" "func_wall" "spawnflags" "1792" "model" "*62" } { "classname" "item_artifact_super_damage" "origin" "928 1768 -240" "spawnflags" "1792" } { "classname" "light" "origin" "8 1800 -120" "light" "220" } { "classname" "weapon_lightning" "origin" "1216 1784 -264" "spawnflags" "1792" } { "classname" "item_cells" "origin" "880 1648 -264" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "880 1864 -264" "classname" "item_cells" } { "spawnflags" "1792" "classname" "func_wall" "model" "*63" } { "spawnflags" "1792" "classname" "func_wall" "model" "*64" } { "spawnflags" "1792" "classname" "func_wall" "model" "*65" } { "classname" "info_player_coop" "origin" "664 -1520 -312" "angle" "180" } { "angle" "180" "origin" "592 -1600 -312" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "680 -1712 -312" "angle" "180" } { "classname" "air_bubbles" "origin" "720 1384 -320" } { "classname" "light" "origin" "680 1376 -312" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "2" "targetname" "t41" "model" "*66" } { "classname" "trigger_multiple" "target" "t41" "model" "*67" } { "origin" "688 1176 -312" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "480 1408 -312" } { "origin" "448 1552 -312" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "840 1080 -312" } { "origin" "840 1080 -160" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "840 1080 0" } { "classname" "light" "origin" "840 1080 232" "light" "200" } { "classname" "item_artifact_envirosuit" "origin" "576 1440 -344" } { "classname" "item_artifact_invulnerability" "origin" "544 1248 -344" } { "light" "200" "origin" "840 936 232" "classname" "light" } { "classname" "light" "origin" "840 760 232" "light" "150" } { "light" "120" "origin" "808 600 232" "classname" "light" } { "classname" "item_health" "origin" "824 960 152" } { "origin" "848 880 152" "classname" "item_health" } { "classname" "item_health" "origin" "808 768 152" } { "classname" "trigger_multiple" "message" "Welcome to the Well of Wishes!" "wait" "5" "sounds" "1" "model" "*68" } { "classname" "trigger_multiple" "sounds" "1" "wait" "3" "message" "The Dopefish Lives!" "model" "*69" } { "classname" "func_wall" "spawnflags" "1792" "model" "*70" } { "classname" "trigger_secret" "model" "*71" } { "spawnflags" "1" "origin" "-1312 1392 -80" "classname" "item_spikes" } { "classname" "func_wall" "spawnflags" "1792" "model" "*72" } { "classname" "light" "origin" "-544 600 -248" "light" "200" } { "light" "200" "classname" "light_torch_small_walltorch" "origin" "194 -214 196" "spawnflags" "2048" } { "light" "200" "origin" "352 984 -328" "classname" "light" } { "classname" "light" "origin" "96 976 -328" "light" "200" } { "classname" "light" "origin" "640 776 -336" "light" "200" } { "classname" "func_plat" "spawnflags" "1" "model" "*73" } { "classname" "monster_fish" "origin" "656 352 -336" "spawnflags" "256" } { "spawnflags" "256" "origin" "432 424 -336" "classname" "monster_fish" } { "classname" "monster_fish" "origin" "296 968 -336" "spawnflags" "256" } { "origin" "-48 800 -336" "classname" "monster_fish" } { "classname" "monster_fish" "origin" "-896 248 -312" } { "origin" "-744 328 -312" "classname" "monster_fish" } { "classname" "path_corner" "origin" "272 -1504 -264" "targetname" "t42" "target" "t43" } { "origin" "56 -1352 -264" "classname" "path_corner" "target" "t42" "targetname" "t43" } { "classname" "item_health" "origin" "312 -1336 -272" } { "origin" "544 -1488 -336" "classname" "item_health" } { "classname" "item_health" "origin" "312 1464 -160" } { "origin" "56 1488 -192" "classname" "item_health" } { "classname" "trigger_once" "killtarget" "t44" "spawnflags" "3072" "model" "*74" } { "classname" "item_rockets" "origin" "216 648 120" "spawnflags" "1" } { "classname" "item_shells" "origin" "136 648 120" "spawnflags" "1" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "-80 1456 -162" "classname" "item_flag_team1" } { "angle" "90" "origin" "-60 1360 -168" "classname" "info_player_team1" } { "angle" "90" "origin" "-60 1456 -168" "classname" "info_player_team1" } { "angle" "90" "origin" "-60 1526 -168" "classname" "info_player_team1" } { "angle" "90" "origin" "40 1360 -168" "classname" "info_player_team1" } { "angle" "90" "origin" "40 1456 -168" "classname" "info_player_team1" } { "angle" "90" "origin" "40 1526 -168" "classname" "info_player_team1" } // team2 { "origin" "-616 -322 108" "classname" "item_flag_team2" } { "angle" "0" "origin" "-610 -242 88" "classname" "info_player_team2" } { "angle" "0" "origin" "-610 -322 88" "classname" "info_player_team2" } { "angle" "0" "origin" "-610 -402 88" "classname" "info_player_team2" } { "angle" "0" "origin" "-530 -242 88" "classname" "info_player_team2" } { "angle" "0" "origin" "-530 -322 88" "classname" "info_player_team2" } { "angle" "0" "origin" "-530 -402 88" "classname" "info_player_team2" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m4.ent000066400000000000000000001312331475442401000251760ustar00rootroot00000000000000{ "wad" "gfx/wizard.wad" "classname" "worldspawn" "sounds" "5" "worldtype" "0" "message" "the Ebon Fortress" } { "classname" "info_player_start" "origin" "1456 312 344" "angle" "180" } { "classname" "light" "origin" "1312 944 488" "angle" "0" "light" "400" } { "classname" "light" "origin" "1536 944 376" "angle" "0" "light" "400" } { "light" "240" "classname" "light" "origin" "1552 1360 400" } { "classname" "light_torch_small_walltorch" "origin" "1850 1330 312" } { "classname" "light" "origin" "1464 1848 400" "angle" "0" "light" "250" } { "classname" "light" "origin" "1728 2032 240" "angle" "0" "light" "220" } { "classname" "light" "origin" "1920 2032 272" "angle" "0" } { "classname" "light_torch_small_walltorch" "origin" "2114 1778 308" "angle" "0" "style" "6" } { "classname" "light_torch_small_walltorch" "origin" "1762 2226 308" "angle" "0" "style" "1" } { "classname" "light_torch_small_walltorch" "origin" "2234 2298 308" "angle" "0" "style" "6" "light" "500" } { "classname" "light" "origin" "1280 2032 240" "angle" "0" "light" "220" } { "classname" "light" "origin" "1856 2032 72" "angle" "0" "light" "250" } { "classname" "light" "origin" "1792 1336 24" "angle" "0" "light" "100" } { "light" "250" "classname" "light" "origin" "1056 1480 288" "angle" "0" } { "light" "200" "classname" "light" "origin" "752 1696 320" } { "classname" "light" "origin" "616 2032 296" "light" "230" } { "classname" "light" "origin" "112 2032 280" "angle" "0" "light" "200" } { "classname" "light" "origin" "416 2032 280" "angle" "0" "light" "200" } { "classname" "light" "origin" "448 1696 464" "angle" "0" "light" "350" } { "classname" "light" "origin" "104 1696 352" "angle" "0" "light" "250" } { "classname" "light" "origin" "112 1360 280" "angle" "0" "light" "200" } { "classname" "light" "origin" "1048 1344 40" } { "classname" "light" "light" "220" "origin" "1128 1152 224" } { "classname" "light" "origin" "1280 1360 272" } { "light" "120" "classname" "light" "origin" "784 1368 272" } { "classname" "light" "light" "250" "origin" "800 1368 80" } { "classname" "light" "origin" "416 1360 280" "angle" "0" "light" "200" } { "classname" "light" "origin" "904 952 432" "angle" "0" "light" "400" } { "light" "250" "classname" "light" "origin" "-576 1904 688" "angle" "0" } { "light" "250" "classname" "light" "origin" "-256 1904 688" "angle" "0" } { "light" "250" "classname" "light" "origin" "-256 1592 688" "angle" "0" } { "light" "250" "classname" "light" "origin" "-576 1592 688" "angle" "0" } { "light" "200" "classname" "light" "origin" "-696 1960 584" "angle" "0" } { "light" "200" "classname" "light" "origin" "-696 1536 584" "angle" "0" } { "classname" "light" "origin" "-392 1712 352" "angle" "0" "light" "200" } { "light" "200" "classname" "light" "origin" "-136 1536 568" "angle" "0" } { "light" "200" "classname" "light" "origin" "-176 1936 560" "angle" "0" } { "classname" "light" "origin" "-32 1696 560" "angle" "0" "light" "200" } { "classname" "light" "light" "140" "origin" "856 2304 56" "angle" "0" } { "classname" "light" "light" "140" "origin" "1016 2488 56" "angle" "0" } { "classname" "light" "light" "140" "origin" "1136 2184 56" "angle" "0" } { "classname" "light" "light" "140" "origin" "776 2488 56" "angle" "0" } { "classname" "light" "light" "140" "origin" "800 2064 56" } { "classname" "light" "origin" "1960 1280 -80" "angle" "0" "light" "200" } { "classname" "light" "origin" "1304 312 608" "light" "200" } { "light" "200" "origin" "1368 432 608" "classname" "light" } { "classname" "light" "origin" "1368 184 608" "light" "200" } { "classname" "light" "origin" "1464 312 536" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "1322 466 476" } { "origin" "1322 154 476" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "1464 264 400" "light" "120" } { "light" "120" "origin" "1464 384 400" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "1082 306 444" "light" "200" } { "origin" "834 554 364" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "1048 312 312" "classname" "light" } { "light" "200" "origin" "816 320 376" "classname" "light" } { "sounds" "2" "spawnflags" "1" "classname" "func_plat" "model" "*1" "speed" "350" } { "light" "200" "origin" "832 352 96" "classname" "light" } { "classname" "light" "origin" "832 520 96" "light" "200" } { "light" "200" "origin" "840 600 -112" "classname" "light" } { "classname" "light" "origin" "840 600 96" "light" "160" } { "classname" "light" "origin" "936 744 -136" "light" "150" } { "classname" "light" "origin" "832 320 224" "light" "160" } { "light" "200" "origin" "824 888 -136" "classname" "light" } { "classname" "light" "origin" "784 1208 -64" "light" "160" } { "classname" "light" "origin" "824 1032 -136" "light" "200" } { "classname" "light" "origin" "1024 888 -136" "light" "200" } { "light" "200" "origin" "1264 880 -136" "classname" "light" } { "classname" "light" "origin" "1472 840 -136" "light" "200" } { "light" "200" "origin" "1680 864 -136" "classname" "light" } { "classname" "light" "origin" "1808 984 -136" "light" "200" } { "light" "200" "origin" "1688 1096 -16" "classname" "light" } { "light" "160" "origin" "1104 992 -64" "classname" "light" } { "classname" "light" "origin" "1472 960 -24" "light" "160" } { "angle" "0" "origin" "784 1192 432" "classname" "light" } { "classname" "light" "origin" "784 1176 96" "angle" "0" "light" "200" } { "angle" "0" "origin" "896 1000 96" "classname" "light" "light" "200" } { "classname" "light" "origin" "1128 952 96" "angle" "0" "light" "200" } { "angle" "0" "origin" "1360 1024 96" "classname" "light" "light" "200" } { "classname" "light" "origin" "1544 840 96" "angle" "0" "light" "200" } { "light" "200" "angle" "0" "origin" "1368 904 96" "classname" "light" } { "light" "200" "classname" "light" "origin" "1784 1176 96" "angle" "0" } { "angle" "0" "origin" "1808 1000 96" "classname" "light" "light" "200" } { "light" "200" "angle" "0" "origin" "1712 896 96" "classname" "light" } { "classname" "light" "origin" "1736 936 328" } { "origin" "1760 1144 376" "classname" "light" } { "classname" "light" "origin" "1280 1016 -136" "light" "200" } { "angle" "0" "origin" "1552 1224 136" "classname" "light" "light" "200" } { "light" "240" "angle" "0" "origin" "1544 1320 272" "classname" "light" } { "light" "160" "origin" "1632 952 8" "classname" "light" } { "classname" "light" "origin" "1472 1208 8" "light" "160" } { "light" "160" "origin" "1656 1208 8" "classname" "light" } { "classname" "light" "origin" "1440 1360 72" "light" "160" } { "light" "160" "origin" "1656 1360 72" "classname" "light" } { "classname" "light" "origin" "1608 1096 8" "light" "160" } { "angle" "0" "origin" "1464 1544 400" "classname" "light" "light" "250" } { "classname" "light" "origin" "1608 1544 400" "angle" "0" "light" "250" } { "angle" "0" "origin" "1608 1848 400" "classname" "light" "light" "250" } { "light" "220" "angle" "0" "origin" "1464 1848 72" "classname" "light" } { "classname" "light" "origin" "1464 1544 72" "angle" "0" "light" "220" } { "light" "220" "angle" "0" "origin" "1608 1544 72" "classname" "light" } { "classname" "light" "origin" "1608 1848 72" "angle" "0" "light" "220" } { "light" "220" "angle" "0" "origin" "1608 1696 224" "classname" "light" } { "classname" "light" "origin" "1464 1696 224" "angle" "0" "light" "220" } { "light" "160" "angle" "0" "origin" "1632 1984 0" "classname" "light" } { "classname" "light" "origin" "1440 1984 0" "angle" "0" "light" "160" } { "light" "220" "angle" "0" "origin" "1536 2032 240" "classname" "light" } { "light" "220" "angle" "0" "origin" "1280 1736 240" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "1282 1602 364" "style" "1" } { "classname" "light" "origin" "1280 1576 304" "light" "160" } { "light" "200" "angle" "0" "origin" "1856 2216 72" "classname" "light" } { "classname" "light" "origin" "2008 2168 16" "light" "140" } { "classname" "light" "origin" "2120 2144 136" "angle" "0" "light" "200" } { "light" "160" "angle" "0" "origin" "2120 2288 192" "classname" "light" } { "classname" "light" "origin" "2224 2184 192" "angle" "0" "light" "160" } { "light" "160" "angle" "0" "origin" "2216 2136 40" "classname" "light" } { "classname" "light" "origin" "2112 1856 40" "light" "200" } { "classname" "light" "origin" "2216 2080 40" "angle" "0" "light" "160" } { "classname" "light" "origin" "1848 1848 312" "light" "200" } { "light" "200" "origin" "1848 1608 312" "classname" "light" } { "classname" "light" "origin" "1848 1832 56" "light" "200" } { "light" "160" "origin" "1800 1720 56" "classname" "light" } { "classname" "light" "origin" "1784 1528 56" "light" "200" } { "classname" "light" "origin" "1904 1568 104" "light" "200" } { "light" "200" "angle" "0" "origin" "1816 1224 -80" "classname" "light" } { "light" "200" "style" "6" "origin" "1938 1354 4" "classname" "light_torch_small_walltorch" } { "light" "160" "origin" "1992 2264 312" "classname" "light" } { "light" "160" "origin" "2024 2032 312" "classname" "light" } { "angle" "0" "origin" "1280 1992 56" "light" "160" "classname" "light" } { "classname" "light" "light" "140" "origin" "1112 2032 56" "angle" "0" } { "origin" "920 2032 56" "light" "140" "classname" "light" } { "angle" "0" "origin" "1024 2304 56" "light" "140" "classname" "light" } { "classname" "light" "light" "140" "origin" "1136 2392 56" "angle" "0" } { "angle" "0" "origin" "1144 2512 56" "light" "140" "classname" "light" } { "classname" "light" "light" "160" "origin" "912 2184 56" "angle" "0" } { "origin" "760 2240 56" "light" "140" "classname" "light" } { "angle" "0" "origin" "1008 2184 56" "light" "140" "classname" "light" } { "classname" "light" "light" "160" "origin" "1280 1864 56" "angle" "0" } { "angle" "0" "origin" "1280 1720 56" "light" "160" "classname" "light" } { "light" "250" "angle" "0" "origin" "864 1480 288" "classname" "light" } { "light" "250" "angle" "0" "origin" "1056 1912 288" "classname" "light" } { "light" "250" "classname" "light" "origin" "864 1912 288" "angle" "0" } { "angle" "0" "origin" "1152 1680 56" "light" "160" "classname" "light" } { "classname" "light" "light" "160" "origin" "1152 1888 56" "angle" "0" } { "angle" "0" "origin" "1152 1504 56" "light" "160" "classname" "light" } { "origin" "738 1570 164" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "738 1818 164" } { "angle" "0" "origin" "752 1888 56" "light" "120" "classname" "light" } { "angle" "0" "origin" "1056 1856 0" "light" "160" "classname" "light" } { "classname" "light" "light" "160" "origin" "1056 1536 0" "angle" "0" } { "angle" "0" "origin" "1056 1696 0" "light" "160" "classname" "light" } { "classname" "light" "light" "120" "origin" "752 1504 56" "angle" "0" } { "classname" "light" "light" "160" "origin" "968 1856 56" "angle" "0" } { "angle" "0" "origin" "968 1696 56" "light" "160" "classname" "light" } { "classname" "light" "light" "160" "origin" "968 1536 56" "angle" "0" } { "classname" "light" "light" "160" "origin" "1152 1680 256" "angle" "0" } { "light" "250" "origin" "584 1696 136" "classname" "light" } { "classname" "light" "origin" "312 1696 136" "light" "250" } { "light" "250" "origin" "448 1696 136" "classname" "light" } { "origin" "386 2106 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "346 1158 116" } { "origin" "38 1866 340" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "38 1526 340" } { "origin" "346 1158 276" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "362 2106 276" } { "light" "200" "angle" "0" "origin" "120 1696 96" "classname" "light" } { "origin" "38 1286 108" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "38 2106 108" } { "light" "200" "origin" "616 1888 72" "classname" "light" } { "classname" "light" "origin" "616 1504 72" "light" "200" } { "angle" "0" "origin" "976 1176 224" "light" "220" "classname" "light" } { "classname" "func_plat" "model" "*2" } { "light" "200" "origin" "1272 1192 24" "classname" "light" } { "classname" "light" "origin" "864 1432 288" "angle" "0" "light" "200" } { "angle" "0" "origin" "1056 1432 288" "classname" "light" "light" "200" } { "light" "200" "origin" "1026 1242 228" "classname" "light_torch_small_walltorch" } { "lip" "2" "targetname" "t1" "sounds" "3" "wait" "-1" "spawnflags" "1" "angle" "270" "classname" "func_door" "model" "*3" } { "message" "I don't think so..." "targetname" "t1" "sounds" "3" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*4" } { "target" "t1" "sounds" "2" "health" "1" "wait" "-1" "classname" "func_button" "model" "*5" } { "wait" "-1" "targetname" "t4" "sounds" "4" "angle" "90" "classname" "func_door" "model" "*6" } { "target" "t4" "classname" "trigger_once" "model" "*7" } { "style" "32" "targetname" "t3" "spawnflags" "1" "origin" "672 1504 280" "classname" "light" } { "style" "32" "sounds" "3" "target" "t3" "targetname" "t4" "spawnflags" "1" "classname" "trigger_multiple" "model" "*8" } { "style" "32" "sounds" "3" "targetname" "t1" "target" "t3" "classname" "trigger_multiple" "spawnflags" "1" "model" "*9" } { "light" "160" "origin" "664 1304 248" "classname" "light" } { "classname" "light" "origin" "1056 1960 288" "angle" "0" "light" "250" } { "light" "250" "angle" "0" "origin" "864 1960 288" "classname" "light" } { "height" "120" "spawnflags" "1" "classname" "func_plat" "model" "*10" } { "origin" "1098 2146 444" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "1096 2304 192" "classname" "light" } { "light" "160" "origin" "1104 2152 184" "classname" "light" } { "classname" "light" "origin" "1344 2304 192" "light" "200" } { "light" "200" "origin" "1480 2240 192" "classname" "light" } { "classname" "light" "origin" "1584 2376 192" "light" "200" } { "origin" "1400 2296 632" "classname" "light" } { "classname" "light" "origin" "1200 2320 632" } { "origin" "1584 2280 632" "classname" "light" } { "classname" "light" "origin" "1592 2488 632" } { "light" "160" "origin" "1528 2344 384" "classname" "light" } { "origin" "1064 2808 208" "classname" "light" } { "height" "120" "classname" "func_plat" "spawnflags" "1" "model" "*11" } { "origin" "1584 2672 632" "classname" "light" } { "classname" "light" "origin" "1552 2856 632" } { "origin" "1432 2960 632" "classname" "light" } { "classname" "light" "origin" "1232 2976 632" } { "origin" "1040 2976 632" "classname" "light" } { "classname" "light" "origin" "928 2768 632" } { "origin" "928 2576 632" "classname" "light" } { "classname" "light" "origin" "936 2392 632" } { "classname" "light" "origin" "1584 2392 192" "light" "250" } { "light" "200" "origin" "1584 2600 192" "classname" "light" } { "classname" "light" "origin" "1584 2768 192" "light" "200" } { "light" "200" "origin" "1328 2976 192" "classname" "light" } { "classname" "light" "origin" "1488 2896 192" "light" "200" } { "light" "160" "origin" "1224 2320 392" "classname" "light" } { "classname" "light" "origin" "1624 2224 328" "light" "160" } { "classname" "light" "origin" "1136 2976 192" "light" "200" } { "light" "200" "origin" "944 2976 192" "classname" "light" } { "classname" "light" "origin" "928 2784 192" "light" "200" } { "light" "200" "origin" "928 2592 192" "classname" "light" } { "classname" "light" "origin" "936 2376 192" "light" "200" } { "light" "200" "origin" "736 2480 192" "classname" "light" } { "classname" "light" "origin" "736 2256 192" "light" "200" } { "light" "200" "origin" "968 2256 192" "classname" "light" } { "classname" "light" "origin" "1488 2896 392" "light" "160" } { "light" "160" "origin" "904 3000 392" "classname" "light" } { "classname" "light" "origin" "720 2496 392" "light" "160" } { "light" "160" "origin" "1248 2976 392" "classname" "light" } { "light" "160" "origin" "1584 2656 392" "classname" "light" } { "classname" "light" "origin" "1584 2464 392" "light" "160" } { "light" "160" "origin" "928 2800 392" "classname" "light" } { "origin" "1114 2394 540" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1266 2858 540" } { "origin" "1482 2682 540" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1482 2394 540" } { "light" "160" "origin" "1136 2776 312" "classname" "light" } { "classname" "light" "origin" "1192 2648 376" "light" "160" } { "light" "160" "origin" "1360 2560 424" "classname" "light" } { "classname" "light" "origin" "1064 2752 296" "light" "120" } { "light" "160" "origin" "1056 2616 376" "classname" "light" } { "classname" "light" "origin" "1416 2440 192" "light" "200" } { "light" "200" "origin" "1272 2440 192" "classname" "light" } { "classname" "light" "origin" "1096 2440 192" "light" "200" } { "origin" "834 2154 492" "classname" "light_torch_small_walltorch" } { "style" "33" "target" "t5" "wait" "-1" "angle" "270" "classname" "func_button" "spawnflags" "2048" "model" "*12" } { "style" "33" "targetname" "t5" "light" "200" "origin" "1776 2408 488" "classname" "light" } { "light" "200" "origin" "1752 2568 488" "classname" "light" } { "lip" "2" "targetname" "t5" "speed" "30" "sounds" "4" "wait" "-1" "angle" "-2" "classname" "func_door" "spawnflags" "2048" "model" "*13" } { "origin" "1392 2784 456" "classname" "item_key1" "spawnflags" "2048" } { "origin" "1264 2704 432" "classname" "item_armor1" } { "light" "160" "origin" "1320 2568 288" "classname" "light" } { "classname" "light" "origin" "1448 2568 200" "light" "160" } { "origin" "1312 2536 272" "classname" "item_artifact_envirosuit" } { "origin" "1312 2600 248" "classname" "item_armorInv" } { "targetname" "t16" "sounds" "1" "target" "t14" "classname" "func_train" "spawnflags" "2048" "model" "*14" } { "wait" "3" "targetname" "t15" "target" "t6" "origin" "1056 2272 256" "classname" "path_corner" } { "target" "t7" "targetname" "t6" "classname" "path_corner" "origin" "1536 2272 256" } { "target" "t8" "targetname" "t7" "origin" "1536 2752 256" "classname" "path_corner" } { "target" "t63" "targetname" "t8" "classname" "path_corner" "origin" "1360 2912 256" } { "target" "t65" "targetname" "t9" "origin" "896 2912 256" "classname" "path_corner" } { "target" "t11" "targetname" "t10" "classname" "path_corner" "origin" "896 2544 256" } { "target" "t12" "targetname" "t11" "origin" "800 2432 256" "classname" "path_corner" } { "wait" "3" "target" "t13" "targetname" "t12" "classname" "path_corner" "origin" "800 2272 256" } { "target" "t14" "targetname" "t13" "origin" "800 2272 160" "classname" "path_corner" } { "target" "t15" "targetname" "t14" "classname" "path_corner" "origin" "1056 2272 160" } { "target" "t16" "wait" "-1" "angle" "180" "classname" "func_button" "spawnflags" "2048" "model" "*15" } { "classname" "light" "origin" "896 2120 208" "angle" "0" "light" "160" } { "light" "160" "angle" "0" "origin" "776 2120 208" "classname" "light" } { "light" "250" "origin" "-198 1674 364" "classname" "light_torch_small_walltorch" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "-546 1714 364" } { "classname" "light_torch_small_walltorch" "origin" "-198 1758 364" } { "light" "200" "origin" "-416 1536 352" "classname" "light" } { "light" "200" "origin" "-408 1960 280" "classname" "light" } { "classname" "light" "origin" "-408 1544 544" "light" "200" } { "classname" "light" "origin" "-680 1752 400" "light" "200" } { "light" "200" "origin" "-400 1968 504" "classname" "light" } { "angle" "0" "origin" "-688 1544 392" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-624 1936 440" "angle" "0" } { "light" "200" "origin" "-128 1712 328" "classname" "light" } { "angle" "0" "origin" "-136 1552 352" "classname" "light" "light" "200" } { "light" "160" "origin" "-688 1904 288" "classname" "light" } { "classname" "light" "origin" "-120 1976 288" "light" "160" } { "light" "200" "origin" "-272 1712 560" "classname" "light" } { "light" "200" "origin" "-520 1712 576" "classname" "light" } { "message" "These bars open elsewhere..." "lip" "2" "wait" "-1" "targetname" "t17" "speed" "30" "sounds" "4" "angle" "-2" "classname" "func_door" "spawnflags" "2048" "model" "*16" } { "target" "t17" "sounds" "0" "wait" "-1" "angle" "270" "classname" "func_button" "spawnflags" "2048" "model" "*17" } { "style" "34" "targetname" "t17" "light" "160" "origin" "-680 1808 280" "classname" "light" } { "targetname" "t60" "wait" "-1" "sounds" "1" "angle" "90" "classname" "func_door" "model" "*18" } //{ //"target" "t18" //"wait" "-1" //"health" "1" //"angle" "0" //"classname" "func_button" //"model" "*19" //} //{ //"message" "This barrier opens elsewhere..." //"targetname" "t18" //"speed" "30" //"sounds" "4" //"wait" "-1" //"angle" "-2" //"classname" "func_door" //"model" "*20" //} { "light" "160" "origin" "-800 1728 544" "classname" "light" } { "classname" "light" "origin" "-896 1728 568" "light" "160" } { "light" "160" "origin" "-1024 1728 568" "classname" "light" } { "classname" "light" "origin" "-1024 1728 416" "light" "160" } { "light" "160" "origin" "-1024 1728 264" "classname" "light" } { "angle" "-2" "sounds" "3" "speed" "550" //Q-Man //"spawnflags" "32" "classname" "func_door" "targetname" "t50" "model" "*21" } { "light" "500" "origin" "-1320 1728 736" "classname" "light" } { "origin" "-1032 1552 616" "classname" "light" } { "classname" "light" "origin" "-1032 1888 616" } { "origin" "-1144 2184 616" "classname" "light" } { "classname" "light" "origin" "-1160 1312 616" } { "origin" "-1176 1328 312" "classname" "light" } { "classname" "light" "origin" "-1160 1512 312" } { "origin" "-1160 1968 312" "classname" "light" } { "classname" "light" "origin" "-1160 2168 312" } { "classname" "light" "origin" "-1304 1728 312" } { "classname" "light" "origin" "-1408 2112 616" } { "origin" "-1400 1352 616" "classname" "light" } { "classname" "light" "origin" "-1464 1544 616" } { "origin" "-1464 1912 616" "classname" "light" } { "origin" "-1472 1728 312" "classname" "light" } { "classname" "light" "origin" "-1440 2016 312" } { "origin" "-1416 1448 312" "classname" "light" } //{ //"classname" "func_door" //"angle" "-2" //"wait" "-1" //"sounds" "4" //"speed" "30" //"targetname" "t19" //"message" "Shoot the switches..." //"model" "*22" //} { "classname" "func_door" "angle" "270" "targetname" "t21" "wait" "-1" "model" "*23" } { "angle" "90" "classname" "func_door" "sounds" "3" "wait" "-1" "model" "*24" } //{ //"classname" "func_button" //"target" "t20" //"sounds" "2" //"wait" "-1" //"health" "1" //"model" "*25" //} //{ //"classname" "func_button" //"target" "t20" //"sounds" "2" //"wait" "-1" //"health" "1" //"model" "*26" //} { "classname" "func_button" "target" "t50" //Q-Man "sounds" "2" "wait" "4" "health" "1" "model" "*27" } //{ //"classname" "trigger_counter" //"count" "3" //"target" "t19" //"targetname" "t20" //"model" "*28" //} { "classname" "light" "origin" "-1552 1728 280" "light" "120" } { "classname" "trigger_once" "target" "t21" "model" "*29" } { "classname" "item_shells" "origin" "-1024 1504 208" } { "classname" "item_health" "origin" "-1024 1936 208" } { "classname" "item_health" "origin" "-1120 1952 128" } { "classname" "item_shells" "origin" "-1080 2168 128" } { "classname" "trigger_changelevel" "map" "e2m5" "model" "*30" } { "message" "These bars open elsewhere..." "targetname" "t22" "sounds" "3" "wait" "-1" "angle" "-2" "classname" "func_door" "spawnflags" "2048" "model" "*31" } { "target" "t22" "sounds" "2" "wait" "-1" "classname" "func_button" "spawnflags" "2048" "model" "*32" } { "style" "35" "targetname" "t22" "light" "200" "origin" "656 2032 80" "classname" "light" } { "targetname" "t23" "angle" "90" "origin" "136 1888 56" "classname" "monster_demon1" } { "spawnflags" "256" "targetname" "t23" "angle" "270" "origin" "136 1504 56" "classname" "monster_demon1" } { "origin" "408 1696 32" "classname" "weapon_rocketlauncher" } { "target" "t23" "classname" "trigger_once" "model" "*33" } { "speed" "200" "sounds" "4" "wait" "-1" "spawnflags" "2064" "angle" "-2" "classname" "func_door" "target" "t58" "model" "*34" } { "origin" "1168 2032 8" "classname" "monster_zombie" } { "target" "t26" "angle" "270" "origin" "856 2192 8" "classname" "monster_zombie" } { "targetname" "t26" "target" "t25" "origin" "864 2152 -8" "classname" "path_corner" } { "targetname" "t25" "target" "t26" "classname" "path_corner" "origin" "896 2416 -8" } { "target" "t28" "targetname" "t27" "origin" "832 2496 -8" "classname" "path_corner" } { "targetname" "t28" "target" "t27" "classname" "path_corner" "origin" "1144 2512 -8" } { "target" "t27" "origin" "808 2528 8" "classname" "monster_zombie" } { "angle" "90" "origin" "992 2272 56" "classname" "monster_zombie" } { "angle" "270" "origin" "1136 2344 8" "classname" "monster_zombie" } { "angle" "180" "origin" "1152 2168 8" "classname" "monster_zombie" } { "spawnflags" "256" "origin" "808 2072 8" "classname" "monster_zombie" } { "spawnflags" "256" "origin" "912 2016 8" "classname" "monster_zombie" } { "spawnflags" "256" "origin" "1048 2000 8" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "270" "origin" "1624 2560 440" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "270" "origin" "1544 2560 440" "classname" "monster_ogre" } { "target" "t29" "origin" "1312 2760 456" "classname" "monster_demon1" "spawnflags" "1024" "targetname" "t49" } { "target" "t30" "targetname" "t29" "origin" "1240 2832 440" "classname" "path_corner" } { "targetname" "t30" "target" "t29" "classname" "path_corner" "origin" "1440 2680 440" } { "spawnflags" "256" "angle" "0" "origin" "1016 2976 456" "classname" "monster_wizard" } { "angle" "135" "origin" "1088 2656 344" "classname" "monster_ogre" } { "angle" "135" "spawnflags" "256" "origin" "1200 2616 344" "classname" "monster_ogre" } { "spawnflags" "768" "angle" "135" "origin" "1112 2560 344" "classname" "monster_ogre" } { "angle" "270" "origin" "1480 1360 168" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "270" "origin" "1648 1360 168" "classname" "monster_ogre" } { "angle" "225" "origin" "1776 1184 56" "classname" "monster_zombie" } { "target" "t31" "origin" "1136 1840 8" "classname" "monster_zombie" } { "target" "t32" "targetname" "t31" "origin" "1080 1848 -8" "classname" "path_corner" } { "targetname" "t32" "target" "t31" "classname" "path_corner" "origin" "1080 1544 -8" } { "spawnflags" "256" "angle" "90" "origin" "1144 1528 8" "classname" "monster_zombie" } { "spawnflags" "768" "origin" "1120 1688 8" "classname" "monster_zombie" } { "target" "t34" "targetname" "t33" "origin" "840 1864 40" "classname" "path_corner" } { "target" "t35" "targetname" "t34" "classname" "path_corner" "origin" "840 1528 40" } { "target" "t36" "targetname" "t35" "origin" "968 1528 40" "classname" "path_corner" } { "targetname" "t36" "target" "t33" "classname" "path_corner" "origin" "968 1864 40" } { "target" "t36" "origin" "976 1760 56" "classname" "monster_ogre" } { "spawnflags" "256" "target" "t34" "origin" "896 1664 56" "classname" "monster_ogre" } { "target" "t35" "spawnflags" "768" "origin" "944 1520 56" "classname" "monster_ogre" } { "target" "t33" "spawnflags" "768" "origin" "880 1832 56" "classname" "monster_hell_knight" } { "origin" "736 1880 32" "classname" "item_health" } { "spawnflags" "1" "origin" "736 1488 32" "classname" "item_rockets" } { "origin" "1144 1880 -16" "classname" "item_rockets" } { "angle" "180" "origin" "624 2032 56" "classname" "monster_hell_knight" } { "spawnflags" "1" "origin" "640 1872 32" "classname" "item_shells" } { "spawnflags" "1" "origin" "56 1896 32" "classname" "item_health" } { "classname" "item_armor2" "origin" "2216 2088 -32" } { "classname" "weapon_supernailgun" "origin" "784 1232 -128" } { "classname" "item_shells" "origin" "1792 896 -192" } { "classname" "weapon_nailgun" //Q-Man "origin" "1776 1088 -192" } { "classname" "item_spikes" "origin" "1824 992 -192" } { "origin" "1840 1176 32" "classname" "item_armor2" //"spawnflags" "256" //Q-Man } { "spawnflags" "256" "origin" "1416 1360 8" "classname" "monster_zombie" } { "spawnflags" "256" "target" "t38" "origin" "1504 2016 160" "classname" "monster_ogre" } { "target" "t39" "targetname" "t37" "origin" "1920 2072 144" "classname" "path_corner" } { "targetname" "t38" "target" "t37" "classname" "path_corner" "origin" "1280 2072 144" } { "target" "t40" "targetname" "t39" "classname" "path_corner" "origin" "1920 1984 144" } { "target" "t38" "targetname" "t40" "origin" "1280 1984 144" "classname" "path_corner" } { "target" "t37" "origin" "1840 2056 160" "classname" "monster_ogre" } { "target" "t40" "spawnflags" "768" "origin" "1656 1992 160" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "135" "origin" "1680 1488 472" "classname" "monster_wizard" } { "spawnflags" "768" "angle" "270" "origin" "1440 1888 472" "classname" "monster_wizard" } { "spawnflags" "1024" "origin" "1312 424 320" "classname" "item_health" } { "spawnflags" "1" "origin" "984 232 320" "classname" "item_health" } { "origin" "776 344 32" "classname" "item_spikes" "spawnflags" "1" //Q-Man } { "origin" "834 618 88" "classname" "ambient_swamp1" } { "origin" "898 946 88" "classname" "ambient_swamp2" } { "origin" "1714 1114 88" "classname" "ambient_swamp1" } { "origin" "1538 1690 88" "classname" "ambient_swamp2" } { "classname" "trigger_secret" "model" "*35" } { "classname" "func_door_secret" "angle" "0" "spawnflags" "3" "sounds" "1" "model" "*36" } { "classname" "item_health" "origin" "768 848 -192" } { "classname" "trigger_secret" "model" "*37" } { "classname" "trigger_secret" "model" "*38" } { "classname" "item_health" "origin" "1984 1320 -128" "spawnflags" "2" } { "classname" "item_rockets" "origin" "1896 1264 -128" "spawnflags" "1" } { "classname" "path_corner" "origin" "832 336 40" "targetname" "t41" "target" "t42" } { "origin" "832 536 40" "classname" "path_corner" "target" "t41" "targetname" "t42" } { "classname" "monster_hell_knight" "origin" "864 432 56" "target" "t41" "spawnflags" "256" } { "classname" "item_shells" "origin" "1320 160 320" } { "classname" "monster_ogre" "origin" "1256 1368 160" "angle" "270" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "1080 1392 -40" "angle" "180" "targetname" "t22" } { "classname" "path_corner" "origin" "952 1192 -56" "targetname" "t43" "target" "t44" } { "origin" "1208 1160 -56" "classname" "path_corner" "target" "t43" "targetname" "t44" } { "classname" "monster_demon1" "origin" "1104 1240 -40" "target" "t43" "spawnflags" "256" } { "classname" "item_health" "origin" "944 1392 -64" } { "classname" "item_rockets" "origin" "1112 1296 -64" } { "classname" "item_spikes" "origin" "1104 1128 -64" } { "classname" "path_corner" "origin" "432 1360 40" "targetname" "t45" "target" "t46" } { "origin" "632 1360 40" "classname" "path_corner" "target" "t45" "targetname" "t46" } { "targetname" "t22" "classname" "monster_hell_knight" "origin" "392 1328 56" "target" "t45" "spawnflags" "256" } { "origin" "72 2056 40" "classname" "path_corner" "targetname" "t47" "target" "t48" } { "classname" "path_corner" "origin" "536 2056 40" "target" "t47" "targetname" "t48" } { "spawnflags" "256" "origin" "336 2024 56" "classname" "monster_hell_knight" "target" "t47" } { "classname" "item_armor1" "origin" "128 1696 32" } { "classname" "item_artifact_super_damage" "origin" "856 3048 184" } { "classname" "trigger_once" "target" "t49" "model" "*39" } { "classname" "monster_shambler" "origin" "1344 2688 456" "spawnflags" "768" "targetname" "t49" "target" "t29" } { "classname" "item_health" "origin" "1232 2504 320" "spawnflags" "1" } { "light" "160" "origin" "680 2304 312" "classname" "light" } { "target" "t55" "classname" "trigger_once" "model" "*40" } { "spawnflags" "2" "target" "t54" "classname" "trigger_teleport" "targetname" "t67" "model" "*41" } { "spawnflags" "2" "target" "t53" "classname" "trigger_teleport" "targetname" "t67" "model" "*42" } { "spawnflags" "2" "target" "t52" "classname" "trigger_teleport" "targetname" "t67" "model" "*43" } { "spawnflags" "2" "target" "t51" "classname" "trigger_teleport" "targetname" "t67" "model" "*44" } { "origin" "216 2720 280" "classname" "monster_wizard" "spawnflags" "257" "targetname" "t67" } { "classname" "monster_wizard" "origin" "216 2656 280" "spawnflags" "257" "targetname" "t67" } { "origin" "216 2592 280" "classname" "monster_wizard" "spawnflags" "257" "targetname" "t67" } { "classname" "monster_wizard" "origin" "216 2528 280" "spawnflags" "257" "targetname" "t67" } { "targetname" "t51" "angle" "180" "origin" "504 2032 248" "classname" "info_teleport_destination" } { "targetname" "t53" "angle" "90" "classname" "info_teleport_destination" "origin" "352 1760 248" } { "targetname" "t52" "angle" "90" "origin" "104 1656 328" "classname" "info_teleport_destination" } { "targetname" "t54" "angle" "180" "classname" "info_teleport_destination" "origin" "296 1376 264" } { "origin" "80 1336 192" "classname" "item_health" } { "classname" "item_health" "origin" "96 2008 192" } { "spawnflags" "256" "angle" "90" "origin" "1784 1616 -8" "classname" "monster_ogre" } { "origin" "2200 1768 -32" "classname" "item_rockets" } { "origin" "2048 1888 -32" "classname" "item_spikes" } { "origin" "1824 1992 -32" "classname" "item_health" } { "light" "200" "origin" "664 1368 104" "classname" "light" } { "light" "200" "origin" "240 1496 104" "classname" "light" } { "classname" "light" "origin" "240 1896 104" "light" "200" } { "light" "160" "origin" "296 1392 80" "classname" "light" } { "light" "160" "origin" "280 1368 248" "classname" "light" } { "classname" "light" "origin" "400 1368 248" "light" "160" } { "classname" "light" "origin" "392 1392 80" "light" "160" } { "angle" "270" "origin" "1848 1880 264" "classname" "monster_wizard" } { "angle" "270" "spawnflags" "256" "origin" "1792 1488 264" "classname" "monster_wizard" } { "classname" "monster_wizard" "origin" "1904 1648 264" "spawnflags" "768" "angle" "270" } { "spawnflags" "257" "angle" "180" "origin" "2120 1800 -8" "classname" "monster_demon1" "targetname" "t59" } { "spawnflags" "768" "angle" "225" "origin" "2120 1896 -8" "classname" "monster_demon1" } { "angle" "180" "spawnflags" "256" "origin" "2032 2168 -8" "classname" "monster_hell_knight" } { "angle" "225" "spawnflags" "768" "origin" "2120 2000 120" "classname" "monster_ogre" } { "angle" "90" "origin" "1256 1504 208" "classname" "monster_ogre" } { "origin" "1304 1640 136" "classname" "item_health" } { "classname" "item_health" "origin" "1224 1640 136" } { "spawnflags" "1" "origin" "1304 1544 184" "classname" "item_health" } { "origin" "1296 1760 136" "classname" "item_spikes" } { "origin" "1048 2264 32" "classname" "item_armor2" } { "origin" "1048 2296 56" "classname" "item_key2" "spawnflags" "2048" } { "origin" "736 2536 32" "classname" "weapon_grenadelauncher" } { "origin" "720 2432 32" "classname" "item_rockets" } { "lip" "2" "wait" "-1" "speed" "20" "sounds" "3" "spawnflags" "2056" "classname" "func_door" "model" "*45" } { "light" "160" "origin" "2208 2000 48" "classname" "light" } { "origin" "720 2472 32" "classname" "item_health" } { "origin" "640 1464 32" "classname" "item_health" } { "spawnflags" "1" "origin" "224 1168 32" "classname" "item_health" } { "targetname" "t22" "spawnflags" "768" "angle" "135" "origin" "336 1192 56" "classname" "monster_demon1" } { "origin" "1208 1400 136" "classname" "item_health" } { "light" "160" "origin" "2216 2280 32" "classname" "light" } { "targetname" "t57" "angle" "90" "spawnflags" "257" "origin" "1280 1720 160" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "270" "origin" "1160 2248 352" "classname" "monster_wizard" } { "spawnflags" "768" "angle" "180" "origin" "1592 2304 536" "classname" "monster_wizard" } { "classname" "monster_wizard" "origin" "1456 2928 536" "angle" "315" "spawnflags" "768" } { "classname" "item_shells" "origin" "1568 2064 136" } { "classname" "item_spikes" "origin" "1784 2584 416" } { "classname" "item_shells" "origin" "1760 2424 432" } { "classname" "item_health" "origin" "664 2184 272" } { "origin" "664 2224 272" "classname" "item_health" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "-264 1720 256" "angle" "270" "targetname" "t58" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "-120 1976 256" "angle" "270" "spawnflags" "768" } { "classname" "item_shells" "origin" "-120 1496 232" } { "classname" "monster_shambler" "origin" "-128 1736 512" "angle" "135" } { "classname" "item_shells" "origin" "-736 1536 296" } { "classname" "item_rockets" "origin" "-696 1496 296" } { "classname" "item_health" "origin" "-640 1976 232" "spawnflags" "1" } { "classname" "monster_hell_knight" "origin" "-264 1976 256" "angle" "225" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "-648 1952 256" "angle" "270" } { "classname" "monster_ogre" "origin" "-696 1776 376" "angle" "0" } { "classname" "weapon_grenadelauncher" "origin" "1760 1224 32" "spawnflags" "3584" } { "classname" "item_spikes" "origin" "2200 2168 -32" "spawnflags" "1" } { "classname" "item_artifact_envirosuit" "origin" "1320 1496 208" } { "classname" "item_shells" "origin" "1176 2504 320" } { "classname" "item_shells" "origin" "776 556 -192" "spawnflags" "1" } { "classname" "item_artifact_super_damage" "origin" "1776 1016 -168" } { "classname" "trigger_once" "target" "t59" "model" "*46" } { "classname" "trigger_once" "target" "t57" "model" "*47" } { "classname" "monster_zombie" "origin" "920 1264 176" "angle" "90" } { "classname" "item_artifact_super_damage" "origin" "1024 1408 176" } { "classname" "item_health" "origin" "1112 1328 152" "spawnflags" "2" } { "classname" "item_spikes" "origin" "1024 1296 152" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "-904 1720 512" } //{ //"classname" "func_button" //"sounds" "3" //"target" "t50" //"model" "*48" //} { "classname" "monster_demon1" "origin" "-1272 2168 152" "angle" "315" } { "classname" "monster_demon1" "origin" "-1312 1376 152" "angle" "45" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-1392 1560 152" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "-1360 1920 152" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "-1024 1584 232" "spawnflags" "768" "angle" "90" } { "classname" "monster_ogre" "origin" "-1016 1896 232" "angle" "270" "spawnflags" "256" } { "sounds" "3" "classname" "func_button" "angle" "180" "target" "t50" "model" "*49" } { "classname" "monster_wizard" "origin" "160 2720 280" "targetname" "t68" "spawnflags" "1" } { "origin" "160 2528 280" "classname" "monster_wizard" "spawnflags" "257" "targetname" "t68" } { "classname" "monster_wizard" "origin" "160 2592 280" "targetname" "t68" "spawnflags" "1" } { "origin" "160 2656 280" "classname" "monster_wizard" "targetname" "t68" "spawnflags" "1" } { "classname" "func_train" "sounds" "1" "target" "t9" "targetname" "t16" "spawnflags" "2048" "model" "*50" } { "classname" "item_rockets" "origin" "1152 2496 -16" } { "classname" "monster_ogre" "origin" "456 1352 216" "spawnflags" "256" } { //"spawnflags" "2048" "classname" "item_artifact_invulnerability" "origin" "2192 1664 128" } { "classname" "light" "origin" "2192 1664 144" "light" "160" } { "light" "160" "origin" "2040 1664 144" "classname" "light" } { "classname" "func_door_secret" "angle" "0" "wait" "-1" "model" "*51" } { "classname" "trigger_secret" "model" "*52" } { "classname" "light" "origin" "1808 896 -40" } { "classname" "info_player_deathmatch" "origin" "624 1696 104" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "-488 1720 552" } { "classname" "info_player_deathmatch" "origin" "1360 2808 456" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "896 2376 8" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "1104 2040 160" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "1288 1376 160" } { "classname" "info_player_deathmatch" "origin" "840 400 56" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "944 2032 160" "angle" "180" } { "classname" "info_intermission" "origin" "-1440 1304 656" "mangle" "20 45 0" } { "classname" "info_intermission" "origin" "1072 2416 560" "mangle" "20 45 0" } { "classname" "info_intermission" "origin" "1160 1896 336" "mangle" "20 225 0" } { "classname" "info_intermission" "origin" "1688 1480 336" "mangle" "20 135 0" } { "classname" "info_intermission" "origin" "2216 1784 320" "mangle" "20 135 0" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "2051" "targetname" "t55" "sounds" "1" "model" "*53" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "2051" "targetname" "t55" "sounds" "1" "model" "*54" } { "classname" "func_plat" "sounds" "2" "model" "*55" } { "classname" "light" "origin" "96 1232 256" "light" "160" } { "light" "160" "origin" "96 1232 104" "classname" "light" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2051" "sounds" "1" "targetname" "t62" "model" "*56" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "2049" "sounds" "1" "targetname" "t62" "model" "*57" } { "classname" "light" "origin" "1672 2216 56" "light" "160" } { "light" "160" "origin" "1672 2088 56" "classname" "light" } { "target" "t60" "classname" "trigger_once" "model" "*58" } { "classname" "weapon_lightning" "origin" "-680 1712 528" "spawnflags" "1792" } { "classname" "item_cells" "origin" "-624 1664 528" "spawnflags" "1793" } //{ //"spawnflags" "1793" //"origin" "-624 1736 528" //"classname" "item_cells" //} { "classname" "item_cells" "origin" "608 1976 32" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "608 2056 32" "classname" "item_cells" } { "classname" "func_wall" "spawnflags" "1792" "targetname" "t64" "model" "*59" } { "angle" "180" "origin" "1456 256 344" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1456 200 344" "angle" "180" } { "angle" "180" "origin" "1456 368 344" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1456 424 344" "angle" "180" } { "spawnflags" "1792" "classname" "func_wall" "model" "*60" } { "light" "200" "origin" "880 2432 352" "classname" "light" } { "classname" "light" "origin" "960 2624 352" "light" "200" } { "light" "200" "origin" "960 2976 312" "classname" "light" } { "classname" "light" "origin" "1176 2992 312" "light" "200" } { "light" "200" "origin" "1368 2960 312" "classname" "light" } { "classname" "light" "origin" "1472 2872 312" "light" "200" } { "light" "200" "origin" "1584 2768 312" "classname" "light" } { "classname" "light" "origin" "1584 2568 312" "light" "200" } { "light" "200" "origin" "1584 2296 312" "classname" "light" } { "classname" "light" "origin" "1328 2320 312" "light" "200" } //{ //"spawnflags" "1794" //"origin" "2136 1648 104" //"classname" "item_health" //} { "classname" "trigger_once" "target" "t62" "model" "*61" } { "classname" "item_spikes" "origin" "760 1128 -128" "spawnflags" "1" //Q-Man } { "classname" "item_health" "origin" "1272 2824 432" "spawnflags" "1536" } { "origin" "1320 2824 432" "classname" "item_health" "spawnflags" "1536" } { "classname" "path_corner" "origin" "1096 2912 256" "targetname" "t63" "target" "t9" "wait" "2" } { "wait" "2" "origin" "896 2584 256" "classname" "path_corner" "targetname" "t65" "target" "t10" } { "classname" "trigger_relay" "origin" "-128 1664 280" "targetname" "t58" } { "spawnflags" "1" "origin" "784 960 -192" "classname" "item_rockets" } { "classname" "trigger_relay" "origin" "120 2632 184" "targetname" "t55" "target" "t56" } { "classname" "trigger_teleport" "targetname" "t68" "target" "t54" "model" "*62" } { "classname" "trigger_relay" "origin" "160 2760 200" "target" "t68" "targetname" "t56" } { "origin" "216 2760 200" "classname" "trigger_relay" "targetname" "t66" "target" "t67" "delay" "5" } { "classname" "trigger_teleport" "targetname" "t68" "target" "t53" "model" "*63" } { "classname" "trigger_teleport" "targetname" "t68" "target" "t52" "model" "*64" } { "classname" "trigger_teleport" "targetname" "t68" "target" "t51" "model" "*65" } //Q-Man { "origin" "-1335 1351 152" "classname" "item_flag_team1" } { "angle" "90" "origin" "-1263 1381 152" "classname" "info_player_team1" } { "angle" "90" "origin" "-1417 1381 152" "classname" "info_player_team1" } { "angle" "180" "origin" "-1048 1572 232" "classname" "info_player_team1" } { "angle" "180" "origin" "-1048 1876 232" "classname" "info_player_team1" } { "angle" "180" "origin" "-914 1728 512" "classname" "info_player_team1" } { "origin" "-487 1718 552" "classname" "info_player_team1" } { "origin" "1345 304 344" "classname" "item_flag_team2" } { "angle" "180" "origin" "1346 249 344" "classname" "info_player_team2" } { "angle" "180" "origin" "1346 377 344" "classname" "info_player_team2" } { "angle" "180" "origin" "994 310 280" "classname" "info_player_team2" } { "angle" "90" "origin" "827 449 56" "classname" "info_player_team2" } { "angle" "270" "origin" "802 1220 224" "classname" "info_player_team2" } { "angle" "180" "origin" "1759 1211 56" "classname" "info_player_team2" } { "origin" "-1137 1724 232" "classname" "weapon_supershotgun" } { "origin" "-1351 2023 152" "classname" "item_armor1" } { "classname" "weapon_supershotgun" "origin" "1274 305 344" } { "origin" "-656 1922 256" "classname" "weapon_supernailgun" } { "origin" "-700 1904 256" "classname" "item_spikes" "spawnflags" "1" } { "origin" "-1150 1380 152" "classname" "item_spikes" "spawnflags" "1" } { "origin" "1687 1474 8" "classname" "item_health" } { "origin" "1640 1474 8" "classname" "item_health" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m5.ent000066400000000000000000001310121475442401000251720ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/wizard.wad" "message" "the Wizard's Manse" "worldtype" "0" "sounds" "11" } { "classname" "light" "origin" "0 0 128" "angle" "0" "light" "250" } { "classname" "light" "origin" "104 128 296" "angle" "0" } { "classname" "light" "origin" "-104 128 296" "angle" "0" } { "classname" "light" "origin" "-160 200 136" "angle" "0" } { "classname" "light" "origin" "160 200 136" "angle" "0" } { "classname" "light" "origin" "-432 120 112" "angle" "0" "light" "250" } { "classname" "light" "origin" "432 120 112" "angle" "0" "light" "250" } { "classname" "light" "origin" "-424 392 0" "angle" "0" "light" "250" } { "classname" "light" "origin" "456 392 0" "angle" "0" "light" "250" } { "classname" "light" "origin" "0 408 320" "angle" "0" "light" "200" } { "classname" "light" "origin" "-240 704 -48" "angle" "0" "light" "200" } { "classname" "light" "origin" "240 704 -48" "angle" "0" "light" "200" } { "classname" "light" "origin" "0 728 -112" "angle" "0" "light" "250" } { "classname" "light" "origin" "0 680 120" "angle" "0" "light" "250" } { "classname" "light" "origin" "0 528 -64" "angle" "0" } { "classname" "light" "origin" "-336 704 80" "angle" "0" "light" "250" } { "classname" "light" "origin" "336 704 80" "angle" "0" "light" "250" } { "classname" "light" "origin" "0 864 -64" "light" "200" } { "classname" "light" "origin" "192 856 320" "angle" "0" "light" "160" } { "classname" "light" "origin" "-192 856 320" "angle" "0" "light" "160" } { "classname" "light" "origin" "192 368 320" "angle" "0" "light" "160" } { "classname" "light" "origin" "-192 368 320" "angle" "0" "light" "160" } { "classname" "light" "origin" "192 584 320" "angle" "0" "light" "160" } { "classname" "light" "origin" "-192 584 320" "angle" "0" "light" "160" } { "light" "350" "classname" "light" "origin" "0 672 360" } { "classname" "light" "origin" "232 1112 16" "angle" "0" } { "light" "200" "classname" "light" "origin" "480 1120 184" } { "light" "200" "classname" "light" "origin" "928 1472 192" "angle" "0" } { "light" "200" "classname" "light" "origin" "928 1472 256" "angle" "0" } { "light" "200" "classname" "light" "origin" "1088 1376 192" "angle" "0" } { "light" "200" "classname" "light" "origin" "1088 1376 256" "angle" "0" } { "light" "200" "classname" "light" "origin" "672 1472 192" "angle" "0" } { "light" "200" "classname" "light" "origin" "672 1472 256" } { "light" "200" "classname" "light" "origin" "1088 1120 192" } { "light" "200" "classname" "light" "origin" "1088 1120 256" } { "light" "200" "classname" "light" "origin" "1088 864 192" "angle" "0" } { "light" "200" "classname" "light" "origin" "1088 864 256" "angle" "0" } { "light" "200" "classname" "light" "origin" "928 640 192" "angle" "0" } { "light" "200" "classname" "light" "origin" "928 640 256" "angle" "0" } { "light" "200" "classname" "light" "origin" "672 704 192" "angle" "0" } { "classname" "light" "origin" "1024 1152 16" "angle" "0" "light" "160" } { "classname" "light" "origin" "1024 960 16" "angle" "0" "light" "160" } { "classname" "light" "origin" "784 712 16" "angle" "0" "light" "200" } { "classname" "light" "origin" "1016 712 16" "angle" "0" "light" "200" } { "classname" "light" "origin" "784 1400 16" "angle" "0" "light" "200" } { "classname" "light" "origin" "1008 1400 16" "angle" "0" "light" "200" } { "classname" "light" "origin" "864 1248 272" "angle" "0" } { "light" "250" "classname" "light" "origin" "864 864 272" } { "classname" "light" "origin" "608 1120 224" "angle" "0" } { "classname" "light" "origin" "464 896 8" "angle" "0" "light" "200" } { "classname" "light" "origin" "512 896 120" "angle" "0" "light" "200" } { "light" "250" "classname" "light" "origin" "864 1248 48" } { "classname" "light" "origin" "864 864 48" "angle" "0" } { "classname" "light" "origin" "800 680 208" "angle" "0" "light" "200" } { "classname" "light" "origin" "792 1432 208" "angle" "0" "light" "200" } { "classname" "light" "origin" "432 1440 32" "light" "200" } { "classname" "light" "origin" "432 1696 96" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "502 1578 252" "style" "1" "light" "200" } { "classname" "light" "origin" "568 1888 96" "light" "200" } { "classname" "light" "light" "200" "origin" "-248 2304 72" "angle" "0" } { "classname" "light" "light" "170" "origin" "-272 2376 280" "angle" "0" } { "classname" "light" "origin" "-672 1392 248" "angle" "0" "light" "400" } { "classname" "light" "origin" "-600 1896 80" "angle" "0" "light" "200" } { "classname" "light" "origin" "-592 1672 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "-392 1864 -48" "angle" "0" "light" "200" } { "classname" "light" "origin" "-248 1880 -64" "angle" "0" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "122 2818 212" "style" "1" } { "classname" "light_torch_small_walltorch" "origin" "-78 3066 116" "style" "6" } { "classname" "light" "origin" "-224 2776 40" "angle" "0" "light" "200" } { "classname" "light" "origin" "-248 2632 264" "angle" "0" "light" "200" } { "classname" "light" "origin" "-256 1152 224" "angle" "0" "light" "150" } { "classname" "light" "origin" "0 1152 224" "angle" "0" "light" "200" } { "classname" "light" "origin" "-264 1440 224" "angle" "0" "light" "200" } { "classname" "light" "origin" "-648 712 88" "angle" "0" "light" "200" } { "classname" "light" "light" "200" "origin" "-592 1792 120" "angle" "0" } { "classname" "light" "light" "300" "origin" "-680 2944 168" "angle" "0" } { "classname" "light" "light" "300" "origin" "-480 3104 216" "angle" "0" } { "classname" "light" "light" "300" "origin" "-480 2784 216" "angle" "0" } { "classname" "light" "light" "200" "origin" "-632 3080 -32" "angle" "0" } { "classname" "light" "light" "200" "origin" "-632 2808 -32" "angle" "0" } { "classname" "light" "light" "250" "origin" "-832 2816 136" "angle" "0" } { "classname" "light" "light" "250" "origin" "-832 3072 128" "angle" "0" } { "classname" "light" "light" "250" "origin" "-1152 3072 128" "angle" "0" } { "classname" "light" "light" "250" "origin" "-1152 2816 128" "angle" "0" } { "classname" "light" "origin" "0 -432 120" } { "classname" "light" "origin" "-640 -552 -144" "light" "200" } { "light" "200" "origin" "-864 -1288 -56" "classname" "light" } { "light" "200" "style" "1" "origin" "-782 -926 -100" "classname" "light_torch_small_walltorch" } { "light" "200" "style" "1" "origin" "-1078 -1142 -148" "classname" "light_torch_small_walltorch" } { "light" "200" "style" "6" "classname" "light_torch_small_walltorch" "origin" "-646 -1214 -148" } { "light" "160" "origin" "-1024 -1288 -184" "classname" "light" } { "classname" "light" "origin" "-688 -1288 -184" "light" "160" } { "light" "160" "origin" "-1048 -1000 -184" "classname" "light" } { "light" "160" "origin" "-864 -1272 -184" "classname" "light" } { "classname" "light" "origin" "-864 -984 -136" "light" "160" } { "light" "120" "origin" "-704 -744 -136" "classname" "light" } { "light" "160" "origin" "-736 -1056 -160" "classname" "light" } { "classname" "func_plat" "spawnflags" "1" "model" "*1" } { "style" "1" "light" "200" "origin" "674 -606 36" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "584 -552 -136" "classname" "light" } { "classname" "light" "origin" "672 -552 -136" "light" "150" } { "origin" "0 -160 344" "classname" "light" } { "classname" "light" "origin" "-128 -160 264" } { "origin" "128 -160 264" "classname" "light" } { "light" "150" "origin" "0 -176 32" "classname" "light" } { "light" "200" "origin" "-8 -544 -120" "classname" "light" } { "light" "250" "classname" "light" "origin" "-160 -224 -120" } { "light" "250" "origin" "160 -224 -120" "classname" "light" } { "light" "250" "origin" "-352 -224 -120" "classname" "light" } { "light" "250" "classname" "light" "origin" "352 -224 -120" } { "light" "200" "origin" "312 -384 -184" "classname" "light" } { "light" "250" "classname" "light" "origin" "-352 -416 -120" } { "classname" "light" "origin" "384 -384 120" "light" "200" } { "light" "200" "origin" "384 -552 128" "classname" "light" } { "light" "160" "origin" "552 -384 8" "classname" "light" } { "style" "1" "classname" "light" "origin" "672 -400 8" "light" "160" } { "classname" "light" "origin" "-160 -512 -120" "light" "200" } { "classname" "light" "origin" "368 -552 -120" "light" "200" } { "origin" "344 -840 -120" "classname" "light" "light" "250" } { "light" "250" "classname" "light" "origin" "-328 -840 -120" } { "origin" "0 -824 -120" "classname" "light" "light" "250" } { "light" "200" "classname" "light" "origin" "168 -832 56" } { "origin" "-168 -832 56" "classname" "light" "light" "200" } { "light" "250" "classname" "light" "origin" "-352 -704 56" } { "origin" "352 -704 56" "classname" "light" "light" "250" } { "origin" "-320 -256 192" "classname" "light" "light" "250" } { "light" "250" "classname" "light" "origin" "320 -256 192" } { "light" "120" "origin" "520 -128 320" "classname" "light" } { "classname" "light" "origin" "-520 -128 320" "light" "120" } { "classname" "light" "origin" "160 -544 -120" "light" "200" } { "origin" "-376 -544 120" "classname" "light" "light" "160" } { "origin" "-312 -824 96" "classname" "light" "light" "250" } { "light" "250" "classname" "light" "origin" "328 -824 96" } { "light" "230" "classname" "light" "origin" "0 -840 200" } { "light" "200" "origin" "224 -384 120" "classname" "light" } { "light" "200" "origin" "-376 -888 -376" "classname" "light" } { "classname" "light" "origin" "376 -888 -376" "light" "200" } { "classname" "light" "origin" "-376 -712 -376" "light" "200" } { "light" "200" "origin" "376 -712 -376" "classname" "light" } { "light" "200" "origin" "-184 -888 -376" "classname" "light" } { "classname" "light" "origin" "200 -888 -376" "light" "200" } { "light" "200" "origin" "8 -888 -376" "classname" "light" } { "light" "200" "origin" "-376 -520 -376" "classname" "light" } { "classname" "light" "origin" "-376 -352 -376" "light" "200" } { "light" "200" "origin" "-376 -184 -376" "classname" "light" } { "classname" "light" "origin" "-192 -184 -376" "light" "200" } { "light" "200" "origin" "0 -200 -376" "classname" "light" } { "classname" "light" "origin" "192 -184 -376" "light" "200" } { "light" "200" "origin" "376 -184 -376" "classname" "light" } { "classname" "light" "origin" "376 -352 -376" "light" "200" } { "light" "200" "origin" "376 -520 -376" "classname" "light" } { "light" "200" "origin" "0 -584 -376" "classname" "light" } { "classname" "light" "origin" "-160 -416 -376" "light" "200" } { "classname" "light" "origin" "184 -416 -376" "light" "200" } { "classname" "light" "origin" "-152 -552 -256" "light" "200" } { "light" "200" "origin" "144 -544 -256" "classname" "light" } { "classname" "light" "origin" "328 -544 -256" "light" "200" } { "light" "200" "origin" "-360 -544 -256" "classname" "light" } { "spawnflags" "1" "targetname" "t1" "angle" "270" "origin" "0 152 24" "classname" "monster_demon1" } { "angle" "225" "origin" "-40 -384 -16" "classname" "monster_ogre" } { "target" "t1" "classname" "trigger_once" "model" "*2" } { "classname" "info_player_start" "origin" "-864 -1280 -232" "angle" "90" } { "classname" "light" "origin" "-224 864 -264" "light" "200" } { "light" "250" "origin" "-224 560 -264" "classname" "light" } { "light" "200" "origin" "-160 312 -264" "classname" "light" } { "light" "200" "origin" "-96 704 -264" "classname" "light" } { "classname" "light" "origin" "96 704 -264" "light" "200" } { "style" "32" "classname" "light" "origin" "-128 888 -8" "light" "160" "targetname" "t2" } { "style" "32" "spawnflags" "2048" "classname" "func_button" "angle" "90" "target" "t2" "wait" "-1" "model" "*3" } { "classname" "func_door" "spawnflags" "2049" "targetname" "t2" "wait" "-1" "model" "*4" } { "light" "150" "origin" "-232 872 -8" "classname" "light" } { "classname" "light" "origin" "248 872 -8" "light" "200" } { "classname" "light" "origin" "0 864 120" "light" "120" } { "classname" "light_torch_small_walltorch" "origin" "-294 418 132" } { "origin" "298 418 132" "classname" "light_torch_small_walltorch" } { "light" "140" "origin" "0 920 288" "classname" "light" } { "light" "200" "origin" "240 864 -264" "classname" "light" } { "classname" "light" "origin" "224 560 -264" "light" "200" } { "light" "200" "origin" "160 312 -264" "classname" "light" } { "classname" "light" "origin" "0 872 -264" "light" "200" } { "light" "200" "angle" "0" "origin" "624 1120 72" "classname" "light" } { "spawnflags" "2048" "angle" "180" "height" "300" "speed" "150" "classname" "trigger_monsterjump" "model" "*5" } { "classname" "light" "origin" "1048 984 200" "light" "200" } { "light" "200" "origin" "1008 720 200" "classname" "light" } { "classname" "light" "origin" "472 704 160" "light" "200" } { "spawnflags" "2048" "classname" "func_button" "angle" "180" "target" "t3" "wait" "-1" "model" "*6" } { "spawnflags" "2048" "classname" "func_door" "angle" "90" "targetname" "t3" "wait" "-1" "sounds" "1" "lip" "-2" "model" "*7" } { "style" "33" "light" "200" "origin" "624 1408 0" "classname" "light" "targetname" "t18" "spawnflags" "1" } { "wait" "-1" "classname" "func_door" "angle" "-2" "targetname" "t3" "speed" "300" "sounds" "1" "spawnflags" "2048" "model" "*8" } { "style" "34" "classname" "light" "origin" "608 704 0" "light" "200" "targetname" "t3" } { "light" "200" "origin" "496 2048 112" "classname" "light" } { "light" "200" "origin" "488 1408 152" "classname" "light" } { "classname" "light" "origin" "304 2216 -176" "light" "150" } { "light" "150" "origin" "112 2216 -176" "classname" "light" } { "light" "170" "origin" "-48 2296 264" "classname" "light" } { "classname" "light" "origin" "112 2296 264" "light" "170" } { "light" "170" "origin" "272 2296 264" "classname" "light" } { "classname" "light" "origin" "-48 2200 96" "light" "170" } { "light" "170" "origin" "112 2200 96" "classname" "light" } { "classname" "light" "origin" "272 2200 96" "light" "170" } { "classname" "light" "origin" "320 1408 40" "light" "150" } { "classname" "light" "origin" "328 1912 72" "light" "150" } { "classname" "light" "origin" "-120 1760 72" "light" "170" } { "light" "170" "origin" "344 1760 72" "classname" "light" } { "light" "150" "origin" "-96 2120 -184" "classname" "light" } { "classname" "light" "origin" "-96 1928 -184" "light" "200" } { "light" "200" "origin" "-96 1736 -184" "classname" "light" } { "classname" "light" "origin" "-96 1544 -184" "light" "200" } { "classname" "light" "origin" "200 1920 96" "light" "200" } { "light" "200" "origin" "24 1920 96" "classname" "light" } { "light" "150" "origin" "-96 1408 40" "classname" "light" } { "light" "200" "origin" "32 1408 -184" "classname" "light" } { "classname" "light" "origin" "200 1408 -184" "light" "200" } { "light" "200" "origin" "320 1544 -184" "classname" "light" } { "classname" "light" "origin" "320 1736 -184" "light" "200" } { "light" "200" "origin" "320 2120 -184" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "114 1362 132" } { "origin" "112 1760 -184" "classname" "light" } { "classname" "light" "origin" "112 2048 -184" } { "classname" "light_torch_small_walltorch" "origin" "378 2050 236" } { "origin" "-150 2050 236" "classname" "light_torch_small_walltorch" } { "origin" "378 1410 236" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-150 1410 252" } { "classname" "light" "origin" "-96 1696 240" "light" "200" } { "light" "200" "origin" "328 1696 240" "classname" "light" } { "classname" "light" "origin" "-96 1632 40" "light" "150" } { "light" "150" "origin" "320 1632 40" "classname" "light" } { "classname" "light" "origin" "-112 2296 -184" "light" "150" } { "classname" "light" "origin" "112 1824 168" "light" "170" } { "classname" "light_torch_small_walltorch" "origin" "-334 1978 244" } { "classname" "light" "origin" "-112 2288 120" "light" "170" } { "angle" "0" "origin" "-240 2256 248" "light" "170" "classname" "light" } { "classname" "light" "origin" "-248 2184 -160" "light" "150" } { "light" "150" "origin" "-248 2080 -160" "classname" "light" } { "classname" "light" "origin" "-248 1992 -160" "light" "150" } { "light" "150" "origin" "-248 2344 -160" "classname" "light" } { "classname" "light" "origin" "-248 2480 -160" "light" "150" } { "light" "150" "origin" "-248 2664 -160" "classname" "light" } { "classname" "light" "origin" "-600 1888 -32" "light" "150" } { "light" "150" "origin" "-600 1648 -32" "classname" "light" } { "classname" "light" "origin" "-592 1560 -32" "light" "150" } { "classname" "light" "origin" "-600 1768 -32" "light" "150" } { "origin" "-672 1400 24" "classname" "light" "light" "240" } { "light" "170" "origin" "-600 2048 64" "classname" "light" } { "classname" "light" "origin" "-384 2048 88" "light" "170" } { "classname" "light" "origin" "-256 2424 0" "light" "150" } { "light" "200" "origin" "-600 2032 -136" "classname" "light" } { "classname" "light" "origin" "-600 1872 -128" "light" "200" } { "spawnflags" "256" "classname" "monster_demon1" "origin" "-584 1824 -128" "target" "t4" } { "spawnflags" "1" "classname" "monster_demon1" "origin" "-656 2080 -112" "angle" "270" "target" "t6" } { "classname" "trigger_monsterjump" "angle" "270" "height" "400" "speed" "400" "model" "*9" } { "classname" "path_corner" "origin" "-664 1800 -136" "targetname" "t4" "target" "t5" } { "origin" "-520 1800 -136" "classname" "path_corner" "target" "t4" "targetname" "t5" } { "classname" "path_corner" "origin" "-664 2064 -128" "targetname" "t6" "target" "t7" } { "origin" "-520 2064 -128" "classname" "path_corner" "target" "t6" "targetname" "t7" } { "classname" "light" "origin" "-752 1056 248" "light" "400" } { "classname" "light" "origin" "-872 1056 56" "light" "250" } { "origin" "-632 1056 56" "classname" "light" "light" "250" } { "classname" "light" "origin" "-544 1352 -40" "light" "130" } { "light" "130" "origin" "-784 1352 -40" "classname" "light" } { "origin" "-960 1152 -200" "classname" "light" "light" "200" } { "classname" "light" "origin" "-808 1640 104" "light" "150" } { "classname" "light" "origin" "-960 1344 -96" "light" "200" } { "light" "200" "origin" "-960 1504 -96" "classname" "light" } { "light" "200" "classname" "light" "origin" "-936 944 -200" } { "origin" "-568 944 -200" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-552 1152 -200" } { "origin" "-752 928 -200" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-752 1176 -200" } { "classname" "func_plat" "height" "336" "model" "*10" } { "classname" "light" "origin" "-960 1576 -224" "light" "200" } { "light" "200" "origin" "-960 1440 -224" "classname" "light" } { "classname" "light" "origin" "-960 1296 -224" "light" "200" } { "light" "150" "origin" "-960 1640 104" "classname" "light" } { "classname" "light" "origin" "-960 1640 -64" "light" "150" } { "classname" "item_health" "origin" "-864 1616 64" } { "origin" "-800 1616 64" "classname" "item_health" } { "style" "35" "classname" "func_button" "angle" "0" "wait" "-1" "target" "t12" "health" "1" "spawnflags" "2048" "model" "*11" } { "style" "35" "classname" "light" "origin" "-504 1192 -72" "light" "200" "targetname" "t12" } { "health" "1" "wait" "-1" "angle" "180" "classname" "func_button" "target" "t13" "model" "*12" } { "classname" "func_door" "angle" "180" "spawnflags" "1" "targetname" "t13" "speed" "300" "wait" "-1" "sounds" "2" "lip" "-2" "model" "*13" } { "style" "36" "classname" "light" "origin" "-1000 1192 -72" "light" "200" "targetname" "t13" } { "classname" "light" "origin" "-992 952 -120" "light" "120" } { "light" "120" "origin" "-992 1056 -120" "classname" "light" } { "classname" "light" "origin" "-992 1152 -120" "light" "120" } { "target" "t14" "targetname" "t12" "dmg" "20" "classname" "func_train" "sounds" "1" "spawnflags" "2048" "model" "*14" } { "targetname" "t14" "target" "t15" "classname" "path_corner" "origin" "-608 1280 -152" } { "wait" "3" "target" "t16" "targetname" "t15" "origin" "-608 1160 -152" "classname" "path_corner" } { "target" "t17" "targetname" "t16" "classname" "path_corner" "origin" "-1184 1160 -152" } { "wait" "0.8" "targetname" "t17" "target" "t14" "origin" "-1184 1280 -152" "classname" "path_corner" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "speed" "300" "sounds" "2" "model" "*15" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "speed" "300" "sounds" "2" "model" "*16" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "speed" "300" "sounds" "2" "model" "*17" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "speed" "300" "sounds" "2" "model" "*18" } { "classname" "func_door" "angle" "270" "spawnflags" "1" "speed" "200" "sounds" "2" "model" "*19" } { "classname" "light" "origin" "-896 896 -80" "light" "120" } { "light" "120" "origin" "-736 896 -16" "classname" "light" } { "style" "33" "classname" "trigger_once" "target" "t18" "targetname" "t3" "spawnflags" "1" "model" "*20" } { "classname" "light_torch_small_walltorch" "origin" "-294 906 148" } { "origin" "298 906 148" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "632 840 304" "classname" "light" "light" "170" } { "classname" "light" "origin" "312 1200 -40" "light" "170" } { "classname" "light" "origin" "-256 1280 200" "light" "150" } { "classname" "light" "origin" "0 952 232" "light" "170" } { "classname" "light" "origin" "-64 2624 224" "light" "200" } { "classname" "light" "origin" "-80 3040 -32" "light" "150" } { "light" "150" "origin" "96 2816 72" "classname" "light" } { "classname" "light" "origin" "-136 2744 -160" "light" "150" } { "light" "150" "origin" "-56 2816 -160" "classname" "light" } { "classname" "light" "origin" "-160 2904 -160" "light" "150" } { "light" "150" "origin" "-296 3000 -160" "classname" "light" } { "classname" "func_train" "targetname" "t20" "target" "t22" "dmg" "20" "speed" "70" "spawnflags" "2048" "sounds" "1" "model" "*21" } { "classname" "path_corner" "origin" "-64 320 160" "target" "t19" "targetname" "t22" } { "origin" "-64 320 -624" "classname" "path_corner" "targetname" "t19" "target" "t25" } { "classname" "func_button" "angle" "270" "target" "t20" "wait" "-1" "spawnflags" "2048" "model" "*22" } { "classname" "path_corner" "origin" "-64 1088 -480" "targetname" "t21" "target" "t22" "wait" "-1" } { "classname" "light" "origin" "0 384 232" "light" "160" } { "style" "37" "light" "200" "origin" "0 336 232" "classname" "light" "targetname" "t20" } { "light" "160" "origin" "0 384 96" "classname" "light" } { "classname" "light" "origin" "0 384 -32" "light" "160" } { "light" "160" "origin" "0 384 -160" "classname" "light" } { "classname" "light" "origin" "0 384 -288" "light" "160" } { "light" "160" "origin" "0 384 -416" "classname" "light" } { "classname" "light" "origin" "0 384 -544" "light" "160" } { "classname" "func_train" "target" "t23" "speed" "70" "targetname" "t32" "spawnflags" "2048" "sounds" "1" "model" "*23" } { "classname" "path_corner" "origin" "-64 304 -624" "targetname" "t23" "target" "t29" } { "classname" "trigger_once" "target" "t24" "model" "*24" } { "classname" "path_corner" "origin" "-64 1088 -624" "targetname" "t25" "target" "t21" } { "light" "160" "origin" "0 512 -544" "classname" "light" } { "classname" "light" "origin" "0 640 -544" "light" "160" } { "light" "160" "origin" "0 768 -544" "classname" "light" } { "classname" "light" "origin" "0 896 -544" "light" "160" } { "light" "160" "origin" "0 1024 -544" "classname" "light" } { "classname" "light" "origin" "0 1152 -544" "light" "160" } { "classname" "func_train" "target" "t26" "speed" "70" "targetname" "t32" "spawnflags" "2048" "sounds" "1" "model" "*25" } { "classname" "path_corner" "origin" "-64 464 -624" "target" "t27" "targetname" "t26" } { "origin" "-64 1192 -624" "classname" "path_corner" "targetname" "t27" "target" "t28" } { "classname" "path_corner" "origin" "-64 1208 -624" "targetname" "t28" "target" "t27" "wait" "-1" } { "classname" "light" "origin" "0 1152 -376" "light" "200" } { "origin" "-64 1072 -624" "classname" "path_corner" "targetname" "t29" "wait" "-1" "target" "t25" } { "classname" "light" "origin" "-248 1112 -352" "light" "250" } { "light" "200" "origin" "-160 1152 -200" "classname" "light" } { "classname" "light" "origin" "-352 1272 -312" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-382 1642 -84" "style" "1" } { "classname" "light" "origin" "-376 1400 -120" "light" "200" } { "classname" "light" "origin" "-376 1456 -328" "light" "170" } { "classname" "func_plat" "model" "*26" } { "classname" "light" "origin" "-384 1512 -240" "light" "100" } { "light" "200" "angle" "0" "origin" "-136 320 -64" "classname" "light" } { "classname" "light" "origin" "136 320 -64" "angle" "0" "light" "200" } { "classname" "light" "origin" "-384 1720 -80" "light" "200" } { "classname" "light" "origin" "-192 3008 -72" "light" "150" } { "classname" "func_wall" "spawnflags" "2048" "model" "*27" } { "light" "120" "origin" "-64 2752 -24" "classname" "light" } { "classname" "light" "origin" "-240 2856 264" "light" "120" } { "classname" "func_door" "angle" "270" "targetname" "t24" "wait" "-1" "model" "*28" } { "classname" "func_door" "angle" "-1" "spawnflags" "2048" "message" "These bars open elsewhere..." "targetname" "t30" "sounds" "4" "wait" "-1" "model" "*29" } { "classname" "func_door" "angle" "-1" "targetname" "t30" "wait" "-1" "sounds" "4" "spawnflags" "2048" "model" "*30" } { "classname" "func_door" "angle" "-1" "spawnflags" "2049" "targetname" "t30" "wait" "120" "sounds" "4" "model" "*31" } { "targetname" "t20" "classname" "trigger_once" "target" "t30" "spawnflags" "2049" "model" "*32" } { "classname" "func_door" "angle" "-2" "sounds" "1" "targetname" "t31" "lip" "-2" "model" "*33" } { "classname" "func_plat" "lip" "2" "sounds" "1" "model" "*34" } { "classname" "light" "origin" "0 -384 -160" "light" "150" } { "light" "150" "origin" "0 -384 -256" "classname" "light" } { "classname" "light" "origin" "0 -384 -352" "light" "150" } { "classname" "light" "origin" "88 -384 -368" "light" "150" } { "classname" "trigger_multiple" "target" "t31" "model" "*35" } { "classname" "light" "origin" "160 -8 -328" "light" "150" } { "light" "150" "origin" "160 136 -328" "classname" "light" } { "classname" "light" "origin" "312 1912 184" "light" "150" } { "light" "150" "origin" "-104 1912 192" "classname" "light" } { "classname" "light" "origin" "56 1912 192" "light" "150" } { "light" "150" "origin" "200 1912 192" "classname" "light" } { "classname" "light" "origin" "-320 2888 -64" "light" "150" } { "light" "150" "origin" "-320 3000 -64" "classname" "light" } { "classname" "light" "origin" "-320 3000 128" "light" "150" } { "light" "150" "origin" "-320 2888 128" "classname" "light" } { "light" "150" "origin" "-424 3120 -160" "classname" "light" } { "classname" "light" "origin" "-424 2768 -160" "light" "150" } { "light" "150" "origin" "-416 2872 -160" "classname" "light" } { "classname" "light" "origin" "-416 3016 -160" "light" "150" } { "classname" "light" "origin" "-992 2944 32" "light" "200" } { "classname" "func_door" "angle" "90" "speed" "300" "sounds" "1" "wait" "-1" "model" "*36" } { "angle" "270" "classname" "func_door" "speed" "300" "wait" "-1" "model" "*37" } { "classname" "trigger_changelevel" "map" "e2m6" "model" "*38" } { "classname" "light" "origin" "-776 2944 -16" "light" "200" } { "angle" "0" "origin" "-512 3104 -32" "light" "200" "classname" "light" } { "classname" "light" "light" "200" "origin" "-512 2784 -32" "angle" "0" } { "classname" "light" "light" "150" "origin" "-512 2944 -32" "angle" "0" } { "light" "150" "origin" "-992 3144 8" "classname" "light" } { "classname" "light" "origin" "-992 2744 8" "light" "150" } { "light" "150" "origin" "-1152 2760 -40" "classname" "light" } { "classname" "light" "origin" "-1184 2944 -40" "light" "220" } { "light" "150" "origin" "-1152 3128 -40" "classname" "light" } { "classname" "light" "origin" "-760 3144 8" "light" "150" } { "light" "150" "origin" "-760 2744 8" "classname" "light" } { "classname" "light" "origin" "-1248 3152 -96" "light" "100" } { "light" "100" "origin" "-1248 2736 -96" "classname" "light" } { "classname" "trigger_once" "targetname" "t20" "delay" "11.5" "spawnflags" "1" "target" "t32" "model" "*39" } { "classname" "light" "origin" "488 568 144" "light" "200" } { "light" "200" "origin" "640 544 184" "classname" "light" } { "classname" "light" "origin" "184 168 32" "light" "120" } { "light" "120" "origin" "-184 168 32" "classname" "light" } { "classname" "func_door" "angle" "-2" "spawnflags" "2049" "wait" "60" "sounds" "4" "targetname" "t53" "model" "*40" } { "spawnflags" "256" "classname" "monster_hell_knight" "origin" "-208 -536 -168" "angle" "180" "target" "t33" } { "classname" "monster_hell_knight" "origin" "-744 -512 -168" "angle" "270" "spawnflags" "768" } { "classname" "path_corner" "origin" "-312 -552 -184" "targetname" "t33" "target" "t34" } { "origin" "-72 -552 -184" "classname" "path_corner" "target" "t33" "targetname" "t34" } { "classname" "path_corner" "origin" "136 -552 -184" "target" "t35" "targetname" "t36" } { "origin" "440 -552 -184" "classname" "path_corner" "targetname" "t35" "target" "t36" } { "classname" "monster_hell_knight" "origin" "272 -536 -168" "target" "t36" "spawnflags" "256" } { "classname" "item_health" "origin" "-1080 -1320 -256" } { "origin" "-680 -1320 -256" "classname" "item_health" } { "classname" "item_shells" "origin" "-1056 -1024 -256" "spawnflags" "1" } { "classname" "item_shells" "origin" "648 -392 -48" } { "classname" "item_shells" "origin" "-24 -464 -192" } { "classname" "monster_ogre" "origin" "352 -408 -24" "spawnflags" "768" "angle" "225" } { "classname" "monster_ogre" "origin" "-536 -560 -168" "angle" "225" "spawnflags" "768" } { "classname" "monster_wizard" "origin" "-432 120 112" "angle" "0" "target" "t1" "spawnflags" "769" } { "angle" "180" "origin" "432 120 112" "classname" "monster_wizard" "target" "t1" "spawnflags" "257" } { "classname" "monster_hell_knight" "origin" "-136 880 -40" "angle" "270" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "0 608 216" "angle" "225" } { "classname" "monster_ogre" "origin" "-80 704 88" "angle" "270" } { "classname" "item_shells" "origin" "-256 576 -96" "spawnflags" "1" } { "classname" "item_spikes" "origin" "400 432 -96" "spawnflags" "1" } { "classname" "weapon_nailgun" "origin" "448 384 -96" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "-256 864 -80" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "264 1072 -72" "targetname" "t2" } { "classname" "monster_ogre" "origin" "1024 1272 112" "angle" "180" } { "angle" "180" "origin" "1016 832 112" "classname" "monster_ogre" "spawnflags" "256" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "1032 1056 112" "angle" "180" } { "classname" "item_shells" "origin" "688 688 -48" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1000 1384 -48" "spawnflags" "1" } { "classname" "item_health" "origin" "976 720 -48" } { "classname" "item_health" "origin" "-448 400 -48" } { "classname" "item_health" "origin" "528 1096 0" } { "classname" "item_health" "origin" "464 64 -48" } { "classname" "monster_ogre" "origin" "784 1400 112" "angle" "270" "spawnflags" "256" } { "spawnflags" "768" "angle" "90" "origin" "800 712 112" "classname" "monster_ogre" } { "classname" "monster_hell_knight" "origin" "1000 704 -24" "angle" "180" "spawnflags" "257" } { "classname" "path_corner" "origin" "712 1288 -40" "targetname" "t37" "target" "t38" } { "origin" "712 840 -40" "classname" "path_corner" "targetname" "t38" "target" "t39" } { "classname" "path_corner" "origin" "904 904 -40" "targetname" "t39" "target" "t40" } { "origin" "904 1208 -40" "classname" "path_corner" "target" "t37" "targetname" "t40" } { "classname" "monster_hell_knight" "origin" "744 968 -24" "target" "t38" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "848 1264 -24" "target" "t37" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "880 1088 -24" "target" "t40" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "976 1432 -24" "angle" "270" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "488 896 -24" "spawnflags" "1024" "targetname" "t3" } { "classname" "monster_shambler" "origin" "488 904 -24" "spawnflags" "768" "targetname" "t3" } { "classname" "monster_ogre" "origin" "504 2040 56" "angle" "270" } { "classname" "item_spikes" "origin" "464 1392 -48" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "200 2288 224" "angle" "270" "spawnflags" "256" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "168 1904 184" "angle" "315" } { "classname" "monster_hell_knight" "origin" "320 1416 24" "angle" "90" } { "classname" "monster_hell_knight" "origin" "-96 2048 56" "spawnflags" "256" } { "classname" "item_shells" "origin" "96 1392 0" "spawnflags" "1" } { "wait" "10" "speed" "600" "classname" "func_door" "angle" "-1" "spawnflags" "2049" "targetname" "t42" "sounds" "4" "model" "*41" } { "classname" "trigger_multiple" "spawnflags" "1" "targetname" "t3" "target" "t42" "model" "*42" } { "classname" "monster_ogre" "origin" "-96 1672 24" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-96 1792 184" } { "classname" "monster_ogre" "origin" "-264 2288 224" "angle" "270" } { "classname" "monster_hell_knight" "origin" "-760 1512 -80" "spawnflags" "768" } { "spawnflags" "768" "origin" "-536 2072 16" "classname" "monster_hell_knight" } { "classname" "item_shells" "origin" "-424 2000 -8" } { "classname" "item_artifact_super_damage" "origin" "-40 2728 -224" "spawnflags" "2048" } { "classname" "item_rockets" "origin" "128 2288 200" "spawnflags" "1" } { "classname" "item_health" "origin" "40 2288 200" } { "classname" "item_health" "origin" "-616 2016 -104" "spawnflags" "2" } { "classname" "item_artifact_envirosuit" "origin" "-600 1648 -80" } { "classname" "weapon_grenadelauncher" "origin" "-688 1392 -104" "spawnflags" "1792" } { "classname" "item_rockets" "origin" "-816 1488 -104" } { "classname" "monster_ogre" "origin" "-656 776 16" "angle" "90" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "608 528 96" "angle" "135" "spawnflags" "1" } { "classname" "monster_hell_knight" "origin" "488 584 80" "angle" "90" "spawnflags" "257" } { "classname" "monster_wizard" "origin" "-960 1136 88" "spawnflags" "256" } { "classname" "monster_wizard" "origin" "-824 944 184" "angle" "90" "spawnflags" "768" } { "classname" "item_shells" "origin" "-16 688 64" } { "classname" "monster_ogre" "origin" "-200 1160 -424" "target" "t44" "spawnflags" "768" } { "classname" "path_corner" "origin" "-264 1032 -440" "targetname" "t43" "target" "t44" } { "origin" "-264 1240 -440" "classname" "path_corner" "target" "t43" "targetname" "t44" } { "classname" "monster_ogre" "origin" "-192 1088 -424" "target" "t43" } { "classname" "item_health" "origin" "-368 1160 -448" } { "origin" "-344 1000 -448" "classname" "item_health" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "-384 1608 -240" "angle" "270" "spawnflags" "256" } { "classname" "item_armorInv" "origin" "480 840 -48" } { "classname" "item_armor1" "origin" "296 1128 -96" "spawnflags" "1024" } { "classname" "item_health" "origin" "-160 528 -320" } { "origin" "160 384 -320" "classname" "item_health" } { "classname" "item_health" "origin" "120 848 -320" } { "classname" "item_health" "origin" "480 952 -48" "spawnflags" "1024" } { "classname" "monster_wizard" "origin" "-960 1312 88" "angle" "90" } { "classname" "monster_demon1" "origin" "0 1152 192" "angle" "180" "spawnflags" "1024" } { "classname" "item_health" "origin" "-144 1136 168" } { "classname" "item_shells" "origin" "-280 1152 168" } { "spawnflags" "1" "classname" "monster_wizard" "origin" "-384 1408 -104" "angle" "90" } { "classname" "monster_ogre" "origin" "-216 3032 -112" "target" "t48" } { "classname" "path_corner" "origin" "-192 3008 -128" "target" "t47" "targetname" "t48" } { "origin" "48 3008 -48" "classname" "path_corner" "targetname" "t47" "target" "t48" } { "origin" "48 2624 96" "classname" "path_corner" "targetname" "t45" "target" "t46" } { "classname" "path_corner" "origin" "-240 2624 208" "target" "t45" "targetname" "t46" } { "classname" "path_corner" "origin" "64 2624 96" "targetname" "t49" "target" "t50" } { "classname" "path_corner" "origin" "64 3008 -48" "target" "t49" "targetname" "t50" } { "classname" "monster_ogre" "origin" "88 3032 -32" "spawnflags" "256" "target" "t50" } { "classname" "monster_ogre" "origin" "88 2600 112" "target" "t45" "spawnflags" "768" } { "lip" "-2" "classname" "func_door" "angle" "90" "spawnflags" "2056" "targetname" "t51" "sounds" "4" "wait" "-1" "speed" "300" "target" "t53" "model" "*43" } { "classname" "monster_demon1" "origin" "-832 2944 -48" "targetname" "t53" } { "classname" "monster_hell_knight" "origin" "-824 3152 -48" "angle" "270" "targetname" "t53" } { "classname" "monster_hell_knight" "origin" "-824 2736 -48" "angle" "90" "spawnflags" "256" "targetname" "t53" } { "classname" "monster_hell_knight" "origin" "-1208 2944 -96" "spawnflags" "768" "targetname" "t53" } { "classname" "item_health" "origin" "-1040 3136 -72" } { "origin" "-1048 2736 -72" "classname" "item_health" } { "classname" "item_rockets" "origin" "-1256 3136 -120" } { "classname" "item_key2" "origin" "352 2304 224" "sounds" "1" "spawnflags" "2048" } { "lip" "-2" "speed" "300" "wait" "-1" "sounds" "4" "spawnflags" "2056" "angle" "270" "classname" "func_door" "model" "*44" } { "classname" "item_health" "origin" "888 696 88" "spawnflags" "1024" } { "spawnflags" "1024" "origin" "1008 976 88" "classname" "item_health" } { "classname" "item_health" "origin" "880 1368 88" "spawnflags" "1536" } { "classname" "item_health" "origin" "-16 512 400" } { "origin" "-16 848 400" "classname" "item_health" } { "classname" "monster_shambler" "origin" "-1040 2944 -48" "spawnflags" "768" "targetname" "t53" } { "classname" "item_rockets" "origin" "-56 2888 -248" "spawnflags" "1" } { "classname" "light" "origin" "-696 2896 -16" "light" "170" } { "light" "170" "origin" "-696 2992 -16" "classname" "light" } { "classname" "item_spikes" "origin" "-744 1616 64" } { "classname" "item_shells" "origin" "-704 664 -8" } { "classname" "item_shells" "origin" "664 720 88" } { "classname" "item_spikes" "origin" "472 1408 88" "spawnflags" "1" } { "classname" "item_spikes" "origin" "256 472 -320" "spawnflags" "1" } { "classname" "item_shells" "origin" "-208 288 -320" } { "classname" "item_spikes" "origin" "-16 -312 -32" "spawnflags" "1024" } { "classname" "item_spikes" "origin" "-368 -112 -400" } { "spawnflags" "256" "origin" "-928 2888 -48" "classname" "monster_demon1" "targetname" "t53" } { "spawnflags" "256" "classname" "monster_demon1" "origin" "-928 3000 -48" "targetname" "t53" } { "classname" "item_spikes" "origin" "-56 2800 -248" "spawnflags" "1" } { "classname" "info_player_deathmatch" "origin" "320 2304 224" "angle" "180" } { "delay" "4" "classname" "func_door" "angle" "-1" "spawnflags" "2049" "speed" "600" "sounds" "4" "targetname" "t20" "model" "*45" } { "classname" "monster_wizard" "origin" "752 1584 232" "targetname" "t55" } { "origin" "808 1568 232" "classname" "monster_wizard" "targetname" "t55" "spawnflags" "256" } { "classname" "monster_wizard" "origin" "864 1584 232" "targetname" "t55" "spawnflags" "768" } { "origin" "808 1632 232" "classname" "monster_wizard" "targetname" "t55" "spawnflags" "768" } { "targetname" "t55" "classname" "trigger_teleport" "target" "t54" "spawnflags" "2" "model" "*46" } { "classname" "info_teleport_destination" "origin" "760 1208 264" "angle" "315" "targetname" "t54" } { "classname" "trigger_once" "target" "t55" "model" "*47" } { "classname" "item_spikes" "origin" "1024 1152 88" "spawnflags" "1" } { "spawnflags" "1" "origin" "688 1400 88" "classname" "item_spikes" } { "angle" "90" "classname" "func_door_secret" "model" "*48" } { "light" "200" "origin" "-16 2432 128" "classname" "light" } { "classname" "light" "origin" "32 2432 192" "light" "200" } { "light" "200" "origin" "-56 2432 256" "classname" "light" } { "origin" "-88 2432 200" "classname" "item_armorInv" } { "origin" "-32 2432 88" "classname" "item_artifact_super_damage" } { "classname" "trigger_secret" "model" "*49" } { "classname" "trigger_secret" "model" "*50" } { "spawnflags" "1024" "origin" "-536 3144 -136" "classname" "item_health" } { "classname" "item_health" "origin" "-512 2720 -136" "spawnflags" "1024" } { "spawnflags" "1024" "origin" "-664 3144 -136" "classname" "item_health" } { "classname" "monster_shambler" "origin" "-24 1152 192" "spawnflags" "768" "angle" "180" } { "spawnflags" "1024" "origin" "432 1784 -248" "classname" "item_health" } { "classname" "item_health" "origin" "440 1640 -248" "spawnflags" "1024" } { "origin" "0 -552 -192" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "1024 1048 88" "classname" "weapon_supernailgun" } { "origin" "-112 2304 224" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-648 712 16" "classname" "info_player_deathmatch" } { "origin" "-400 -552 -168" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "angle" "270" "origin" "0 816 216" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "angle" "180" "origin" "320 1912 184" "classname" "info_player_deathmatch" } { "mangle" "20 125 0" "origin" "416 -896 144" "classname" "info_intermission" } { "mangle" "-40 125 0" "origin" "256 336 -96" "classname" "info_intermission" } { "mangle" "20 125 0" "origin" "-552 928 96" "classname" "info_intermission" } { "mangle" "20 125 0" "origin" "240 1496 320" "classname" "info_intermission" } { "mangle" "20 55 0" "origin" "608 800 304" "classname" "info_intermission" } { "classname" "item_artifact_super_damage" "origin" "8 -416 -16" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "-240 808 -96" "spawnflags" "1792" } { "classname" "func_wall" "spawnflags" "1792" "model" "*51" } { "classname" "weapon_lightning" "origin" "0 512 192" "spawnflags" "1792" } { "classname" "item_cells" "origin" "24 688 192" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "-56 688 192" "classname" "item_cells" } { "classname" "item_cells" "origin" "-696 -1008 -208" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "-768 -1008 -208" "classname" "item_cells" } { "classname" "func_wall" "spawnflags" "1792" "model" "*52" } { "classname" "info_player_coop" "origin" "-800 -1280 -232" "angle" "90" } { "angle" "90" "origin" "-736 -1280 -232" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-928 -1280 -232" "angle" "90" } { "angle" "90" "origin" "-992 -1280 -232" "classname" "info_player_coop" } { "light" "200" "origin" "-312 920 -416" "classname" "light" } { "classname" "light" "origin" "-208 912 -576" "light" "200" } { "light" "200" "origin" "-112 912 -576" "classname" "light" } { "targetname" "t57" "spawnflags" "2049" "angle" "270" "classname" "func_door_secret" "model" "*53" } { "target" "t57" "classname" "trigger_once" "model" "*54" } { "spawnflags" "1792" "classname" "func_wall" "model" "*55" } { "classname" "weapon_lightning" "origin" "-672 1392 -104" "spawnflags" "2048" } { "classname" "item_cells" "origin" "-816 1432 -104" "spawnflags" "1" } { "targetname" "t60" "angle" "315" "origin" "696 1128 264" "classname" "info_teleport_destination" } { "targetname" "t59" "classname" "info_teleport_destination" "origin" "1008 1216 264" "angle" "270" } { "targetname" "t58" "angle" "270" "origin" "1008 1360 264" "classname" "info_teleport_destination" } { "targetname" "t55" "target" "t59" "spawnflags" "2" "classname" "trigger_teleport" "model" "*56" } { "targetname" "t55" "target" "t60" "classname" "trigger_teleport" "spawnflags" "2" "model" "*57" } { "targetname" "t55" "target" "t58" "spawnflags" "2" "classname" "trigger_teleport" "model" "*58" } { "classname" "func_wall" "spawnflags" "2048" "model" "*59" } { "classname" "func_wall" "spawnflags" "2048" "model" "*60" } { "classname" "light" "origin" "-800 2048 104" "light" "160" } { "light" "160" "origin" "-800 1792 104" "classname" "light" } { "classname" "light" "origin" "-800 1920 104" "light" "160" } { "classname" "func_wall" "spawnflags" "1792" "model" "*61" } { "classname" "item_artifact_invulnerability" "origin" "-320 1088 -416" "spawnflags" "1792" } { "classname" "item_artifact_invisibility" "origin" "-928 2944 -48" "spawnflags" "1792" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "-856 -1296 -200" "classname" "item_flag_team1" } { "angle" "90" "origin" "-756 -1246 -232" "classname" "info_player_team1" } { "angle" "90" "origin" "-856 -1246 -232" "classname" "info_player_team1" } { "angle" "90" "origin" "-956 -1246 -232" "classname" "info_player_team1" } { "angle" "90" "origin" "-756 -1146 -216" "classname" "info_player_team1" } { "angle" "90" "origin" "-856 -1146 -216" "classname" "info_player_team1" } { "angle" "90" "origin" "-956 -1146 -216" "classname" "info_player_team1" } // team2 { "origin" "-1246 2944 -76" "classname" "item_flag_team2" } { "angle" "0" "origin" "-1200 2844 -96" "classname" "info_player_team2" } { "angle" "0" "origin" "-1200 2944 -96" "classname" "info_player_team2" } { "angle" "0" "origin" "-1200 3044 -96" "classname" "info_player_team2" } { "angle" "0" "origin" "-1056 2844 -48" "classname" "info_player_team2" } { "angle" "0" "origin" "-1056 2944 -48" "classname" "info_player_team2" } { "angle" "0" "origin" "-1056 3044 -48" "classname" "info_player_team2" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m6.ent000066400000000000000000001331341475442401000252020ustar00rootroot00000000000000{ "wad" "gfx/wizard.wad" "classname" "worldspawn" "message" "the Dismal Oubliette" "worldtype" "0" "sounds" "4" } { "angle" "0" "origin" "456 128 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "760 128 -360" "classname" "light_torch_small_walltorch" } { "origin" "392 -304 -368" "classname" "light_torch_small_walltorch" "light" "250" } { "origin" "608 -264 -248" "classname" "light_torch_small_walltorch" "light" "250" } { "origin" "824 -40 -376" "classname" "light_torch_small_walltorch" "light" "200" } { "origin" "392 -40 -376" "classname" "light_torch_small_walltorch" "light" "200" } { "angle" "0" "origin" "800 192 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "416 192 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "304 304 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "912 304 -360" "classname" "light_torch_small_walltorch" } { "light" "250" "angle" "0" "origin" "776 312 -776" "classname" "light" } { "light" "250" "angle" "0" "origin" "440 312 -776" "classname" "light" } { "angle" "0" "origin" "304 688 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "472 800 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "744 800 -360" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "912 688 -360" "classname" "light_torch_small_walltorch" } { "light" "250" "angle" "0" "origin" "776 680 -776" "classname" "light" } { "light" "250" "angle" "0" "origin" "440 680 -776" "classname" "light" } { "light" "200" "angle" "0" "origin" "608 384 -672" "classname" "light" } { "light" "200" "angle" "0" "origin" "512 496 -672" "classname" "light" } { "light" "200" "angle" "0" "origin" "608 600 -672" "classname" "light" } { "light" "200" "angle" "0" "origin" "704 496 -672" "classname" "light" } { "light" "200" "angle" "0" "origin" "608 496 -456" "classname" "light" } { "light" "250" "angle" "0" "origin" "992 496 -400" "classname" "light" } { "angle" "0" "origin" "1024 136 -400" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1448 144 -304" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1136 192 -304" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "1420 804 -552" "classname" "light" } { "light" "200" "angle" "0" "origin" "1668 804 -552" "classname" "light" } { "light" "200" "angle" "0" "origin" "1668 540 -552" "classname" "light" } { "light" "200" "angle" "0" "origin" "1544 672 -616" "classname" "light" } { "light" "200" "angle" "0" "origin" "1168 672 -616" "classname" "light" } { "light" "200" "angle" "0" "origin" "1360 672 -616" "classname" "light" } { "light" "160" "origin" "1664 312 -520" "classname" "light" } { "light" "200" "angle" "0" "origin" "1168 496 -520" "classname" "light" } { "light" "200" "angle" "0" "origin" "1168 328 -520" "classname" "light" } { "light" "200" "angle" "0" "origin" "1368 408 -520" "classname" "light" } { "light" "200" "angle" "0" "origin" "1544 408 -520" "classname" "light" } { "angle" "0" "origin" "1264 852 -388" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1520 704 -392" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1668 492 -388" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1024 856 -400" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1168 464 -472" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1168 352 -472" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "608 1040 -416" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "408 960 -448" "classname" "light" } { "light" "200" "angle" "0" "origin" "228 964 -528" "classname" "light" } { "light" "220" "angle" "0" "origin" "128 1280 -560" "classname" "light" } { "light" "200" "angle" "0" "origin" "144 1280 -800" "classname" "light" } { "angle" "0" "origin" "400 1464 -880" "classname" "light_torch_small_walltorch" "light" "250" } { "angle" "0" "origin" "400 1096 -880" "classname" "light_torch_small_walltorch" "light" "250" } { "angle" "0" "origin" "608 1096 -904" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "608 1464 -904" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "608 1280 -744" "classname" "light" } { "light" "160" "angle" "0" "origin" "960 1160 -456" "classname" "light" } { "light" "200" "angle" "0" "origin" "964 964 -456" "classname" "light" } { "angle" "0" "origin" "488 1136 -680" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "948 1148 -672" "classname" "light" } { "light" "160" "angle" "0" "origin" "768 1136 -672" "classname" "light" } { "angle" "0" "origin" "832 1368 -480" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "784 1280 -888" "classname" "light_torch_small_walltorch" } { "light" "250" "origin" "832 1496 -704" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "960 1368 -704" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1008 1712 -672" "classname" "light" "light" "400" } { "angle" "0" "origin" "1168 1712 -672" "classname" "light" "light" "400" } { "angle" "0" "origin" "1328 1584 -664" "classname" "light" "light" "400" } { "origin" "1324 1420 -664" "classname" "light" "light" "400" } { "angle" "0" "origin" "1420 1292 -672" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1432 1072 -688" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1064 1304 -672" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1120 968 -672" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "984 904 -752" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "584 968 -832" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "864 1016 -1008" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "864 872 -1008" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "1112 872 -1008" "classname" "light_torch_small_walltorch" } { "light" "200" "angle" "0" "origin" "1112 1064 -1008" "classname" "light_torch_small_walltorch" } { "origin" "1112 1272 -952" "classname" "light_torch_small_walltorch" "light" "250" } { "light" "200" "angle" "0" "origin" "624 1280 -416" "classname" "light" } { "origin" "612 1476 -444" "classname" "light" } { "angle" "0" "origin" "880 1744 -448" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "640 1640 -408" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1336 1856 -448" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1200 1592 -432" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "1200 1544 -432" "classname" "light_torch_small_walltorch" } { "target" "t1" "angle" "0" "origin" "1104 1784 -496" "classname" "monster_hell_knight" } { "target" "t2" "targetname" "t1" "angle" "0" "origin" "1280 1784 -512" "classname" "path_corner" } { "target" "t3" "targetname" "t2" "angle" "0" "origin" "1280 1352 -512" "classname" "path_corner" } { "target" "t4" "targetname" "t3" "angle" "0" "origin" "1104 1472 -512" "classname" "path_corner" } { "target" "t1" "targetname" "t4" "angle" "0" "origin" "1104 1736 -512" "classname" "path_corner" } { "classname" "light_torch_small_walltorch" "origin" "1336 1288 -448" "angle" "0" } { "target" "t5" "sounds" "1" "speed" "300" //Q-Man "targetname" "t7" "classname" "func_train" "model" "*1" } { "wait" "2" "target" "t6" "targetname" "t5" "origin" "32 1216 -1008" "classname" "path_corner" } { "wait" "2" "targetname" "t6" "target" "t5" "classname" "path_corner" "origin" "32 1216 -1368" } { "target" "t7" "classname" "trigger_once" "model" "*2" } { "targetname" "t11" "target" "t8" "wait" "1" "origin" "512 1216 -1384" "classname" "path_corner" } { "target" "t11" "sounds" "1" "targetname" "t7" "classname" "func_train" "dmg" "100" "speed" "300" "model" "*3" } { "target" "t10" "targetname" "t9" "wait" "1" "origin" "512 1216 -992" "classname" "path_corner" } { "target" "t9" "targetname" "t8" "wait" "1" "origin" "512 1216 -1192" "classname" "path_corner" } { "spawnflags" "2048" "speed" "10" "wait" "-1" "angle" "-2" "classname" "func_door" "target" "t27" "targetname" "t90" "sounds" "3" "model" "*4" } { "target" "t11" "targetname" "t10" "classname" "path_corner" "origin" "512 1216 -1192" "wait" "1" } { "light" "200" "origin" "608 1280 -544" "classname" "light" } { "light" "200" "origin" "136 1280 -968" "classname" "light" } { "targetname" "t15" "spawnflags" "2085" "angle" "90" "classname" "func_door" "speed" "50" "sounds" "1" "model" "*5" } { "targetname" "t13" "spawnflags" "2085" "angle" "0" "classname" "func_door" "speed" "50" "sounds" "1" "model" "*6" } { "targetname" "t12" "spawnflags" "2085" "angle" "270" "classname" "func_door" "speed" "50" "sounds" "1" "model" "*7" } { "targetname" "t16" "spawnflags" "2085" "angle" "180" "classname" "func_door" "speed" "50" "sounds" "1" "model" "*8" } { "targetname" "t12" "spawnflags" "2085" "angle" "-2" "classname" "func_door" "speed" "50" "sounds" "3" "model" "*9" } { "targetname" "t15" "classname" "func_door" "angle" "-2" "spawnflags" "2085" "speed" "50" "sounds" "3" "model" "*10" } { "targetname" "t13" "spawnflags" "2085" "angle" "-2" "classname" "func_door" "speed" "50" "sounds" "3" "model" "*11" } { "targetname" "t16" "classname" "func_door" "angle" "-2" "spawnflags" "2085" "speed" "50" "sounds" "3" "model" "*12" } { "targetname" "t17" "spawnflags" "1" "target" "t12" "classname" "trigger_multiple" //Q-Man "model" "*13" } { "targetname" "t17" "spawnflags" "1" "target" "t13" "classname" "trigger_multiple" "model" "*14" } { "spawnflags" "1" "target" "t15" "classname" "trigger_multiple" "targetname" "t24" "model" "*15" } { "target" "t16" "spawnflags" "1" "classname" "trigger_multiple" "targetname" "t27" "model" "*16" } { "light" "200" "origin" "608 352 -488" "classname" "light" } { "classname" "light" "origin" "608 632 -488" "light" "200" } { "light" "200" "origin" "744 496 -488" "classname" "light" } { "classname" "light" "origin" "464 496 -488" "light" "200" } { "light" "200" "origin" "336 496 -608" "classname" "light" } { "classname" "light" "origin" "608 768 -608" "light" "200" } { "light" "200" "origin" "608 224 -608" "classname" "light" } { "classname" "light" "origin" "880 496 -608" "light" "200" } { "classname" "light" "origin" "1248 792 -472" "light" "160" } { "classname" "func_door" "angle" "-2" "spawnflags" "1" "sounds" "4" "speed" "40" "wait" "10" "model" "*17" } { "speed" "40" "sounds" "4" "spawnflags" "2049" "angle" "-2" "classname" "func_door" "wait" "10" "model" "*18" } { "classname" "func_door" "angle" "-2" "spawnflags" "2049" "sounds" "4" "speed" "40" "wait" "10" "model" "*19" } { "speed" "40" "sounds" "4" "spawnflags" "2049" "angle" "-2" "classname" "func_door" "wait" "10" "model" "*20" } { "classname" "func_door" "angle" "-2" "spawnflags" "2049" "sounds" "4" "speed" "40" "targetname" "t19" "wait" "10" "model" "*21" } { "spawnflags" "2048" "classname" "func_button" "angle" "0" "sounds" "3" "target" "t19" "model" "*22" } { "classname" "light_torch_small_walltorch" "origin" "1408 288 -432" "angle" "0" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2049" "sounds" "1" "targetname" "t23" "model" "*23" } { "classname" "light_torch_small_walltorch" "origin" "1802 330 -492" } { "classname" "light_torch_small_walltorch" "origin" "1826 154 -468" } { "origin" "1826 610 -468" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "1912 384 -328" "light" "200" } { "classname" "light" "origin" "2120 648 -696" "light" "160" } { "light" "160" "origin" "2104 384 -696" "classname" "light" } { "classname" "light" "origin" "2104 24 -696" "light" "160" } { "light" "200" "origin" "2320 48 -696" "classname" "light" } { "classname" "light" "origin" "2272 624 -696" "light" "200" } { "light" "200" "origin" "2296 448 -696" "classname" "light" } { "classname" "light" "origin" "2232 240 -696" "light" "200" } { "classname" "light" "origin" "2120 560 -544" } { "origin" "2120 136 -544" "classname" "light" } { "classname" "light" "origin" "1880 288 -520" "light" "160" } { "light" "160" "origin" "1880 480 -520" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "2522 386 -492" } { "classname" "light_torch_small_walltorch" "origin" "2826 506 -604" "light" "250" } { "origin" "2826 266 -604" "classname" "light_torch_small_walltorch" "light" "250" } { "classname" "light" "origin" "2488 384 -760" "light" "160" } { "origin" "2570 386 -604" "classname" "light_torch_small_walltorch" "light" "250" } { "light" "200" "origin" "2376 608 -696" "classname" "light" } { "classname" "light" "origin" "2376 152 -696" "light" "200" } { "classname" "light" "origin" "2944 768 -568" "light" "250" } { "classname" "light" "origin" "2944 800 -208" "light" "400" } { "classname" "light" "origin" "2944 800 -312" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "2498 650 -324" } { "origin" "2650 890 -324" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2946 634 -324" } { "classname" "light" "origin" "2848 512 -344" "light" "200" } { "classname" "func_plat" "model" "*24" } { "classname" "func_plat" "model" "*25" } { "classname" "light" "origin" "2792 384 -256" "light" "200" } { "light" "200" "origin" "2624 384 -256" "classname" "light" } { "origin" "2498 122 -324" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2986 -174 -340" } { "origin" "2842 298 -204" "classname" "light_torch_small_walltorch" } { "origin" "2570 -54 -340" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "2776 216 -408" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "2442 210 -588" } { "light" "200" "origin" "2808 168 -568" "classname" "light" } { "classname" "light" "origin" "2640 -8 -592" "light" "200" } { "light" "200" "origin" "2616 248 -408" "classname" "light" } { "classname" "light" "origin" "2936 128 -360" "light" "200" } { "classname" "light" "origin" "2568 208 -240" "light" "200" } { "origin" "2986 -174 -564" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "2944 144 -616" "light" "200" } { "classname" "light" "origin" "2840 40 -200" "light" "200" } { "classname" "light" "origin" "2808 88 -760" "light" "180" } { "light" "180" "origin" "2944 128 -760" "classname" "light" } { "classname" "light" "origin" "2944 -72 -760" "light" "180" } { "light" "180" "origin" "2696 248 -696" "classname" "light" } { "light" "180" "origin" "2664 -136 -760" "classname" "light" } { "classname" "light" "origin" "2632 48 -760" "light" "180" } { "light" "150" "origin" "2496 208 -760" "classname" "light" } { "spawnflags" "2048" "classname" "func_button" "angle" "270" "wait" "-1" "sounds" "1" "target" "t21" "message" "The bar has been drawn..." "model" "*26" } { "targetname" "t72" "spawnflags" "2048" "classname" "func_door" "angle" "-2" "speed" "30" "sounds" "1" "target" "t24" "wait" "-1" "model" "*27" } { "spawnflags" "2048" "classname" "func_door" "angle" "270" "sounds" "4" "speed" "30" "targetname" "t21" "wait" "-1" "model" "*28" } { "spawnflags" "2048" "classname" "func_button" "angle" "180" "wait" "-1" "sounds" "1" "target" "t23" "model" "*29" } { "classname" "light" "origin" "2376 504 -696" "light" "200" } { "light" "200" "origin" "2376 264 -696" "classname" "light" } { "classname" "light" "origin" "2376 560 -504" "light" "200" } { "light" "200" "origin" "2376 208 -504" "classname" "light" } { "classname" "func_door_secret" "angle" "270" "spawnflags" "2049" "targetname" "t24" "model" "*30" } { "classname" "trigger_multiple" "spawnflags" "1" "target" "t13" "targetname" "t27" "model" "*31" } { "classname" "trigger_multiple" "spawnflags" "1" "target" "t12" "targetname" "t24" "model" "*32" } { "classname" "light" "origin" "2440 40 -696" "light" "160" } { "light" "160" "origin" "2416 664 -696" "classname" "light" } { "classname" "light" "origin" "2408 456 -264" "light" "160" } { "light" "160" "origin" "2408 312 -264" "classname" "light" } { "classname" "light" "origin" "2408 104 -264" "light" "160" } { "light" "160" "origin" "2400 664 -264" "classname" "light" } { "sounds" "1" "targetname" "t24" "spawnflags" "2049" "angle" "0" "classname" "func_door_secret" "model" "*33" } { "light" "250" "origin" "2202 -310 -324" "classname" "light_torch_small_walltorch" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "2458 -294 -404" } { "light" "250" "origin" "2786 -374 -404" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2074 -110 -300" } { "light" "160" "origin" "1920 -272 -336" "classname" "light" } { "classname" "light" "origin" "744 960 -448" "angle" "0" "light" "200" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "3" "model" "*34" } { "classname" "func_plat" "sounds" "2" "spawnflags" "1" "model" "*35" } { "classname" "light" "origin" "648 960 -1024" "light" "160" } { "classname" "func_door" "angle" "180" "sounds" "3" "wait" "-1" "spawnflags" "2048" "speed" "30" "targetname" "t30" "message" "This door opens elsewhere..." "model" "*36" } { "classname" "light_torch_small_walltorch" "origin" "1018 1170 -476" } { "spawnflags" "2048" "classname" "item_key2" "origin" "800 1312 -552" } { "speed" "30" "spawnflags" "2048" "wait" "-1" "sounds" "3" "angle" "90" "classname" "func_door" "targetname" "t28" "model" "*37" } { "classname" "func_door" "angle" "-1" "sounds" "3" "wait" "-1" "spawnflags" "2048" "speed" "30" "targetname" "t26" "model" "*38" } { "speed" "30" "spawnflags" "2048" "wait" "-1" "sounds" "3" "angle" "-1" "classname" "func_door" "targetname" "t29" "model" "*39" } { "spawnflags" "2048" "classname" "func_button" "angle" "180" "wait" "-1" "sounds" "2" "target" "t26" "model" "*40" } { "classname" "func_door" "spawnflags" "2056" "angle" "-2" "speed" "30" "wait" "-1" "sounds" "3" "target" "t92" "model" "*41" } { "classname" "light_torch_small_walltorch" "origin" "1402 1274 -908" "light" "250" } { "spawnflags" "2048" "classname" "func_button" "angle" "270" "wait" "-1" "sounds" "2" "target" "t28" "model" "*42" } { "spawnflags" "2048" "classname" "func_button" "angle" "270" "wait" "-1" "sounds" "2" "target" "t29" "model" "*43" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t30" "model" "*44" } { "classname" "light_torch_small_walltorch" "origin" "266 1282 -820" } { "classname" "light" "origin" "1064 1384 -960" "light" "200" } { "light" "200" "origin" "1064 1152 -960" "classname" "light" } { "classname" "light" "origin" "832 1296 -712" "light" "200" } { "classname" "light" "origin" "1008 1640 -672" "light" "200" } { "light" "200" "origin" "1168 1640 -672" "classname" "light" } { "classname" "light" "origin" "1256 1584 -672" "light" "200" } { "light" "200" "origin" "1256 1424 -672" "classname" "light" } { "classname" "trigger_once" "spawnflags" "2049" "message" "The third floor is accessible..." "targetname" "t29" "model" "*45" } { "classname" "trigger_once" "spawnflags" "1" "message" "The second floor is accessible..." "targetname" "t26" "model" "*46" } { "classname" "light_torch_small_walltorch" "origin" "818 1210 -684" "light" "220" } { "classname" "light" "origin" "1344 1272 -992" "light" "120" } { "classname" "light" "origin" "1248 1104 -912" "light" "250" } { "light" "250" "origin" "1248 1456 -912" "classname" "light" } { "classname" "light" "origin" "128 1104 -560" "angle" "0" "light" "200" } { "classname" "light" "origin" "1080 1368 -744" "light" "130" } { "classname" "light" "origin" "216 1280 -944" "light" "130" } { "light" "130" "origin" "216 1280 -816" "classname" "light" } { "classname" "light" "origin" "216 1280 -688" "light" "130" } { "classname" "func_door" "targetname" "t32" "wait" "-1" "speed" "20" "sounds" "1" "angle" "-2" "model" "*47" } { "classname" "func_door" "spawnflags" "1" "angle" "-2" "sounds" "4" "wait" "10" "speed" "400" "targetname" "t31" "model" "*48" } { "classname" "light_torch_small_walltorch" "origin" "26 546 -428" "light" "250" } { "origin" "26 450 -428" "classname" "light_torch_small_walltorch" "light" "250" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t31" "model" "*49" } { "classname" "trigger_once" "spawnflags" "1" "targetname" "t31" "delay" "6" "target" "t32" "model" "*50" } { "classname" "light" "origin" "136 496 -440" "light" "200" } { "light" "200" "origin" "-88 496 -440" "classname" "light" } { "classname" "monster_shambler" "origin" "-360 1032 -408" "angle" "270" "targetname" "t31" "spawnflags" "256" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t33" "model" "*51" } { "classname" "info_teleport_destination" "origin" "184 496 -512" "angle" "180" "targetname" "t33" } { "classname" "light" "origin" "-80 584 -584" "light" "200" } { "light" "200" "origin" "-80 408 -584" "classname" "light" } { "classname" "light" "origin" "136 408 -584" "light" "200" } { "light" "200" "origin" "136 584 -584" "classname" "light" } { "classname" "light" "origin" "136 584 -720" "light" "160" } { "light" "160" "origin" "136 408 -720" "classname" "light" } { "classname" "light" "origin" "-80 408 -720" "light" "160" } { "light" "160" "origin" "-80 584 -720" "classname" "light" } { "classname" "light" "origin" "136 584 -840" "light" "200" } { "light" "200" "origin" "136 408 -840" "classname" "light" } { "classname" "light" "origin" "-80 408 -840" "light" "200" } { "light" "200" "origin" "-80 584 -840" "classname" "light" } { "classname" "light" "origin" "136 584 -992" "light" "200" } { "light" "200" "origin" "136 408 -992" "classname" "light" } { "classname" "light" "origin" "-80 408 -992" "light" "200" } { "light" "200" "origin" "-80 584 -992" "classname" "light" } { "classname" "trigger_multiple" "wait" "0.5" "target" "t34" "model" "*52" } { "classname" "trap_spikeshooter" "origin" "0 496 -648" "angle" "180" "targetname" "t34" } { "angle" "0" "origin" "48 496 -648" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "trap_spikeshooter" "origin" "24 520 -648" "angle" "90" "targetname" "t34" } { "angle" "270" "origin" "24 472 -648" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "monster_zombie" "origin" "-144 496 -496" "angle" "0" } { "spawnflags" "1" "classname" "monster_zombie" "origin" "-192 496 -400" "angle" "0" } { "angle" "270" "origin" "-568 1032 -408" "classname" "monster_demon1" "targetname" "t34" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t35" "model" "*53" } { "classname" "info_teleport_destination" "origin" "-136 496 -632" "targetname" "t35" } { "classname" "func_train" "sounds" "1" "target" "t36" "targetname" "t42" "speed" "25" "model" "*54" } { "classname" "func_train" "sounds" "1" "target" "t39" "targetname" "t42" "speed" "25" "model" "*55" } { "classname" "path_corner" "origin" "-208 496 -1072" "targetname" "t36" "target" "t37" } { "origin" "-384 496 -1072" "classname" "path_corner" "targetname" "t37" "target" "t38" } { "classname" "path_corner" "origin" "-384 592 -1072" "targetname" "t38" "target" "t37" "wait" "-1" } { "origin" "-208 400 -1072" "classname" "path_corner" "targetname" "t39" "target" "t40" } { "classname" "path_corner" "origin" "-384 400 -1072" "targetname" "t40" "target" "t41" } { "origin" "-384 304 -1072" "classname" "path_corner" "targetname" "t41" "target" "t40" "wait" "-1" } { "classname" "trigger_once" "target" "t42" "model" "*56" } { "classname" "light" "origin" "-264 496 -984" "light" "160" } { "light" "160" "origin" "-392 496 -984" "classname" "light" } { "classname" "monster_demon1" "origin" "-360 1032 -408" "spawnflags" "1536" "targetname" "t31" } { "spawnflags" "769" "angle" "270" "origin" "-440 1032 -408" "classname" "monster_shambler" "targetname" "t43" } { "classname" "trigger_once" "spawnflags" "1" "targetname" "t31" "target" "t43" "delay" "3" "model" "*57" } { "classname" "trigger_once" "target" "t50" "model" "*58" } { "classname" "func_door" "angle" "90" "targetname" "t50" "model" "*59" } { "classname" "monster_zombie" "origin" "-88 936 -360" "targetname" "t50" } { "spawnflags" "768" "origin" "-88 1000 -360" "classname" "monster_zombie" "targetname" "t50" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "-88 1064 -360" "targetname" "t50" } { "spawnflags" "256" "origin" "-152 1064 -360" "classname" "monster_zombie" "targetname" "t50" } { "spawnflags" "768" "classname" "monster_zombie" "origin" "-152 1000 -360" "targetname" "t50" } { "origin" "-152 936 -360" "classname" "monster_zombie" "targetname" "t50" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t47" "model" "*60" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t46" "model" "*61" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t45" "model" "*62" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t44" "model" "*63" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t48" "model" "*64" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t49" "model" "*65" } { "classname" "info_teleport_destination" "origin" "-152 344 -736" "angle" "45" "targetname" "t46" } { "classname" "info_teleport_destination" "origin" "24 344 -744" "angle" "90" "targetname" "t45" } { "classname" "info_teleport_destination" "origin" "184 344 -736" "angle" "135" "targetname" "t44" } { "classname" "info_teleport_destination" "origin" "184 648 -736" "angle" "225" "targetname" "t47" } { "classname" "info_teleport_destination" "origin" "24 648 -736" "angle" "270" "targetname" "t48" } { "classname" "info_teleport_destination" "origin" "-152 648 -736" "angle" "315" "targetname" "t49" } { "classname" "light_torch_small_walltorch" "origin" "-406 618 -940" } { "origin" "-406 378 -940" "classname" "light_torch_small_walltorch" } { "classname" "monster_shalrath" "origin" "-504 512 -1016" "angle" "0" "target" "t51" } { "origin" "-1014 634 -940" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-1014 362 -940" } { "classname" "light" "origin" "-608 496 -728" "light" "160" } { "classname" "func_door" "angle" "-2" "targetname" "t51" "speed" "30" "sounds" "3" "wait" "-1" "spawnflags" "2048" "model" "*66" } { "target" "t87" "classname" "item_artifact_invulnerability" //Q-Man "origin" "-608 496 -984" //"spawnflags" "2" } { "light" "160" "origin" "-608 576 -800" "classname" "light" } { "classname" "light" "origin" "-608 416 -800" "light" "160" } { "light" "160" "origin" "-696 496 -800" "classname" "light" } { "classname" "light" "origin" "-520 496 -800" "light" "160" } { //"spawnflags" "2048" //Q-Man "targetname" "t60" "angle" "-2" "target" "t17" "wait" "4" "speed" "20" "sounds" "3" "classname" "func_door" "model" "*67" } { "spawnflags" "1792" "origin" "1240 1392 -1024" "classname" "weapon_supershotgun" } { "angle" "270" "origin" "544 40 -488" "classname" "monster_demon1" } { "angle" "270" "spawnflags" "769" "origin" "672 40 -488" "classname" "monster_ogre" } { //"spawnflags" "2048" "target" "t60" "classname" "trigger_multiple" //"message" "A bridge has been raised." "sounds" "3" "model" "*68" } { "spawnflags" "1792" "classname" "func_wall" "model" "*69" } { "classname" "trigger_secret" "model" "*70" } { "origin" "1120 984 -1048" "classname" "item_artifact_super_damage" } { "spawnflags" "2050" "origin" "1104 912 -1072" "classname" "item_health" } { "origin" "856 992 -1072" "classname" "item_rockets" } { "origin" "760 912 -1072" "classname" "item_spikes" } { "targetname" "t65" "target" "t62" "origin" "1064 176 -504" "classname" "path_corner" } { "target" "t64" "targetname" "t63" "classname" "path_corner" "origin" "1000 808 -504" } { "target" "t63" "targetname" "t62" "origin" "1064 808 -504" "classname" "path_corner" } { "target" "t65" "targetname" "t64" "classname" "path_corner" "origin" "1000 176 -504" } { "target" "t62" "origin" "1040 600 -488" "classname" "monster_hell_knight" } { "target" "t62" "spawnflags" "768" "origin" "1056 400 -488" "classname" "monster_hell_knight" } { "spawnflags" "1" "angle" "180" "origin" "1536 184 -392" "classname" "monster_demon1" } { "spawnflags" "257" "angle" "0" "origin" "1192 408 -488" "classname" "monster_ogre" } { "target" "t67" "targetname" "t66" "origin" "1936 624 -608" "classname" "path_corner" } { "targetname" "t67" "target" "t66" "classname" "path_corner" "origin" "1936 88 -608" } { "target" "t66" "origin" "1992 568 -592" "classname" "monster_demon1" } { "spawnflags" "769" "angle" "45" "origin" "1864 168 -592" "classname" "monster_shambler" } { "angle" "45" "origin" "2128 64 -792" "classname" "monster_zombie" } { "angle" "180" "origin" "2480 384 -792" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "270" "origin" "2144 632 -792" "classname" "monster_zombie" } { "angle" "135" "spawnflags" "768" "origin" "2240 160 -792" "classname" "monster_zombie" } { "spawnflags" "768" "angle" "180" "origin" "2400 456 -792" "classname" "monster_zombie" } { "angle" "180" "spawnflags" "768" "origin" "2400 344 -792" "classname" "monster_zombie" } { "spawnflags" "768" "angle" "90" "origin" "2144 224 -792" "classname" "monster_zombie" } { "spawnflags" "768" "origin" "2088 320 -792" "classname" "monster_zombie" } { "origin" "1832 608 -616" "classname" "item_cells" } { "classname" "item_cells" "origin" "1864 656 -616" } { "angle" "180" "origin" "2792 392 -680" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "225" "origin" "2920 520 -680" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "135" "origin" "2840 304 -680" "classname" "monster_zombie" } { "spawnflags" "257" "angle" "90" "origin" "2952 -88 -616" "classname" "monster_demon1" } { "classname" "monster_demon1" "origin" "2920 24 -616" "angle" "90" "spawnflags" "769" } { "spawnflags" "1" "angle" "270" "origin" "2824 88 -616" "classname" "monster_demon1" } { "target" "t73" "angle" "180" "origin" "2480 208 -392" "classname" "monster_ogre" } { "angle" "180" "origin" "2480 576 -392" "classname" "monster_ogre" } { "angle" "270" "origin" "2944 112 -792" "classname" "monster_zombie" } { "classname" "trigger_secret" "model" "*71" } { "origin" "2944 152 -792" "classname" "item_artifact_super_damage" } { "spawnflags" "256" "angle" "225" "origin" "2808 88 -792" "classname" "monster_zombie" } { "spawnflags" "768" "angle" "270" "origin" "2728 264 -792" "classname" "monster_zombie" } { "spawnflags" "768" "angle" "90" "origin" "2728 -144 -792" "classname" "monster_zombie" } { "spawnflags" "1" "angle" "315" "origin" "2720 248 -472" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "0" "origin" "2608 72 -472" "classname" "monster_ogre" } { "spawnflags" "769" "angle" "90" "origin" "2792 -136 -472" "classname" "monster_ogre" } { "spawnflags" "769" "angle" "45" "origin" "2632 -96 -472" "classname" "monster_ogre" } { "spawnflags" "257" "origin" "2640 -336 -472" "classname" "monster_demon1" } { "spawnflags" "257" "origin" "2040 -208 -408" "classname" "monster_ogre" } { "angle" "45" "origin" "1920 -280 -408" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "270" "origin" "2056 -88 -408" "classname" "monster_zombie" } { "spawnflags" "1792" "origin" "2656 608 -416" "classname" "weapon_rocketlauncher" } { "target" "t71" "targetname" "t70" "origin" "2592 520 -408" "classname" "path_corner" } { "target" "t70" "targetname" "t69" "classname" "path_corner" "origin" "2592 840 -408" } { "target" "t69" "targetname" "t68" "origin" "2760 840 -408" "classname" "path_corner" } { "targetname" "t71" "target" "t68" "classname" "path_corner" "origin" "2760 520 -408" } { "target" "t69" "spawnflags" "257" "origin" "2696 816 -392" "classname" "monster_hell_knight" } { "target" "t71" "spawnflags" "256" "origin" "2720 504 -392" "classname" "monster_hell_knight" } { "angle" "270" "spawnflags" "256" "origin" "2944 864 -368" "classname" "monster_wizard" } { "angle" "135" "spawnflags" "256" "origin" "1696 304 -336" "classname" "monster_wizard" } { "spawnflags" "257" "angle" "180" "origin" "1664 800 -584" "classname" "monster_demon1" } { "spawnflags" "2048" "target" "t72" "classname" "trigger_once" "message" "The center bridge has changed..." "sounds" "3" "model" "*72" } { "light" "180" "origin" "608 216 -832" "classname" "light" } { "classname" "light" "origin" "328 496 -832" "light" "180" } { "light" "180" "origin" "888 496 -832" "classname" "light" } { "classname" "light" "origin" "608 776 -832" "light" "180" } { "origin" "592 320 -528" "classname" "item_shells" } { "origin" "760 480 -528" "classname" "item_spikes" } { "origin" "592 648 -528" "classname" "item_cells" } { "origin" "464 496 -528" "classname" "item_armor2" "spawnflags" "2048" } { "origin" "1008 776 -512" "classname" "item_shells" } { "origin" "1456 168 -416" "classname" "item_spikes" } { "origin" "1624 288 -608" "classname" "item_health" } { "classname" "item_health" "origin" "1624 336 -608" "spawnflags" "1536" } { "origin" "1680 336 -608" "classname" "item_health" } { "origin" "1648 576 -608" "classname" "item_rockets" } { "origin" "2368 624 -816" "classname" "item_shells" } { "origin" "2008 8 -616" "classname" "item_rockets" } { "spawnflags" "1" "origin" "2384 -8 -816" "classname" "item_rockets" } { "origin" "3000 728 -640" "classname" "item_health" } { "spawnflags" "1" "classname" "item_health" "origin" "2856 728 -640" } { "origin" "1320 216 -416" "classname" "item_health" } { "origin" "2080 640 -816" "classname" "item_health" } { "classname" "item_health" "origin" "2072 -8 -816" } { "spawnflags" "2049" "classname" "func_plat" "model" "*73" } { "origin" "2928 -176 -656" "classname" "item_health" } { "spawnflags" "1" "origin" "2968 -40 -640" "classname" "item_shells" } { "spawnflags" "257" "angle" "180" "origin" "2928 512 -392" "classname" "monster_demon1" } { "origin" "2968 520 -416" "classname" "item_health" } { "spawnflags" "1" "origin" "2456 504 -416" "classname" "item_spikes" } { "origin" "2480 616 -416" "classname" "item_rockets" } { "targetname" "t73" "spawnflags" "769" "origin" "2504 -520 -280" "classname" "monster_shambler" } { "target" "t74" "spawnflags" "2" "classname" "trigger_teleport" "model" "*74" } { "targetname" "t74" "angle" "180" "origin" "2800 224 -296" "classname" "info_teleport_destination" } { "spawnflags" "1" "origin" "2480 128 -416" "classname" "item_rockets" } { "spawnflags" "257" "angle" "90" "origin" "2808 -296 -472" "classname" "monster_ogre" } { "origin" "1888 -240 -432" "classname" "item_shells" } { "origin" "1880 -160 -432" "classname" "item_spikes" } { "origin" "776 768 -880" "classname" "item_health" } { "classname" "item_health" "origin" "384 248 -880" } { "spawnflags" "1" "origin" "2640 232 -304" "classname" "item_shells" } { "origin" "2392 -344 -496" "classname" "item_health" } { "angle" "180" "spawnflags" "1" "origin" "944 992 -552" "classname" "monster_hell_knight" } { "origin" "608 960 -512" "classname" "item_armor2" "spawnflags" "2048" } { "angle" "270" "origin" "128 1280 -616" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "225" "origin" "416 1448 -776" "classname" "monster_wizard" } { "classname" "monster_wizard" "origin" "416 1112 -776" "angle" "135" "spawnflags" "768" } { "target" "t76" "targetname" "t75" "origin" "416 1408 -984" "classname" "path_corner" } { "targetname" "t76" "target" "t75" "classname" "path_corner" "origin" "416 1152 -984" } { "spawnflags" "256" "target" "t76" "origin" "352 1240 -968" "classname" "monster_ogre" } { "target" "t79" "targetname" "t78" "origin" "808 1416 -984" "classname" "path_corner" } { "target" "t78" "targetname" "t77" "classname" "path_corner" "origin" "936 1416 -984" } { "targetname" "t80" "target" "t77" "origin" "936 1128 -984" "classname" "path_corner" } { "target" "t80" "targetname" "t79" "classname" "path_corner" "origin" "808 1128 -984" } { "target" "t79" "spawnflags" "1" "origin" "856 1200 -968" "classname" "monster_hell_knight" } { "spawnflags" "1" "angle" "180" "origin" "1312 1272 -1000" "classname" "monster_demon1" "targetname" "t92" } { "spawnflags" "769" "angle" "180" "origin" "1232 1160 -1000" "classname" "monster_shambler" } { "angle" "90" "origin" "616 1136 -752" "classname" "monster_ogre" } { "angle" "270" "origin" "616 1416 -552" "classname" "monster_ogre" } { "angle" "180" "spawnflags" "257" "origin" "976 1152 -744" "classname" "monster_demon1" } { "spawnflags" "1" "angle" "180" "origin" "1120 1160 -744" "classname" "monster_ogre" } { "targetname" "t82" "target" "t81" "origin" "960 1312 -768" "classname" "path_corner" } { "target" "t82" "targetname" "t81" "classname" "path_corner" "origin" "824 1312 -768" } { "spawnflags" "257" "target" "t82" "origin" "904 1304 -752" "classname" "monster_hell_knight" } { "spawnflags" "257" "angle" "270" "origin" "936 1624 -768" "classname" "monster_demon1" } { "target" "t84" "targetname" "t83" "origin" "1224 1608 -784" "classname" "path_corner" } { "target" "t85" "targetname" "t84" "classname" "path_corner" "origin" "1016 1608 -784" } { "target" "t86" "targetname" "t85" "origin" "1016 1464 -784" "classname" "path_corner" } { "targetname" "t86" "target" "t83" "classname" "path_corner" "origin" "1224 1464 -784" } { "target" "t83" "origin" "1208 1552 -768" "classname" "monster_hell_knight" } { "target" "t84" "spawnflags" "257" "origin" "1088 1584 -768" "classname" "monster_hell_knight" } { "target" "t85" "spawnflags" "257" "origin" "984 1512 -768" "classname" "monster_hell_knight" } { "target" "t86" "spawnflags" "769" "origin" "1176 1432 -768" "classname" "monster_hell_knight" } { "spawnflags" "256" "angle" "90" "origin" "1080 1368 -768" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1256 1368 -768" "angle" "90" "spawnflags" "768" } { "spawnflags" "1" "angle" "270" "origin" "1128 1272 -744" "classname" "monster_ogre" } { "spawnflags" "1" "angle" "90" "origin" "1336 1016 -744" "classname" "monster_demon1" } { "spawnflags" "769" "angle" "90" "origin" "1360 1104 -744" "classname" "monster_demon1" } { "spawnflags" "257" "angle" "180" "origin" "864 1784 -496" "classname" "monster_demon1" } { "classname" "monster_demon1" "origin" "968 1784 -496" "angle" "180" "spawnflags" "769" } { "target" "t3" "spawnflags" "257" "origin" "1208 1368 -496" "classname" "monster_hell_knight" } { "target" "t4" "spawnflags" "769" "origin" "1152 1680 -496" "classname" "monster_hell_knight" } { "angle" "0" "spawnflags" "1" "origin" "872 1336 -552" "classname" "monster_demon1" } { "origin" "616 1488 -576" "classname" "weapon_grenadelauncher" //Q-Man } { "spawnflags" "1792" "origin" "-88 496 -520" "classname" "weapon_supernailgun" } { "targetname" "t87" "angle" "-2" "wait" "-1" "speed" "20" "sounds" "4" //"message" "You must grab the Black Magic Rune!" "classname" "func_door" "model" "*75" } { "origin" "952 920 -576" "classname" "item_spikes" } { "origin" "336 1344 -992" "classname" "item_shells" } { "origin" "344 1168 -992" "classname" "item_spikes" } { "origin" "656 1408 -968" "classname" "item_health" } { "classname" "item_health" "origin" "656 1120 -968" } { "origin" "696 1120 -776" "classname" "item_health" } { "origin" "944 1232 -776" "classname" "item_health" } { "spawnflags" "1" "origin" "784 1256 -784" "classname" "item_shells" } { "spawnflags" "1" "origin" "1112 1352 -792" "classname" "item_rockets" } { "spawnflags" "1" "origin" "1088 1520 -792" "classname" "item_spikes" } { "spawnflags" "1" "origin" "1232 992 -768" "classname" "item_shells" } { "origin" "1392 1008 -768" "classname" "item_health" } { "origin" "1232 1664 -520" "classname" "item_health" } { "classname" "item_health" "origin" "1184 1824 -520" } { "spawnflags" "1" "origin" "1112 1384 -520" "classname" "item_health" } { "spawnflags" "1" "origin" "1184 1312 -520" "classname" "item_spikes" } { "spawnflags" "1" "origin" "1224 1216 -1024" "classname" "item_rockets" } { "spawnflags" "1" "origin" "1224 1264 -1024" "classname" "item_shells" } { "origin" "1128 1200 -1024" "classname" "item_cells" } { //"spawnflags" "1" "origin" "1280 1144 -1024" "classname" "item_health" } { "spawnflags" "1" "origin" "-64 480 -520" "classname" "item_cells" } { "spawnflags" "2" "origin" "128 488 -520" "classname" "item_health" } { "classname" "trigger_changelevel" "map" "start" "model" "*76" } { "classname" "trigger_teleport" "target" "t88" "model" "*77" } { "classname" "info_teleport_destination" "origin" "-1056 504 -1032" "targetname" "t88" } { "classname" "light" "origin" "-776 496 -928" "light" "200" } { "classname" "info_null" "origin" "-608 496 -1004" "targetname" "t89" } { "classname" "light" "origin" "-608 496 -824" "target" "t89" } { "classname" "light" "origin" "-920 496 -952" "light" "200" } { "classname" "info_intermission" "origin" "832 272 -240" "mangle" "20 135 0" } { "classname" "info_intermission" "origin" "2096 656 -640" "mangle" "-20 315 0" } { "classname" "info_intermission" "origin" "-168 328 -352" "mangle" "20 45 0" } { "classname" "ambient_swamp1" "origin" "2242 354 -648" } { "classname" "light" "origin" "608 -144 -440" "light" "180" } { "classname" "light" "origin" "1928 -64 -384" "light" "180" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t90" "sounds" "3" "message" "The center bridge has changed..." "model" "*78" } { "classname" "light" "origin" "2944 800 -392" "light" "180" } { "classname" "item_spikes" "origin" "488 1560 -576" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1288 1504 -520" "spawnflags" "1" } { "spawnflags" "1" "origin" "1288 1432 -520" "classname" "item_spikes" } { "classname" "light" "origin" "1144 1168 -864" "light" "180" } { "light" "180" "origin" "1144 1368 -864" "classname" "light" } { "classname" "item_spikes" "origin" "8 408 -520" "spawnflags" "1" } { "classname" "item_rockets" "origin" "8 552 -520" "spawnflags" "1" } { "classname" "monster_shalrath" "origin" "-728 368 -1016" "angle" "0" "spawnflags" "256" } { "classname" "info_player_deathmatch" "origin" "1856 576 -592" "angle" "315" } { "classname" "info_player_deathmatch" "origin" "2672 848 -392" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "2616 -72 -472" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "616 1408 -552" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "1248 1632 -768" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "-160 656 -496" "angle" "315" } { "classname" "light" "origin" "-856 496 -976" "light" "200" } { "classname" "item_health" "origin" "-776 624 -1040" } { "classname" "item_spikes" "origin" "-848 328 -1040" } { "classname" "item_artifact_super_damage" "origin" "608 -120 -488" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "2482 240 -392" //Q-Man "spawnflags" "1792" } { "classname" "trigger_once" "target" "t7" "spawnflags" "1792" "model" "*79" } { "spawnflags" "1792" "classname" "trigger_once" "target" "t7" "model" "*80" } { "classname" "trigger_once" "target" "t7" "model" "*81" } { "classname" "trigger_once" "target" "t7" "spawnflags" "1792" "model" "*82" } { "classname" "func_button" "angle" "-1" "wait" "-1" "spawnflags" "1792" "target" "t32" "health" "1" "model" "*83" } { "classname" "monster_ogre" "origin" "2512 -520 -280" "spawnflags" "1281" "targetname" "t73" } { "light" "200" "origin" "-40 496 -272" "classname" "light" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "824 -304 -368" } { "origin" "824 -496 -368" "classname" "light_torch_small_walltorch" "light" "250" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "392 -496 -368" } { "classname" "light" "origin" "608 -520 -264" "light" "200" } { "light" "200" "origin" "608 -504 -384" "classname" "light" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "608 -80 -400" } { "classname" "info_player_start" "origin" "608 -496 -440" "angle" "90" } { "classname" "info_player_coop" "origin" "688 -496 -440" "angle" "90" } { "origin" "752 -496 -440" "classname" "info_player_coop" "angle" "90" } { "classname" "info_player_coop" "origin" "528 -496 -440" "angle" "90" } { "origin" "464 -496 -440" "classname" "info_player_coop" "angle" "90" } { "classname" "item_armor1" "origin" "768 -352 -480" } { "classname" "item_shells" "origin" "424 -352 -480" } { "classname" "func_wall" "spawnflags" "1792" "model" "*84" } { "classname" "func_plat" "spawnflags" "2049" "model" "*85" } { "spawnflags" "2049" "classname" "func_plat" "model" "*86" } { "classname" "func_plat" "spawnflags" "2049" "model" "*87" } { "classname" "trigger_relay" "origin" "2464 152 -408" "targetname" "t73" } { "classname" "item_health" "origin" "784 -464 -464" } { "origin" "400 -464 -464" "classname" "item_health" } { "targetname" "t17" "speed" "30" "wait" "4" //Q-Man "sounds" "1" "angle" "180" "classname" "func_door" "model" "*88" } { "light" "160" "origin" "608 120 -464" "classname" "light" } //Q-Man { "classname" "item_flag_team1" "origin" "2589 235 -280" } { "classname" "info_player_team1" "origin" "2606 150 -280" } { "classname" "info_player_team1" "origin" "2799 239 -280" "angle" "270" } { "classname" "info_player_team1" "origin" "2919 0 -424" "angle" "180" } { "classname" "info_player_team1" "origin" "2602 62 -472" } { "classname" "info_player_team1" "origin" "2804 75 -616" "angle" "180" } { "classname" "info_player_team1" "origin" "2952 -8 -616" "angle" "90" } { "classname" "item_flag_team2" "origin" "1374 1270 -1000" } { "classname" "info_player_team2" "origin" "1184 1271 -1000" } { "classname" "info_player_team2" "origin" "1184 1367 -1000" } { "classname" "info_player_team2" "origin" "1184 1139 -1000" } { "classname" "info_player_team2" "origin" "868 1264 -968" } { "classname" "info_player_team2" "origin" "591 1292 -944" } { "classname" "info_player_team2" "origin" "120 1278 -616" } { "classname" "item_armorInv" "origin" "1176 407 -488" } { "classname" "weapon_lightning" "origin" "609 493 -504" } { "classname" "weapon_supershotgun" "origin" "610 110 -488" } { "classname" "weapon_rocketlauncher" "origin" "923 1635 -768" } { "classname" "trigger_teleport" "target" "Q-Man" "model" "*76" } { "classname" "info_teleport_destination" "origin" "608 -496 -440" "angle" "90" "targetname" "Q-Man" } { "classname" "item_armor2" "origin" "2783 -324 -472" } { "classname" "item_armor2" "origin" "1330 1120 -744" } { "origin" "2575 140 -280" "classname" "item_health" "spawnflags" "1" } { "origin" "1516 193 -392" "classname" "item_armor1" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e2m7.ent000066400000000000000000001450151475442401000252040ustar00rootroot00000000000000{ "wad" "gfx/tim.wad" "classname" "worldspawn" "sounds" "7" "worldtype" "0" "message" "the Underearth" } { "angle" "90" "origin" "1136 -1100 -72" "classname" "info_player_start" } { "origin" "1184 -776 -152" "classname" "light" "light" "150" } { "classname" "light" "origin" "1704 -584 -184" "light" "150" } { "classname" "light" "origin" "1640 -688 -184" "light" "150" } { "classname" "light" "origin" "1696 -888 -192" "light" "150" } { "classname" "light" "origin" "1088 -960 -152" "light" "150" } { "classname" "light" "origin" "1248 -960 -152" "light" "150" } { "classname" "light" "origin" "1016 -768 -152" "light" "100" } { "classname" "light" "origin" "896 -920 -152" "light" "150" } { "light" "100" "origin" "1584 -208 -112" "classname" "light" } { "light" "100" "origin" "1776 -208 -112" "classname" "light" } { "light" "150" "origin" "1584 -88 -112" "classname" "light" } { "origin" "1774 58 -76" "classname" "light_torch_small_walltorch" } { "light" "100" "origin" "1584 -488 -232" "classname" "light" } { "light" "100" "origin" "1768 -480 -232" "classname" "light" } { "light" "150" "origin" "1752 -112 -176" "classname" "light" } { "light" "150" "origin" "1592 -120 -176" "classname" "light" } { "light" "150" "origin" "1592 -248 -192" "classname" "light" } { "light" "200" "origin" "1768 -240 -192" "classname" "light" } { "light" "150" "origin" "1676 -220 -188" "classname" "light" } { "light" "150" "origin" "1672 -40 -136" "classname" "light" } { "light" "150" "origin" "1676 -376 -252" "classname" "light" } { "light" "250" "origin" "1112 952 -92" "classname" "light" } { "light" "200" "origin" "1280 928 -152" "classname" "light" } { "classname" "light" "origin" "704 952 -92" "light" "250" } { "classname" "light" "origin" "824 1112 -92" "light" "200" } { "classname" "light" "origin" "952 760 -92" "light" "200" } { "classname" "light" "origin" "824 760 -92" "light" "200" } { "light" "250" "origin" "952 1112 -92" "classname" "light" } { "classname" "light" "origin" "1128 -848 288" "light" "500" } { "classname" "light" "origin" "1144 -432 288" } { "classname" "light" "origin" "864 -552 272" "light" "200" } { "classname" "light" "origin" "1392 -568 168" "light" "200" } { "classname" "light" "origin" "1416 -592 -24" "light" "150" } { "classname" "light" "origin" "888 -584 -24" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "1058 -466 -24" "light" "225" } { "origin" "1214 -466 -24" "classname" "light_torch_small_walltorch" "light" "225" } { "classname" "light_torch_small_walltorch" "origin" "1198 -66 40" "light" "300" } { "classname" "light" "origin" "1144 -204 172" "light" "150" } { "classname" "light" "origin" "1144 -292 -32" "light" "150" } { "classname" "item_spikes" "origin" "880 -592 -96" "spawnflags" "1" } { "classname" "item_health" "origin" "1068 -944 -96" } { "classname" "light" "origin" "1128 -1084 96" "light" "300" } { "classname" "light" "origin" "888 -848 248" "light" "150" } { "light" "150" "origin" "1504 -896 248" "classname" "light" } { "classname" "light" "origin" "1304 -1048 24" "light" "225" } { "classname" "light" "origin" "1520 -872 -192" "light" "150" } { "light" "100" "origin" "1384 -776 -184" "classname" "light" } { "classname" "light" "origin" "1368 -912 -184" "light" "100" } { "classname" "light" "origin" "1584 496 148" "light" "200" } { "light" "200" "origin" "1488 496 148" "classname" "light" } { "classname" "light" "origin" "1688 164 148" "light" "200" } { "light" "200" "origin" "1352 496 148" "classname" "light" } { "classname" "light" "origin" "1608 496 -36" "light" "200" } { "light" "200" "origin" "1456 496 -36" "classname" "light" } { "classname" "light" "origin" "1692 600 -12" "light" "200" } { "light" "200" "origin" "1274 618 -64" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1274 378 -64" "light" "200" } { "classname" "light" "origin" "1256 496 -40" "light" "200" } { "spawnflags" "2056" "wait" "-1" "classname" "func_door" "angle" "270" "model" "*1" } { "wait" "-1" "spawnflags" "2056" "sounds" "3" "angle" "90" "classname" "func_door" "model" "*2" } { "light" "200" "origin" "1968 1792 -257" "classname" "light" } { "light" "250" "origin" "1880 1792 -105" "classname" "light" } { "classname" "light" "origin" "1976 1944 56" "light" "150" } { "light" "150" "origin" "1992 1624 64" "classname" "light" } { "classname" "light" "origin" "1944 1736 64" "light" "150" } { "light" "150" "origin" "1944 1832 64" "classname" "light" } { "classname" "light" "origin" "1128 496 -24" "light" "250" } { "light" "150" "origin" "1120 632 -24" "classname" "light" } { "light" "200" "origin" "928 544 -24" "classname" "light" } { "classname" "light" "origin" "640 664 -8" "light" "200" } { "light" "200" "origin" "848 672 -8" "classname" "light" } { "classname" "light" "origin" "1024 544 -188" "light" "175" } { "light" "250" "origin" "64 192 136" "classname" "light" } { "classname" "light" "origin" "528 184 136" "light" "250" } { "light" "200" "origin" "72 408 8" "classname" "light" } { "classname" "light" "origin" "80 -48 8" "light" "200" } { "light" "250" "origin" "400 384 80" "classname" "light" } { "classname" "light" "origin" "392 -16 80" "light" "250" } { "classname" "light" "origin" "312 184 -80" "light" "200" } { "light" "200" "origin" "440 184 -80" "classname" "light" } { "classname" "light" "origin" "504 368 -120" "light" "250" } { "light" "150" "origin" "632 192 -120" "classname" "light" } { "classname" "light" "origin" "504 -16 -120" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "774 446 -172" "light" "250" } { "origin" "774 -70 -172" "classname" "light_torch_small_walltorch" "light" "250" } { "light" "250" "origin" "896 -128 152" "classname" "light" } { "classname" "light" "origin" "896 184 152" "light" "250" } { "light" "150" "origin" "656 184 216" "classname" "light" } { "classname" "light" "origin" "304 368 -152" "light" "200" } { "light" "200" "origin" "0 480 -168" "classname" "light" } { "classname" "light" "origin" "96 376 -168" "light" "200" } { "classname" "light" "origin" "16 1480 -96" "light" "200" } { "light" "200" "origin" "1280 1824 -120" "classname" "light" } { "light" "200" "origin" "504 1816 -120" "classname" "light" } { "classname" "light" "origin" "712 1808 -120" "light" "200" } { "light" "200" "origin" "1064 1808 -120" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "858 1950 -172" "light" "250" } { "origin" "658 1950 -172" "classname" "light_torch_small_walltorch" "light" "250" } { "classname" "light_torch_small_walltorch" "origin" "666 1682 -172" "light" "250" } { "origin" "858 1682 -172" "classname" "light_torch_small_walltorch" "light" "250" } { "classname" "light" "origin" "1248 1384 -32" "light" "200" } { "classname" "light" "origin" "1688 936 -136" "light" "200" } { "light" "250" "origin" "1856 1444 -52" "classname" "light" } { "light" "150" "origin" "1864 1316 -192" "classname" "light" } { "classname" "light" "origin" "1776 1212 -192" "light" "150" } { "light" "150" "origin" "1696 1076 -192" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "1770 730 -64" "light" "250" } { "classname" "light" "origin" "1760 1720 -201" "light" "250" } { "classname" "light" "origin" "1632 1520 -201" "light" "200" } { "classname" "light" "origin" "1984 1504 -201" "light" "200" } { "light" "250" "classname" "light_torch_small_walltorch" "origin" "1874 2104 -300" } { "light" "250" "origin" "1712 2104 -300" "classname" "light_torch_small_walltorch" } { "light" "200" "classname" "light" "origin" "1792 2048 48" } { "classname" "light_flame_large_yellow" "origin" "1362 1778 0" } { "classname" "light" "origin" "1408 1776 -124" "light" "200" } { "classname" "light" "origin" "1520 1880 -84" "light" "175" } { "light" "175" "origin" "1416 1512 -84" "classname" "light" } { "classname" "light" "origin" "1376 1568 -164" "light" "150" } { "light" "150" "origin" "1416 1888 -164" "classname" "light" } { "classname" "light" "origin" "1544 2072 -164" "light" "150" } { "classname" "light" "origin" "1552 1968 36" "light" "250" } { "classname" "light" "origin" "1416 1968 -16" "light" "175" } { "light" "175" "origin" "1416 2176 -16" "classname" "light" } { "classname" "light" "origin" "1240 2176 -16" "light" "175" } { "light" "175" "origin" "1240 2000 -16" "classname" "light" } { "classname" "light" "origin" "1264 1576 -72" "light" "200" } { "light" "200" "origin" "992 1480 -40" "classname" "light" } { "light" "200" "classname" "light_torch_small_walltorch" "origin" "968 1632 -132" } { "light" "200" "origin" "968 1328 -132" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1474 2234 -133" "light" "200" } { "origin" "1182 2234 -133" "classname" "light_torch_small_walltorch" "light" "200" } { "classname" "light" "origin" "1936 1480 48" "light" "150" } { "light" "150" "origin" "1544 1528 64" "classname" "light" } { "classname" "light" "origin" "1472 1488 24" "light" "150" } { "classname" "light" "origin" "1400 1664 96" "light" "150" } { "light" "200" "origin" "1792 2176 -221" "classname" "light" } { "classname" "light" "origin" "1880 2288 -221" "light" "200" } { "light" "200" "origin" "2048 2288 -221" "classname" "light" } { "classname" "light" "origin" "2128 2208 -221" "light" "200" } { "light" "200" "origin" "2160 1992 -205" "classname" "light" } { "origin" "2288 1952 -29" "classname" "light" } { "light" "250" "origin" "2274 1738 -172" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2274 1682 -172" "light" "250" } { "light" "200" "origin" "2376 2184 -152" "classname" "light" } { "light" "200" "origin" "2618 1658 -169" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2618 1368 -169" "light" "200" } { "light" "200" "origin" "2176 1488 -169" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "2298 626 24" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1930 738 24" "light" "200" } { "light" "200" "origin" "2050 394 24" "classname" "light_torch_small_walltorch" } { "classname" "func_plat" "model" "*3" } { "light" "150" "origin" "2152 1784 -312" "classname" "light" } { "classname" "light" "origin" "2232 936 -4" "light" "200" } { "classname" "light" "origin" "2232 1040 48" } { "classname" "light_torch_small_walltorch" "origin" "2034 1034 -164" "light" "200" } { "classname" "light" "origin" "2304 1040 280" "light" "200" } { "light" "200" "origin" "2168 1040 280" "classname" "light" } { "origin" "2130 2452 -112" "classname" "light_flame_large_yellow" "light" "250" } { "classname" "light_flame_large_yellow" "origin" "1858 2452 -112" "light" "250" } { "classname" "light" "origin" "2132 2416 -188" "light" "150" } { "light" "150" "origin" "1860 2416 -188" "classname" "light" } { "light" "200" "origin" "2256 1968 -453" "classname" "light" } { "classname" "light" "origin" "2256 2184 -453" "light" "200" } { "light" "200" "origin" "2216 2384 -453" "classname" "light" } { "classname" "light" "origin" "1792 2400 -453" "light" "200" } { "light" "175" "origin" "1984 2400 -453" "classname" "light" } { "light" "150" "origin" "2168 1608 -9" "classname" "light" } { "classname" "light" "origin" "2368 1600 -9" "light" "150" } { "light" "150" "origin" "2240 1424 44" "classname" "light" } { "classname" "light" "origin" "2400 1424 44" "light" "150" } { "light" "150" "origin" "2560 1424 44" "classname" "light" } { "classname" "light" "origin" "2560 1560 44" "light" "175" } { "light" "150" "origin" "2232 1288 44" "classname" "light" } { "light" "175" "origin" "2384 1424 -160" "classname" "light" } { "classname" "light" "origin" "2232 1288 -160" "light" "175" } { "light" "150" "origin" "2164 932 -172" "classname" "light" } { "classname" "light" "origin" "2308 932 -172" "light" "150" } { "light" "150" "origin" "2232 776 24" "classname" "light" } { "classname" "light" "origin" "2192 664 24" "light" "150" } { "light" "150" "origin" "2016 696 24" "classname" "light" } { "classname" "light" "origin" "1912 496 24" "light" "150" } { "light" "175" "origin" "80 1616 -120" "classname" "light" } { "classname" "light" "origin" "72 1888 -120" "light" "175" } { "light" "175" "origin" "296 1616 -120" "classname" "light" } { "light" "175" "origin" "304 1888 -120" "classname" "light" } //{ //"targetname" "t20" //"angle" "90" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t21" //"angle" "120" //"classname" "trap_spikeshooter" //"origin" "192 1752 -208" //"spawnflags" "1" //} //{ //"targetname" "t22" //"angle" "150" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t19" //"angle" "60" //"classname" "trap_spikeshooter" //"origin" "192 1752 -208" //"spawnflags" "1" //} //{ //"targetname" "t18" //"angle" "30" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t17" //"angle" "0" //"classname" "trap_spikeshooter" //"origin" "192 1752 -208" //"spawnflags" "1" //} //{ //"targetname" "t24" //"angle" "210" //"classname" "trap_spikeshooter" //"origin" "192 1752 -208" //"spawnflags" "1" //} //{ //"targetname" "t23" //"angle" "180" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t25" //"angle" "240" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t26" //"angle" "270" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t27" //"angle" "300" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} //{ //"targetname" "t28" //"angle" "330" //"spawnflags" "1" //"origin" "192 1752 -208" //"classname" "trap_spikeshooter" //} { "delay" ".1" "targetname" "t29" "target" "t17" "classname" "trigger_multiple" "model" "*4" } { "delay" ".1" "targetname" "t17" "target" "t18" "classname" "trigger_multiple" "model" "*5" } { "delay" ".1" "targetname" "t18" "target" "t19" "classname" "trigger_multiple" "model" "*6" } { "delay" ".1" "targetname" "t19" "target" "t20" "classname" "trigger_multiple" "model" "*7" } { "delay" ".1" "targetname" "t20" "target" "t21" "classname" "trigger_multiple" "model" "*8" } { "delay" ".1" "targetname" "t21" "target" "t22" "classname" "trigger_multiple" "model" "*9" } { "delay" ".1" "targetname" "t22" "target" "t23" "classname" "trigger_multiple" "model" "*10" } { "delay" ".1" "targetname" "t23" "target" "t24" "classname" "trigger_multiple" "model" "*11" } { "delay" ".1" "targetname" "t24" "target" "t25" "classname" "trigger_multiple" "model" "*12" } { "delay" ".1" "targetname" "t25" "target" "t26" "classname" "trigger_multiple" "model" "*13" } { "delay" ".1" "targetname" "t26" "target" "t27" "classname" "trigger_multiple" "model" "*14" } { "delay" ".1" "targetname" "t27" "target" "t28" "classname" "trigger_multiple" "model" "*15" } { "target" "t29" "wait" "1.3" "classname" "trigger_multiple" "model" "*16" } { "origin" "192 1750 -188" "classname" "light_flame_large_yellow" } { "light" "125" "origin" "214 1752 -166" "classname" "light" } { "classname" "light" "origin" "192 1774 -166" "light" "125" } { "light" "125" "origin" "170 1750 -166" "classname" "light" } { "classname" "light" "origin" "194 1726 -166" "light" "125" } { "target" "t31" "wait" "-1" "angle" "0" "classname" "func_button" "model" "*17" } { "target" "t31" "angle" "180" "wait" "-1" "classname" "func_button" "model" "*18" } { "target" "t31" "wait" "-1" "angle" "180" "classname" "func_button" "model" "*19" } { "target" "t31" "angle" "90" "wait" "-1" "classname" "func_button" "model" "*20" } { "wait" "-1" "targetname" "t30" "sounds" "4" "speed" "50" "angle" "-1" "classname" "func_door" "model" "*21" } { "count" "4" "targetname" "t31" "target" "t30" "classname" "trigger_counter" "model" "*22" } { "light" "150" "origin" "2424 1080 -176" "classname" "light" } { "classname" "light" "origin" "2424 992 -176" "light" "150" } { "targetname" "t40" "angle" "180" "spawnflags" "1" "origin" "2434 1036 -192" "classname" "trap_spikeshooter" } { "targetname" "t40" "classname" "trap_spikeshooter" "origin" "2434 1036 -192" "spawnflags" "1" "angle" "160" } { "targetname" "t40" "angle" "140" "spawnflags" "1" "origin" "2434 1036 -192" "classname" "trap_spikeshooter" } { "targetname" "t40" "classname" "trap_spikeshooter" "origin" "2434 1036 -192" "spawnflags" "1" "angle" "120" } { "targetname" "t40" "angle" "200" "spawnflags" "1" "origin" "2434 1036 -192" "classname" "trap_spikeshooter" } { "targetname" "t40" "classname" "trap_spikeshooter" "origin" "2434 1036 -192" "spawnflags" "1" "angle" "220" } { "targetname" "t40" "angle" "240" "spawnflags" "1" "origin" "2434 1036 -192" "classname" "trap_spikeshooter" } { "targetname" "t41" "target" "t40" "wait" ".5" "classname" "trigger_multiple" "model" "*23" } { "target" "t41" "classname" "trigger_multiple" "model" "*24" } { "target" "t41" "classname" "trigger_multiple" "model" "*25" } { "target" "t41" "classname" "trigger_multiple" "model" "*26" } { "target" "t41" "classname" "trigger_multiple" "model" "*27" } { "target" "t41" "classname" "trigger_multiple" "model" "*28" } { "target" "t41" "classname" "trigger_multiple" "model" "*29" } { "target" "t41" "classname" "trigger_multiple" "model" "*30" } { "light" "125" "origin" "2196 1200 -204" "classname" "light" } { "classname" "light" "origin" "2284 1200 -204" "light" "125" } { "light" "125" "origin" "2284 1112 -204" "classname" "light" } { "classname" "light" "origin" "2388 1104 -204" "light" "125" } { "light" "125" "origin" "2284 1000 -204" "classname" "light" } { "classname" "light" "origin" "2140 1008 -204" "light" "125" } { "light" "125" "origin" "2132 1096 -204" "classname" "light" } { "classname" "light" "origin" "2132 1160 -204" "light" "125" } { "light" "200" "origin" "528 1816 -392" "classname" "light" } { "classname" "light" "origin" "736 1808 -392" "light" "200" } { "light" "200" "origin" "1040 1808 -392" "classname" "light" } { "classname" "light" "origin" "744 1424 -392" "light" "200" } { "light" "200" "origin" "752 1288 -416" "classname" "light" } { "light" "200" "origin" "760 1064 -376" "classname" "light" } { "classname" "func_train" "spawnflags" "33" "targetname" "t42" "dmg" "1000" "sounds" "1" "target" "t124" "speed" "250" "model" "*31" } { "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t43" "speed" "50" "sounds" "3" "model" "*32" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t42" "sounds" "1" "model" "*33" } { "classname" "trigger_once" "target" "t43" "targetname" "t42" "delay" "2" "model" "*34" } { "classname" "light" "origin" "1936 1784 -288" "light" "125" } { "classname" "monster_ogre" "origin" "1976 1784 -328" "angle" "180" } { "classname" "func_door" "angle" "90" "wait" "-1" "sounds" "1" "model" "*35" } { "classname" "func_door" "angle" "270" "targetname" "t44" "wait" "-1" "model" "*36" } { "classname" "light" "origin" "64 264 8" "light" "125" } { "light" "125" "origin" "64 120 8" "classname" "light" } { "classname" "light" "origin" "64 192 8" "light" "100" } { "classname" "trigger_once" "target" "t44" "model" "*37" } { "classname" "light" "origin" "512 184 -8" "light" "175" } { "targetname" "t119" "classname" "func_door" "angle" "90" "wait" "-1" "speed" "40" "model" "*38" } { "targetname" "t119" "classname" "func_door" "wait" "-1" "angle" "270" "speed" "40" "sounds" "4" "model" "*39" } { "targetname" "t119" "classname" "func_door" "wait" "-1" "angle" "-1" "speed" "30" "message" "Go for a swim first..." "sounds" "3" "model" "*40" } { "classname" "func_button" "angle" "0" "wait" "-1" "target" "t45" "model" "*41" } { "classname" "light" "origin" "36 184 84" "light" "75" } { "classname" "light" "origin" "752 184 -192" "light" "150" } { "classname" "light" "origin" "544 536 -152" "light" "125" } { "classname" "func_door" "angle" "-2" "sounds" "1" "wait" "-1" "targetname" "t45" "model" "*42" } { "wait" "-1" "sounds" "1" "angle" "-2" "classname" "func_door" "targetname" "t45" "model" "*43" } { "light" "125" "origin" "544 -152 -152" "classname" "light" } { "classname" "item_artifact_envirosuit" "origin" "1024 492 -232" } { "classname" "item_armor1" "origin" "2128 1752 -352" } { "classname" "light_flame_small_yellow" "origin" "1024 368 -4" "light" "250" } { "classname" "light" "origin" "1024 400 -64" "light" "150" } { "wait" "5" "sounds" "1" "classname" "func_door" "angle" "-2" "spawnflags" "1" "targetname" "t51" "model" "*44" } { "wait" "5" "sounds" "1" "classname" "func_door" "angle" "-2" "spawnflags" "1" "targetname" "t51" "model" "*45" } { "sounds" "3" "classname" "func_button" "angle" "270" "wait" "3" "target" "t51" "model" "*46" } { "classname" "light" "origin" "1224 712 -216" "light" "100" } { "classname" "light" "origin" "1232 768 -192" "light" "100" } { "light" "75" "origin" "1168 760 -232" "classname" "light" } { "light" "100" "origin" "1232 800 -208" "classname" "light" } { "sounds" "1" "origin" "1860 472 -8" "classname" "item_key2" "spawnflags" "2048" } { "classname" "light" "origin" "1112 1568 -40" "light" "200" } { "light" "150" "origin" "-96 1440 -160" "classname" "light" } { "classname" "light" "origin" "384 1440 -160" "light" "150" } { "light" "200" "origin" "248 1408 -96" "classname" "light" } { "light" "150" "origin" "968 1480 -128" "classname" "light" } { "light" "150" "origin" "1008 -592 -32" "classname" "light" } { "classname" "light" "origin" "1264 -592 -32" "light" "150" } { "light" "200" "origin" "880 -840 -56" "classname" "light" } { "classname" "light" "origin" "1376 -856 -56" "light" "200" } { "light" "175" "origin" "264 184 -8" "classname" "light" } { "light" "175" "origin" "1464 -864 -208" "classname" "light" } { "light" "175" "origin" "1816 160 -56" "classname" "light" } { "classname" "light" "origin" "1560 160 -56" "light" "175" } { "light" "175" "origin" "1544 1632 104" "classname" "light" } { "classname" "light" "origin" "1792 1624 128" "light" "175" } { "classname" "item_health" "origin" "1068 -980 -104" } { "spawnflags" "1" "classname" "item_shells" "origin" "1344 -1160 -96" } { "classname" "monster_ogre" "origin" "1008 -128 40" "angle" "315" "targetname" "t59" "spawnflags" "1" } { "classname" "trigger_once" "target" "t59" "model" "*47" } { "classname" "monster_ogre" "origin" "896 96 56" "angle" "270" "target" "t60" "spawnflags" "1" } { "classname" "path_corner" "origin" "896 208 40" "target" "t60" "targetname" "t61" } { "origin" "896 -16 40" "classname" "path_corner" "targetname" "t60" "target" "t61" } { "classname" "path_corner" "origin" "168 392 -56" "target" "t62" "targetname" "t63" } { "origin" "168 -16 -56" "classname" "path_corner" "targetname" "t62" "target" "t63" } { "classname" "path_corner" "origin" "88 344 -56" "targetname" "t64" "target" "t65" "spawnflags" "256" } { "origin" "88 72 -56" "classname" "path_corner" "target" "t64" "targetname" "t65" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "88 224 -40" "angle" "90" "target" "t64" "spawnflags" "257" } { "classname" "monster_hell_knight" "origin" "168 232 -40" "angle" "270" "target" "t62" "spawnflags" "1" } { "classname" "monster_zombie" "origin" "544 -120 -208" "angle" "90" "targetname" "t45" } { "classname" "monster_zombie" "origin" "544 496 -208" "angle" "270" "targetname" "t45" } { "classname" "monster_wizard" "origin" "664 428 216" "angle" "225" "spawnflags" "1" } { "angle" "135" "origin" "664 -56 216" "classname" "monster_wizard" "spawnflags" "257" } { "classname" "light" "origin" "1736 88 -40" "light" "100" } { "classname" "monster_ogre" "origin" "904 -120 56" "angle" "0" "targetname" "t66" "spawnflags" "1281" } { "classname" "trigger_once" "target" "t66" "spawnflags" "256" "model" "*48" } { "classname" "item_health" "origin" "1168 -408 -80" "spawnflags" "1" } { "classname" "item_health" "origin" "1168 -104 -16" } { "classname" "item_spikes" "origin" "928 216 32" } { "classname" "item_rockets" "origin" "632 -48 32" } { "classname" "item_health" "origin" "32 392 -64" } { "light" "200" "origin" "1688 288 148" "classname" "light" } { "classname" "light" "origin" "1688 464 148" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "1814 622 -64" "light" "250" } { "classname" "light" "origin" "1768 344 -72" "light" "200" } { "classname" "trigger_monsterjump" "angle" "0" "model" "*49" } { "targetname" "t100" "classname" "monster_ogre" "origin" "1504 272 24" "angle" "0" "spawnflags" "256" } { "targetname" "t68" "target" "t67" "origin" "1352 576 -120" "classname" "path_corner" "spawnflags" "256" } { "target" "t68" "targetname" "t67" "classname" "path_corner" "origin" "1352 416 -120" "spawnflags" "256" } { "target" "t68" "angle" "90" "origin" "1360 480 -104" "classname" "monster_demon1" "spawnflags" "257" } { "targetname" "t70" "target" "t69" "origin" "1472 496 -120" "classname" "path_corner" } { "target" "t70" "targetname" "t69" "classname" "path_corner" "origin" "1688 496 -120" } { "target" "t69" "angle" "270" "origin" "1648 544 -104" "classname" "monster_ogre" "spawnflags" "1" } { "target" "t71" "targetname" "t72" "origin" "1984 688 -24" "classname" "path_corner" "spawnflags" "256" } { "target" "t72" "targetname" "t71" "classname" "path_corner" "origin" "1984 448 -24" "spawnflags" "256" } { "target" "t71" "angle" "270" "origin" "1992 536 -8" "classname" "monster_ogre" "spawnflags" "257" } { "target" "t74" "targetname" "t73" "origin" "2120 680 -24" "classname" "path_corner" } { "targetname" "t74" "target" "t73" "classname" "path_corner" "origin" "2240 680 -24" } { "target" "t74" "angle" "225" "origin" "2256 736 -8" "classname" "monster_ogre" "spawnflags" "1" } { "targetname" "t78" "angle" "90" "origin" "2232 1312 -8" "classname" "monster_ogre" "spawnflags" "256" } { "target" "t76" "angle" "90" "origin" "2232 1008 -200" "classname" "monster_hell_knight" "spawnflags" "1" } { "targetname" "t76" "target" "t75" "origin" "2120 968 -216" "classname" "path_corner" } { "target" "t76" "targetname" "t75" "classname" "path_corner" "origin" "2336 968 -216" } { "classname" "light" "origin" "2384 2400 -152" "light" "200" } { "targetname" "t77" "wait" "-1" "sounds" "1" "speed" "300" "angle" "-2" "classname" "func_door" "model" "*50" } { "targetname" "t77" "angle" "180" "origin" "2512 2312 -200" "classname" "monster_demon1" "spawnflags" "256" } { "targetname" "t77" "classname" "monster_demon1" "origin" "2512 2160 -200" "angle" "180" } { "classname" "item_health" "origin" "2504 2200 -224" } { "light" "150" "origin" "2536 2312 -128" "classname" "light" } { "classname" "light" "origin" "2536 2160 -128" "light" "150" } { "target" "t77" "classname" "trigger_once" "model" "*51" } { "spawnflags" "2" "origin" "2368 2336 -224" "classname" "item_health" } { "spawnflags" "1" "origin" "2504 2240 -224" "classname" "item_spikes" } { "origin" "2408 2072 -224" "classname" "item_shells" } { "target" "t78" "classname" "trigger_once" "model" "*52" } { "targetname" "t78" "angle" "90" "origin" "2240 1272 -200" "classname" "monster_demon1" } { "light" "150" "origin" "1120 1384 -40" "classname" "light" } { "light" "200" "origin" "1200 1248 -104" "classname" "light" } { "light" "250" "origin" "1288 1032 -4" "classname" "light_flame_small_yellow" } { "light" "150" "origin" "1256 1032 -64" "classname" "light" } { "classname" "light_flame_small_yellow" "origin" "568 1032 -4" "light" "250" } { "classname" "light" "origin" "600 1032 -64" "light" "150" } { "light" "250" "origin" "888 1272 -4" "classname" "light_flame_small_yellow" } { "light" "150" "origin" "888 1240 -64" "classname" "light" } { "light" "200" "origin" "608 1232 -108" "classname" "light" } { "target" "t79" "wait" "-1" "angle" "180" "classname" "func_button" "model" "*53" } { "targetname" "t79" "message" "This door is opened near by..." "sounds" "3" "speed" "35" "angle" "-1" "wait" "-1" "classname" "func_door" "model" "*54" } { "light" "100" "origin" "580 1208 -148" "classname" "light" } { "light" "200" "origin" "1224 736 -8" "classname" "light" } { "target" "t80" "classname" "trigger_once" "model" "*55" } { "targetname" "t80" "angle" "315" "origin" "640 1088 128" "classname" "monster_wizard" } { "targetname" "t80" "classname" "monster_wizard" "origin" "616 720 128" "angle" "0" } { "targetname" "t80" "angle" "180" "origin" "1280 680 128" "classname" "monster_wizard" "spawnflags" "256" } { "target" "t82" "origin" "1248 1080 24" "classname" "monster_wizard" "spawnflags" "1" } { "targetname" "t82" "target" "t81" "origin" "1168 1064 8" "classname" "path_corner" } { "target" "t82" "targetname" "t81" "classname" "path_corner" "origin" "720 1064 8" } { "targetname" "t80" "classname" "monster_wizard" "origin" "584 1112 128" "angle" "315" "spawnflags" "256" } { "origin" "1256 944 -184" "classname" "item_health" } { "spawnflags" "1" "origin" "1116 584 -256" "classname" "item_spikes" } { "targetname" "t79" "angle" "315" "origin" "1000 1464 -168" "classname" "monster_ogre" } { "target" "t85" "targetname" "t86" "origin" "1456 1824 -192" "classname" "path_corner" "spawnflags" "256" } { "target" "t86" "targetname" "t85" "classname" "path_corner" "origin" "1456 1560 -192" "spawnflags" "256" } { "target" "t85" "angle" "270" "origin" "1456 1664 -176" "classname" "monster_ogre" "spawnflags" "256" } { "targetname" "t91" "angle" "270" "origin" "1560 1944 -320" "classname" "monster_zombie" "spawnflags" "256" } { "targetname" "t91" "classname" "monster_zombie" "origin" "1600 1912 -320" "angle" "270" } { "angle" "225" "origin" "1960 1984 -320" "classname" "monster_zombie" } { "targetname" "t91" "classname" "monster_zombie" "origin" "1904 1928 -320" "angle" "225" } { "targetname" "t91" "angle" "270" "origin" "1624 1768 -320" "classname" "monster_zombie" } { "target" "t87" "classname" "monster_zombie" "origin" "1696 1912 -320" "angle" "0" } { "target" "t89" "angle" "270" "origin" "1704 1800 -320" "classname" "monster_zombie" } { "target" "t87" "targetname" "t88" "origin" "1648 1912 -336" "classname" "path_corner" } { "target" "t88" "targetname" "t87" "classname" "path_corner" "origin" "1848 1904 -336" } { "targetname" "t90" "target" "t89" "origin" "1648 1824 -336" "classname" "path_corner" } { "target" "t90" "targetname" "t89" "classname" "path_corner" "origin" "1768 1752 -336" } { "target" "t91" "classname" "trigger_once" "model" "*56" } { "spawnflags" "1" "origin" "1496 1808 -200" "classname" "item_health" } { "spawnflags" "1" "origin" "1184 2176 -192" "classname" "item_health" } { "classname" "item_health" "origin" "1184 2128 -192" "spawnflags" "1" } { "spawnflags" "1" "origin" "1264 1680 -192" "classname" "item_health" } { "target" "t92" "targetname" "t93" "origin" "2376 2304 -216" "classname" "path_corner" } { "target" "t93" "targetname" "t92" "classname" "path_corner" "origin" "2376 1984 -216" } { "target" "t95" "targetname" "t94" "origin" "2144 1608 -216" "classname" "path_corner" } { "target" "t94" "targetname" "t95" "classname" "path_corner" "origin" "2376 1608 -216" } { "target" "t92" "angle" "270" "origin" "2376 2176 -200" "classname" "monster_hell_knight" "spawnflags" "1" } { "angle" "135" "origin" "2416 1760 -200" "classname" "monster_hell_knight" "spawnflags" "257" } { "target" "t94" "angle" "180" "origin" "2320 1608 -200" "classname" "monster_hell_knight" "spawnflags" "1" } { "angle" "90" "origin" "2152 1840 -200" "classname" "monster_ogre" "spawnflags" "257" } { "target" "t97" "targetname" "t96" "origin" "2096 2376 -216" "classname" "path_corner" "spawnflags" "256" } { "target" "t96" "targetname" "t97" "classname" "path_corner" "origin" "2232 2208 -216" "spawnflags" "256" } { "target" "t96" "angle" "135" "origin" "2200 2264 -200" "classname" "monster_wizard" "spawnflags" "257" } { "origin" "2104 1544 -224" "classname" "item_shells" } { "origin" "2176 1240 -32" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "2256 1240 -32" } { "origin" "1928 584 -32" "classname" "item_shells" } { "spawnflags" "1" "origin" "2040 1072 -32" "classname" "item_health" } { "classname" "item_health" "origin" "2040 1024 -32" "spawnflags" "1" } { "angle" "225" "origin" "2352 1160 -200" "classname" "monster_hell_knight" "spawnflags" "256" } { "angle" "180" "origin" "1864 1192 -216" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1776 1192 -216" "angle" "180" } { "target" "t99" "targetname" "t98" "origin" "1688 1192 -232" "classname" "path_corner" } { "target" "t98" "targetname" "t99" "classname" "path_corner" "origin" "1688 1048 -232" } { "target" "t98" "angle" "90" "origin" "1688 1112 -216" "classname" "monster_zombie" } { "origin" "536 416 32" "classname" "item_shells" } { "target" "t100" "classname" "trigger_once" "spawnflags" "256" "model" "*57" } { "origin" "1784 408 -128" "classname" "item_health" } { "classname" "item_health" "origin" "1784 448 -128" } { "origin" "1736 728 -128" "classname" "item_rockets" } { "target" "t101" "sounds" "1" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*58" } { "light" "250" "origin" "1418 234 52" "classname" "light_torch_small_walltorch" } { "targetname" "t101" "classname" "trigger_secret" "model" "*59" } { "targetname" "t102" "angle" "180" "classname" "trigger_monsterjump" "model" "*60" } { "target" "t102" "killtarget" "t102" "classname" "trigger_once" "model" "*61" } { "origin" "1568 1968 -352" "classname" "item_health" } { "classname" "item_health" "origin" "1608 1968 -352" } { "origin" "2112 1776 -352" "classname" "item_shells" "spawnflags" "2048" } { "origin" "1920 2232 -352" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "2008 2232 -352" } { "classname" "item_shells" "origin" "2176 1440 -224" } { "target" "t66" "classname" "trigger_once" "model" "*62" } { "origin" "1744 0 -128" "classname" "item_spikes" "spawnflags" "1" } { "target" "t103" "targetname" "t104" "origin" "-56 1432 -224" "classname" "path_corner" "spawnflags" "256" } { "target" "t104" "targetname" "t103" "classname" "path_corner" "origin" "312 1432 -224" "spawnflags" "256" } { "target" "t103" "origin" "40 1440 -208" "classname" "monster_ogre" "spawnflags" "257" } { "angle" "45" "origin" "56 1616 -208" "classname" "monster_hell_knight" "spawnflags" "1" } { "target" "t105" "targetname" "t106" "origin" "520 1816 -232" "classname" "path_corner" } { "target" "t106" "targetname" "t105" "classname" "path_corner" "origin" "920 1816 -232" } { "target" "t105" "origin" "624 1800 -216" "classname" "monster_hell_knight" "spawnflags" "1" } { "angle" "0" "origin" "480 1824 64" "classname" "monster_wizard" "spawnflags" "257" } { "targetname" "t107" "classname" "monster_wizard" "origin" "656 1816 64" "angle" "0" "spawnflags" "1" } { "targetname" "t107" "angle" "0" "origin" "840 1816 64" "classname" "monster_wizard" "spawnflags" "257" } { "target" "t107" "classname" "trigger_once" "model" "*63" } { "origin" "1440 2200 -192" "classname" "item_shells" } { "classname" "item_shells" "origin" "1440 2160 -192" } { "spawnflags" "1" "origin" "1184 1976 -192" "classname" "item_spikes" } { "target" "t109" "targetname" "t108" "origin" "1240 2000 -184" "classname" "path_corner" } { "target" "t108" "targetname" "t109" "classname" "path_corner" "origin" "1240 1760 -184" } { "target" "t108" "angle" "90" "origin" "1240 1904 -168" "classname" "monster_ogre" "spawnflags" "1" } { "target" "t110" "classname" "trigger_once" "spawnflags" "256" "model" "*64" } { "targetname" "t110" "angle" "45" "origin" "1216 2088 -168" "classname" "monster_ogre" "spawnflags" "1281" } { "classname" "item_health" "origin" "1496 1768 -200" } { "target" "t111" "classname" "trigger_once" "model" "*65" } { "targetname" "t111" "angle" "315" "origin" "764 -60 -208" "classname" "monster_zombie" } { "targetname" "t111" "angle" "45" "origin" "764 436 -208" "classname" "monster_zombie" } { "targetname" "t111" "angle" "225" "origin" "284 -56 -208" "classname" "monster_zombie" "spawnflags" "256" } { "targetname" "t119" "wait" "-1" "speed" "40" "angle" "90" "classname" "func_door" "model" "*66" } { "origin" "1280 592 -128" "classname" "item_shells" } { "classname" "item_shells" "origin" "576 416 32" } { "classname" "item_spikes" "origin" "904 504 -128" "spawnflags" "1" } { "origin" "904 464 -128" "classname" "item_spikes" "spawnflags" "1" } { "classname" "item_health" "origin" "1024 912 -152" "spawnflags" "1" } { "classname" "item_spikes" "origin" "720 848 -184" "spawnflags" "1" } { "classname" "path_corner" "origin" "1224 1192 -176" "targetname" "t112" "target" "t113" } { "origin" "1216 896 -176" "classname" "path_corner" "targetname" "t113" "target" "t112" } { "classname" "monster_ogre" "origin" "1224 992 -160" "angle" "90" "target" "t112" } { "classname" "item_shells" "origin" "968 1600 -184" } { "classname" "item_artifact_super_damage" "origin" "1444 308 -104" } { "classname" "light" "origin" "992 -128 72" "light" "100" } { "classname" "item_shells" "origin" "1672 1008 -240" } { "classname" "item_health" "origin" "2264 1320 -224" } { "classname" "monster_wizard" "origin" "2120 1664 -72" "angle" "315" "spawnflags" "1" } { "classname" "item_health" "origin" "2016 392 -32" } { "classname" "monster_hell_knight" "origin" "360 1744 -208" "angle" "90" "targetname" "t114" "spawnflags" "257" } { "classname" "trigger_once" "target" "t114" "spawnflags" "256" "model" "*67" } { "classname" "item_health" "origin" "352 1464 -232" } { "spawnflags" "1" "origin" "352 1392 -232" "classname" "item_health" } { "classname" "item_armorInv" "origin" "744 1424 -448" } { "classname" "item_health" "origin" "-56 320 -232" } { "origin" "-16 320 -232" "classname" "item_health" } { "targetname" "t117" "classname" "trigger_teleport" "target" "t115" "spawnflags" "2" "model" "*68" } { "delay" ".5" "targetname" "t117" "classname" "trigger_teleport" "target" "t116" "spawnflags" "2" "model" "*69" } { "classname" "monster_wizard" "origin" "2928 1816 -152" "angle" "180" "targetname" "t117" } { "angle" "180" "origin" "2928 1768 -152" "classname" "monster_wizard" "targetname" "t117" } { "classname" "info_teleport_destination" "origin" "1824 1920 -184" "angle" "225" "targetname" "t115" } { "classname" "info_teleport_destination" "origin" "1880 1544 -184" "angle" "180" "targetname" "t116" } { "classname" "trigger_once" "target" "t117" "model" "*70" } { "classname" "monster_zombie" "origin" "764 388 -208" "angle" "0" "targetname" "t111" } { "angle" "0" "origin" "764 -12 -208" "classname" "monster_zombie" "targetname" "t111" } { "classname" "monster_zombie" "origin" "408 -56 -208" "angle" "270" "targetname" "t111" } { "classname" "light" "origin" "1200 672 -240" "light" "125" } { "classname" "item_spikes" "origin" "72 392 -64" "spawnflags" "1" } { "classname" "item_spikes" "origin" "2368 920 -224" } { "origin" "2032 976 -224" "classname" "item_spikes" } { "classname" "light" "origin" "1416 2096 -112" "light" "150" } { "light" "150" "origin" "1240 2096 -112" "classname" "light" } { "classname" "item_spikes" "origin" "464 1824 -240" } { "origin" "504 1824 -240" "classname" "item_spikes" } { "classname" "item_shells" "origin" "-96 1472 -232" "spawnflags" "1" } { "classname" "item_health" "origin" "528 -172 -232" } { "classname" "item_health" "origin" "40 -64 -64" } { "light" "225" "classname" "light_torch_small_walltorch" "origin" "122 -86 -8" } { "origin" "134 462 -8" "classname" "light_torch_small_walltorch" "light" "225" } { "light" "250" "origin" "678 446 92" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "678 -70 92" "light" "250" } { "light" "150" "origin" "120 -56 -16" "classname" "light" } { "classname" "light" "origin" "136 424 -16" "light" "150" } { "light" "150" "origin" "600 184 296" "classname" "light" } { "classname" "light" "origin" "152 184 296" "light" "150" } { "light" "150" "origin" "368 376 296" "classname" "light" } { "classname" "light" "origin" "368 0 296" "light" "150" } { "light" "150" "origin" "352 192 232" "classname" "light" } { "light" "200" "origin" "64 408 168" "classname" "light" } { "classname" "light" "origin" "56 -48 168" "light" "200" } { "light" "125" "origin" "1520 1880 24" "classname" "light" } { "origin" "272 272 -232" "classname" "item_rockets" } { "targetname" "t45" "classname" "func_door" "angle" "-2" "sounds" "1" "wait" "-1" "model" "*71" } { "classname" "light" "origin" "416 -152 -152" "light" "125" } { "targetname" "t45" "angle" "90" "origin" "416 -120 -208" "classname" "monster_zombie" "spawnflags" "256" } { "origin" "400 524 -232" "classname" "item_health" } { "light" "125" "origin" "416 536 -152" "classname" "light" } { "targetname" "t45" "wait" "-1" "sounds" "1" "angle" "-2" "classname" "func_door" "model" "*72" } { "targetname" "t45" "angle" "270" "origin" "416 496 -208" "classname" "monster_zombie" "spawnflags" "256" } { "target" "t120" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*73" } { "target" "t120" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*74" } { "targetname" "t120" "target" "t119" "classname" "trigger_counter" "model" "*75" } { "light" "125" "origin" "1792 840 -112" "classname" "light" } { "classname" "light" "origin" "1584 840 -112" "light" "125" } { "light" "125" "origin" "1792 2280 -480" "classname" "light" } { "classname" "light" "origin" "1792 2144 -480" "light" "125" } { "origin" "1776 2232 -508" "classname" "item_health" } { "classname" "item_health" "origin" "1776 2192 -508" } { "light" "150" "origin" "1016 1696 -336" "classname" "light" } { "light" "125" "origin" "1080 1696 -280" "classname" "light" } { "light" "125" "origin" "1152 1696 -200" "classname" "light" } { "light" "150" "origin" "1096 1696 -352" "classname" "light" } { "classname" "trigger_secret" "model" "*76" } { "target" "t116" "classname" "trigger_teleport" "model" "*77" } { "spawnflags" "768" "angle" "315" "origin" "1400 1856 -176" "classname" "monster_ogre" } { "target" "t121" "targetname" "t122" "spawnflags" "768" "origin" "1824 2280 -344" "classname" "path_corner" } { "target" "t122" "targetname" "t121" "spawnflags" "768" "classname" "path_corner" "origin" "2080 2280 -344" } { "target" "t121" "spawnflags" "769" "angle" "180" "origin" "2128 2272 -328" "classname" "monster_demon1" } { "spawnflags" "2816" "origin" "1824 2072 -352" "classname" "item_shells" } { "spawnflags" "769" "angle" "90" "origin" "1792 2176 -144" "classname" "monster_wizard" } { "spawnflags" "769" "angle" "180" "origin" "2600 1640 -200" "classname" "monster_hell_knight" } { "spawnflags" "2816" "origin" "2096 1136 -32" "classname" "item_shells" } { "classname" "monster_wizard" "origin" "1872 1432 -72" "angle" "90" "spawnflags" "769" } { "classname" "monster_hell_knight" "origin" "2400 1032 -8" "angle" "180" "spawnflags" "769" } { "classname" "monster_demon1" "origin" "1000 496 -104" "angle" "0" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "1240 2088 -168" "angle" "45" "spawnflags" "769" "targetname" "t110" } { "classname" "monster_hell_knight" "origin" "360 1936 -208" "angle" "270" "spawnflags" "769" "targetname" "t114" } { "classname" "item_shells" "origin" "16 1768 -232" "spawnflags" "2560" } { "spawnflags" "2560" "origin" "344 1576 -232" "classname" "item_shells" } { "classname" "trigger_changelevel" "map" "e2m4" "model" "*78" } { "classname" "light" "origin" "1136 -1144 264" "light" "250" } { "light" "250" "origin" "1264 -552 44" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "1008 -552 44" "light" "250" } { "classname" "monster_demon1" "origin" "888 -120 56" "angle" "0" "spawnflags" "769" "targetname" "t66" } { "classname" "monster_hell_knight" "origin" "616 184 56" "angle" "0" "spawnflags" "768" } { "classname" "item_spikes" "origin" "880 216 32" "spawnflags" "2816" } { "classname" "monster_hell_knight" "origin" "1944 728 -8" "angle" "0" "spawnflags" "769" } { "classname" "light" "origin" "-48 1184 -156" "light" "200" "style" "10" } { "style" "10" "light" "200" "origin" "0 1024 -120" "classname" "light" } { "classname" "light" "origin" "48 800 -120" "light" "200" "style" "10" } { "style" "10" "light" "200" "origin" "0 600 -120" "classname" "light" } { "classname" "monster_hell_knight" "origin" "128 1088 -208" "angle" "225" "spawnflags" "1" } { "angle" "315" "origin" "-104 760 -208" "classname" "monster_hell_knight" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-56 592 -232" } { "classname" "item_health" "origin" "-56 920 -232" } { "classname" "monster_demon1" "origin" "0 544 -208" "angle" "90" "target" "t123" "spawnflags" "769" } { "mangle" "20 315 0" "origin" "1568 2040 -88" "classname" "info_intermission" } { "classname" "item_shells" "origin" "1528 1968 -352" "spawnflags" "3584" } { "origin" "-88 1376 -232" "classname" "item_health" "spawnflags" "3585" } { "classname" "item_artifact_envirosuit" "origin" "1216 1696 -168" "spawnflags" "3584" } { "classname" "monster_demon1" "origin" "144 372 -208" "angle" "180" "spawnflags" "768" "targetname" "t123" } { "classname" "monster_demon1" "origin" "0 528 -208" "angle" "90" "spawnflags" "1025" } { "classname" "info_player_deathmatch" "origin" "1128 -840 -80" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "656 184 -208" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "-24 1440 -208" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "1240 1816 -168" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "1032 1568 -168" "angle" "0" } { "classname" "func_wall" "spawnflags" "1792" "model" "*79" } { "classname" "weapon_lightning" //Q-Man "origin" "1135 -800 -80" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "1424 608 -104" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "2272 680 -8" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "2240 1472 -200" "angle" "270" } { "classname" "weapon_supernailgun" "origin" "2236 1184 -32" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "2424 1824 -200" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "1792 2072 -328" "angle" "270" } { "classname" "weapon_supershotgun" "origin" "1488 1584 -200" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "88 184 -64" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "1224 840 -168" "angle" "90" } { "classname" "weapon_nailgun" "origin" "1024 872 -152" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "136 1760 -232" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "1976 2288 -352" "spawnflags" "1792" } { "classname" "weapon_rocketlauncher" //Q-Man "origin" "2128 1792 -352" "spawnflags" "1792" } { "classname" "item_cells" "origin" "1608 728 -128" "spawnflags" "1792" } { "spawnflags" "1792" "classname" "item_cells" "origin" "72 1032 -232" } { "classname" "item_cells" "origin" "1008 1328 -192" "spawnflags" "1792" } { "classname" "item_cells" "origin" "1304 -1160 -96" "spawnflags" "1792" } { "origin" "2272 1440 -224" "classname" "item_shells" "spawnflags" "2816" } { "origin" "224 1736 -232" "classname" "item_health" } { "classname" "info_intermission" "origin" "1328 -1168 192" "mangle" "20 120 0" } { "classname" "info_intermission" "origin" "1248 680 8" "mangle" "20 130 0" } { "classname" "info_intermission" "origin" "1280 1824 -104" "mangle" "10 180 0" } { "classname" "light" "origin" "-304 888 -80" "light" "150" } { "light" "150" "origin" "-304 712 -80" "classname" "light" } { "classname" "light" "origin" "-224 872 -8" "light" "125" } { "classname" "light" "origin" "-224 728 -8" "light" "125" } { "light" "150" "origin" "-178 706 -156" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "-320 838 -138" "light" "100" } { "light" "100" "origin" "-320 774 -138" "classname" "light" } { "classname" "info_player_coop" "origin" "1192 -1088 -72" "angle" "90" } { "angle" "90" "origin" "1080 -1088 -72" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1008 -1112 -72" "angle" "90" } { "angle" "90" "origin" "1264 -1112 -72" "classname" "info_player_coop" } { "classname" "item_armor1" "origin" "784 1816 -232" } { "classname" "item_spikes" "origin" "-56 1472 -232" "spawnflags" "1" } { "classname" "item_rockets" "origin" "400 -172 -232" } { "classname" "func_wall" "spawnflags" "1792" "model" "*80" } { "spawnflags" "1792" "classname" "func_wall" "model" "*81" } { "classname" "path_corner" "origin" "1954 1770 -96" "targetname" "t124" "target" "t125" } { "classname" "path_corner" "origin" "1954 1770 -320" "targetname" "t125" "target" "t124" } { "classname" "weapon_grenadelauncher" "origin" "1688 720 -128" "spawnflags" "2048" } { "wait" "-1" "angle" "-2" "classname" "func_door" "targetname" "t126" "lip" "-8" "model" "*82" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "2" "model" "*83" } { "classname" "light" "origin" "-224 832 -152" "light" "125" } { "classname" "trigger_counter" "target" "t126" "targetname" "t127" "spawnflags" "1" "count" "7" "model" "*84" } { "classname" "trigger_once" "health" "1" "target" "t127" "model" "*85" } { "health" "1" "classname" "trigger_once" "target" "t127" "model" "*86" } { "classname" "trigger_once" "health" "1" "target" "t127" "model" "*87" } { "health" "1" "classname" "trigger_once" "target" "t127" "model" "*88" } { "classname" "trigger_once" "health" "1" "target" "t127" "model" "*89" } { "health" "1" "classname" "trigger_once" "target" "t127" "model" "*90" } { "classname" "trigger_once" "health" "1" "target" "t127" "model" "*91" } { "classname" "ambient_swamp1" "origin" "1338 -854 -104" } { "classname" "ambient_swamp2" "origin" "938 -854 -104" } { "classname" "ambient_drip" "origin" "1138 -854 -176" } { "classname" "ambient_drip" "origin" "1650 -862 -192" } { "classname" "ambient_drip" "origin" "1674 -438 -192" } { "classname" "ambient_drip" "origin" "1682 2 -48" } { "classname" "ambient_swamp1" "origin" "1674 1986 -280" } { "classname" "ambient_swamp2" "origin" "1826 2378 -280" } { "classname" "ambient_swamp1" "origin" "2258 2058 -280" } { "classname" "ambient_drip" "origin" "746 1370 -376" } { "classname" "ambient_drip" "origin" "762 906 -240" } { "origin" "1034 722 -240" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "554 1818 -352" } { "origin" "1002 1810 -352" "classname" "ambient_drip" } { "speed" "35" "classname" "func_door" "wait" "-1" "angle" "-2" "sounds" "1" "targetname" "t101" "model" "*92" } { "classname" "light" "origin" "1440 296 -80" "light" "125" } { "origin" "1792 792 -240" "classname" "item_spikes" } //Q-Man { "classname" "item_flag_team1" "origin" "784 1816 -232" } { "classname" "info_player_team1" "origin" "500 1818 -216" } { "classname" "info_player_team1" "origin" "600 1818 -216" } { "classname" "info_player_team1" "origin" "700 1818 -216" } { "classname" "info_player_team1" "origin" "800 1818 -216" } { "classname" "info_player_team1" "origin" "900 1818 -216" } { "classname" "item_flag_team2" "origin" "2408 1037 -13" } { "classname" "info_player_team2" "origin" "2066 1037 -13" } { "classname" "info_player_team2" "origin" "2220 1235 -13" "angle" "270" } { "classname" "info_player_team2" "origin" "2344 906 -13" "angle" "135" } { "classname" "info_player_team2" "origin" "2130 891 -13" "angle" "45" } { "classname" "info_player_team2" "origin" "2408 1037 -13" "angle" "180" } { "origin" "2242 1040 -203" "classname" "weapon_supershotgun" } { "origin" "2230 1080 -203" "classname" "item_shells" } { "origin" "184 1440 -232" "classname" "weapon_supernailgun" } { "classname" "item_armor2" "origin" "2105 926 -13" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m1.ent000066400000000000000000001160721475442401000252000ustar00rootroot00000000000000{ "classname" "worldspawn" "worldtype" "2" "sounds" "6" "message" "Termination Central" } { "classname" "info_player_start" "origin" "616 352 72" "angle" "90" } { "classname" "light" "origin" "728 472 168" "light" "264" } { "classname" "light" "origin" "840 616 104" "light" "200" } { "classname" "light" "origin" "864 448 112" "light" "200" } { "classname" "light" "origin" "584 120 56" "light" "200" } { "classname" "light" "origin" "504 120 -176" } { "light" "260" "classname" "light" "origin" "640 480 -96" } { "classname" "light" "origin" "728 360 -104" "light" "164" } { "classname" "light" "origin" "728 536 -104" "light" "164" } { "classname" "light" "origin" "544 864 8" "light" "464" } { "classname" "light" "origin" "696 592 -288" "light" "214" } { "classname" "light" "origin" "504 592 -288" "light" "214" } { "classname" "light" "origin" "464 472 56" "light" "200" } { "classname" "light" "origin" "112 520 80" "light" "200" } { "classname" "light" "origin" "128 368 96" "light" "200" } { "classname" "light" "origin" "352 344 -88" "light" "200" } { "classname" "light" "origin" "352 496 -88" "light" "200" } { "model" "*1" "classname" "func_plat" "angle" "-2" "sounds" "1" } { "classname" "light" "origin" "248 536 -112" "light" "150" } { "classname" "light" "origin" "216 120 56" "light" "200" } { "classname" "light" "origin" "8 -248 56" "light" "350" } { "classname" "light" "origin" "-168 432 152" "light" "150" } { "classname" "light" "origin" "-216 304 152" "light" "244" } { "classname" "light" "origin" "-8 336 152" "light" "200" } { "classname" "light" "origin" "-88 512 152" "light" "150" } { "classname" "light" "origin" "640 312 -288" "light" "214" } { "classname" "light" "origin" "448 312 -288" "light" "214" } { "classname" "light" "origin" "256 312 -288" "light" "214" } { "classname" "light" "origin" "64 264 -288" "light" "214" } { "classname" "light" "origin" "-128 152 -288" "light" "214" } { "classname" "light" "origin" "-152 -32 -288" "light" "214" } { "classname" "light" "origin" "48 480 -112" "light" "200" } { "classname" "light" "origin" "-264 424 8" "light" "150" } { "classname" "light" "origin" "-128 504 8" "light" "150" } { "classname" "light" "origin" "-40 552 -112" "light" "164" } { "classname" "light" "origin" "-304 400 -112" "light" "110" } { "classname" "light" "origin" "-328 -112 -112" "light" "200" } { "classname" "light" "origin" "-328 -16 -112" "light" "200" } { "classname" "light" "origin" "-328 -208 -112" "light" "200" } { "classname" "light" "origin" "-408 -208 -112" "light" "200" } { "classname" "light" "origin" "-408 -112 -112" "light" "200" } { "classname" "light" "origin" "-408 -16 -112" "light" "200" } { "classname" "light" "origin" "-384 184 -112" "light" "264" } { "classname" "light" "origin" "-432 -264 -104" "light" "200" } { "classname" "light" "origin" "-504 -352 -200" "light" "150" } { "classname" "light" "origin" "-632 -416 -200" "light" "200" } { "classname" "light" "origin" "-160 16 136" "target" "t2" } { "classname" "info_null" "origin" "-156 -12 -44" "targetname" "t2" } { "classname" "light" "origin" "-160 48 120" "light" "150" } { "classname" "light" "origin" "-272 -8 120" "light" "264" } { "classname" "light" "origin" "-400 -8 120" "light" "264" } { "classname" "light" "origin" "-488 16 120" "light" "200" } { "classname" "light" "origin" "-272 16 136" "target" "t3" } { "classname" "light" "origin" "-400 16 136" "target" "t4" } { "classname" "info_null" "origin" "-268 36 -44" "targetname" "t3" } { "classname" "info_null" "origin" "-396 36 -44" "targetname" "t4" } { "classname" "light_fluoro" "origin" "-488 208 64" } { "classname" "light" "origin" "-408 -272 24" "light" "200" } { "light" "250" "classname" "light" "origin" "-408 -224 144" } { "classname" "light" "origin" "-248 -120 -8" "light" "200" } { "classname" "light" "origin" "-272 -392 -8" "light" "200" } { "classname" "light" "origin" "-440 -432 -8" "light" "200" } { "classname" "light" "origin" "-472 -128 -8" "light" "200" } { "model" "*2" "classname" "func_plat" "sounds" "1" } { "light" "200" "classname" "light" "origin" "-448 -576 40" } { "classname" "light" "origin" "-296 -416 -184" "light" "100" } { "classname" "light" "origin" "-160 -144 -56" "light" "150" } { "classname" "light" "origin" "-160 -280 -56" "light" "150" } { "classname" "light" "origin" "-160 -472 56" "light" "100" } { "classname" "light" "origin" "-160 -368 -120" "light" "120" } { "classname" "light" "origin" "-160 -352 64" "light" "120" } { "classname" "light" "origin" "-160 -256 64" "light" "120" } { "classname" "light" "origin" "-160 -168 96" "light" "100" } { "classname" "light" "origin" "-432 -800 136" "light" "200" } { "classname" "light" "origin" "-304 -800 136" "light" "200" } { "classname" "light" "origin" "-304 -576 136" "light" "200" } { "classname" "light" "origin" "-432 -576 136" "light" "200" } { "classname" "light" "origin" "-160 -784 48" "light" "200" } { "model" "*3" "spawnflags" "2" "angle" "90" "classname" "func_door_secret" } { "light" "214" "origin" "-448 -560 -248" "classname" "light" } { "classname" "light" "origin" "-320 -736 -192" "light" "150" } { "classname" "light" "origin" "-160 -752 -88" "light" "100" } { "model" "*4" "classname" "func_door_secret" "angle" "90" "spawnflags" "2" } { "classname" "light" "origin" "-648 -856 -8" "light" "150" } { "classname" "light" "origin" "-600 -592 96" "light" "214" } { "classname" "light" "origin" "-568 -328 136" "light" "150" } { "classname" "light" "origin" "-568 -208 136" "light" "164" } { "classname" "light" "origin" "-688 -992 -8" "light" "150" } { "light" "200" "origin" "-368 -888 -208" "classname" "light" } { "light" "200" "origin" "-568 -744 -232" "classname" "light" } { "light" "250" "origin" "-336 -1040 56" "classname" "light" } { "light" "250" "origin" "-336 -1200 56" "classname" "light" } { "light" "250" "origin" "-392 -1096 -224" "classname" "light" } { "light" "200" "origin" "-192 -1096 -224" "classname" "light" } { "origin" "-400 -1040 -312" "classname" "misc_explobox" } { "origin" "-432 -1224 -312" "classname" "misc_explobox" } { "origin" "-288 -1080 -312" "classname" "misc_explobox" } { "classname" "light" "origin" "40 -1016 -256" "light" "150" } { "classname" "light" "origin" "-64 -1064 -224" "light" "150" } { "classname" "light" "origin" "280 -1192 -160" "light" "200" } { "classname" "light" "origin" "-16 -1120 -72" } { "light" "250" "classname" "light" "origin" "264 -1144 -296" } { "classname" "light" "origin" "480 -1136 64" "light" "250" } { "classname" "light" "origin" "272 -1136 64" } { "classname" "light" "origin" "552 -1016 -32" "light" "150" } { "classname" "light" "origin" "552 -1256 -32" "light" "150" } { "classname" "light" "origin" "32 -736 56" "light" "350" } { "classname" "light" "origin" "-152 -224 -288" "light" "214" } { "classname" "light" "origin" "-152 -424 -288" "light" "214" } { "classname" "light" "origin" "-152 -608 -288" "light" "214" } { "classname" "light" "origin" "-160 -800 -288" "light" "214" } { "classname" "light" "origin" "0 -912 -288" "light" "214" } { "light" "120" "origin" "424 -576 -56" "classname" "light" } { "classname" "light" "origin" "720 -368 144" "light" "200" } { "light" "300" "classname" "light" "origin" "1120 -736 96" } { "light" "300" "classname" "light" "origin" "1120 -416 96" } { "light" "300" "classname" "light" "origin" "1440 -416 96" } { "light" "300" "classname" "light" "origin" "1440 -736 96" } { "classname" "light" "origin" "768 -576 48" "light" "200" } { "classname" "light" "origin" "1280 -576 200" "light" "150" } { "light" "250" "classname" "light_fluorospark" "origin" "856 -1344 16" "style" "10" } { "light" "250" "classname" "light_fluoro" "origin" "896 -1096 16" } { "light" "250" "classname" "light_fluoro" "origin" "1280 -1384 32" } { "classname" "light" "origin" "1280 -1056 144" "light" "200" } { "classname" "light" "origin" "1000 -904 128" "light" "214" } { "origin" "976 -720 -48" "classname" "misc_explobox" } { "origin" "976 -480 -48" "classname" "misc_explobox2" } { "classname" "light" "origin" "1280 -1072 -248" "light" "264" } { "classname" "light" "origin" "1280 -1128 -24" "light" "150" } { "model" "*5" "sounds" "3" "classname" "func_door" "angle" "270" "spawnflags" "1" "targetname" "t5" "wait" "-1" } { "classname" "light" "origin" "1280 -1016 32" "light" "200" } { "classname" "light" "origin" "1280 -856 -56" "light" "164" } { "classname" "light" "origin" "1376 -968 -56" "light" "164" } { "classname" "light" "origin" "1376 -1080 -56" "light" "150" } { "classname" "light" "origin" "1184 -968 -56" "light" "164" } { "classname" "light" "origin" "1184 -1080 -56" "light" "150" } { "classname" "light" "origin" "1064 -112 144" } { "classname" "light" "origin" "1656 -152 72" } { "classname" "light" "origin" "1272 16 -312" "light" "564" } { "classname" "light" "origin" "912 -952 -224" } { "origin" "1288 464 80" "classname" "light" } { "light" "200" "origin" "1288 520 -248" "classname" "light" } { "origin" "1088 720 32" "classname" "light" "light" "200" } { "origin" "1280 720 32" "classname" "light" "light" "200" } { "origin" "1472 720 32" "classname" "light" "light" "200" } { "light" "200" "origin" "1424 584 -184" "classname" "light" } { "light" "200" "origin" "1280 768 -184" "classname" "light" } { "light" "150" "origin" "1112 768 -184" "classname" "light" } { "light" "150" "origin" "1448 768 -184" "classname" "light" } { "light" "350" "origin" "1280 912 -32" "classname" "light" } { "light" "150" "origin" "1152 1216 -104" "classname" "light" } { "light" "150" "origin" "1408 1216 -104" "classname" "light" } { "light" "264" "origin" "1272 144 -320" "classname" "light" } { "light" "264" "origin" "1272 296 -320" "classname" "light" } { "origin" "1424 528 -272" "classname" "item_health" } { "origin" "1312 648 -272" "classname" "item_health" } { "origin" "1056 936 -272" "classname" "item_health" } { "origin" "1496 1032 -272" "classname" "item_spikes" "spawnflags" "1" } { "classname" "info_teleport_destination" "origin" "672 280 8" "angle" "180" "targetname" "t6" } { "model" "*6" "classname" "trigger_teleport" "target" "t6" } { "model" "*7" "classname" "trigger_teleport" "target" "t7" } { "classname" "info_teleport_destination" "origin" "-216 288 -136" "targetname" "t7" //Q-Man "angle" "5" } { "model" "*8" "classname" "trigger_teleport" "target" "t8" } { "classname" "info_teleport_destination" "origin" "464 600 8" "angle" "270" "targetname" "t8" } { "classname" "light" "origin" "608 -576 8" "light" "220" } { "classname" "light" "origin" "784 -328 48" "light" "200" } { "classname" "light" "origin" "784 -824 48" "light" "200" } { "classname" "light" "origin" "664 -424 -24" "light" "220" } { "classname" "light" "origin" "680 -744 -24" "light" "220" } { "classname" "light" "origin" "712 -784 144" "light" "200" } { "classname" "light" "origin" "896 -576 8" "light" "170" } { "classname" "light" "origin" "896 -320 8" "light" "180" } { "classname" "light" "origin" "896 -832 8" "light" "180" } { "classname" "light" "origin" "792 -576 152" "light" "200" } { "classname" "info_teleport_destination" "origin" "-192 -1216 -72" "angle" "90" "targetname" "t9" } { "spawnflags" "1792" "classname" "weapon_rocketlauncher" "origin" "-192 -1008 -80" } { "spawnflags" "1792" "classname" "item_rockets" "origin" "24 -1240 -312" } { "classname" "item_health" "origin" "-688 -936 64" "spawnflags" "2" } { "classname" "item_armor2" "origin" "376 -1136 -80" } { "classname" "item_health" "origin" "872 -1400 -64" "spawnflags" "1" } { "classname" "item_health" "origin" "920 -1400 -64" "spawnflags" "1" } { "classname" "item_health" "origin" "1296 -1400 -48" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1472 -592 -48" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1264 -384 -32" "spawnflags" "1" } { "spawnflags" "1792" "classname" "weapon_grenadelauncher" "origin" "1392 1168 -192" } { "spawnflags" "1792" "classname" "weapon_supernailgun" "origin" "1168 1168 -192" } { "classname" "item_rockets" "origin" "1032 1104 -272" } { "classname" "item_health" "origin" "544 1056 -160" "spawnflags" "2" } { "classname" "item_armor1" "origin" "464 304 0" } { "classname" "item_armorInv" "origin" "-472 -512 -288" } { "spawnflags" "1792" "classname" "weapon_nailgun" "origin" "-560 -680 -288" } { "classname" "item_shells" "origin" "0 -592 -128" "spawnflags" "1537" } { "classname" "item_shells" "origin" "96 -592 -128" "spawnflags" "1537" } { "classname" "item_health" "origin" "440 -592 -128" } { "model" "*9" "classname" "trigger_teleport" "target" "t9" } { "classname" "info_player_deathmatch" "origin" "1288 664 -248" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "616 -1128 -56" } { "classname" "info_player_deathmatch" "origin" "-472 -920 -56" } { "spawnflags" "1792" "classname" "weapon_supernailgun" "origin" "-160 -784 -32" } { "classname" "info_player_deathmatch" "origin" "-416 192 -24" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "688 448 -168" "angle" "180" } { "light" "214" "origin" "320 -912 -296" "classname" "light" } { "light" "214" "origin" "184 -912 -288" "classname" "light" } { "model" "*10" "targetname" "t10" "spawnflags" "10" "angle" "180" "classname" "func_door_secret" } { "model" "*11" "classname" "func_plat" "sounds" "1" } { "light" "150" "origin" "40 -1344 -248" "classname" "light" } { "model" "*12" "target" "t10" "classname" "trigger_multiple" } { "light" "150" "origin" "168 -1368 -344" "classname" "light" } { "light" "150" "origin" "320 -1368 -344" "classname" "light" } { "origin" "-120 -1024 -312" "classname" "item_health" } { "origin" "-136 -1080 -312" "classname" "item_health" } { "origin" "24 -1032 -192" "classname" "item_health" } { "model" "*13" "classname" "func_plat" } { "light" "200" "origin" "80 704 32" "classname" "light" } { "light" "200" "origin" "112 568 -312" "classname" "light" } { "light" "200" "origin" "216 456 -312" "classname" "light" } { "light" "200" "origin" "408 456 -288" "classname" "light" } { "light" "200" "origin" "616 456 -288" "classname" "light" } { "model" "*14" "targetname" "t11" "spawnflags" "8" "angle" "180" "classname" "func_door_secret" } { "model" "*15" "target" "t11" "classname" "trigger_multiple" } { "light" "200" "origin" "88 704 -288" "classname" "light" } { "light" "250" "origin" "2144 -528 48" "classname" "light" } { "model" "*16" "classname" "func_plat" "sounds" "1" } { "light" "214" "origin" "1280 -576 -104" "classname" "light" } { "light" "150" "origin" "1104 -568 -112" "classname" "light" } { "light" "200" "origin" "936 -488 -112" "classname" "light" } { "light" "150" "origin" "1168 -432 -112" "classname" "light" } { "light" "150" "origin" "1168 -720 -112" "classname" "light" } { "light" "200" "origin" "864 -576 192" "classname" "light" } { "light" "214" "origin" "1080 -576 192" "classname" "light" } { "origin" "1112 -464 -144" "classname" "item_armor2" } { "origin" "1176 -720 -144" "classname" "item_health" } { "origin" "1032 -552 -144" "classname" "item_rockets" } { "light" "200" "origin" "936 -664 -112" "classname" "light" } { "light" "150" "origin" "1304 -696 -112" "classname" "light" } { "light" "150" "origin" "1296 -456 -112" "classname" "light" } { "spawnflags" "1792" "origin" "720 -576 96" "classname" "weapon_supershotgun" } { "spawnflags" "1" "origin" "736 -480 96" "classname" "item_shells" } { "spawnflags" "1" "origin" "736 -704 96" "classname" "item_shells" } { "spawnflags" "1537" "origin" "328 -560 -128" "classname" "item_spikes" } { "spawnflags" "1793" "origin" "384 -616 -128" "classname" "item_spikes" } { "light" "244" "classname" "light" "origin" "-160 184 8" } { "light" "250" "classname" "light" "origin" "-216 -576 -8" } { "model" "*17" "height" "120" "classname" "func_plat" "sounds" "1" } { "light" "150" "origin" "-672 -936 112" "classname" "light" } { "light" "200" "origin" "-752 -1016 -232" "classname" "light" } { "light" "200" "origin" "-752 -712 -232" "classname" "light" } { "model" "*18" "classname" "trigger_changelevel" "map" "e3m2" } { "light" "200" "origin" "32 32 56" "classname" "light" } { "light" "244" "origin" "-104 296 -104" "classname" "light" } { "classname" "light" "origin" "-120 344 56" "light" "200" } { "classname" "light" "origin" "-48 184 16" "light" "200" } { "classname" "light" "origin" "288 32 56" "light" "244" } { "light" "244" "origin" "544 32 56" "classname" "light" } { "classname" "light" "origin" "704 160 56" "light" "244" } { "light" "214" "origin" "904 176 8" "classname" "light" } { "classname" "light" "origin" "1160 184 8" "light" "214" } { "light" "264" "origin" "2016 -240 8" "classname" "light" } { "classname" "light" "origin" "2040 -40 24" "light" "220" } { "light" "220" "origin" "1864 192 40" "classname" "light" } { "classname" "light" "origin" "1656 192 8" "light" "264" } { "origin" "1624 -920 72" "classname" "light" } { "light" "264" "origin" "1432 -576 -216" "classname" "light" } { "light" "200" "origin" "1760 -352 -152" "classname" "light" } { "spawnflags" "768" "angle" "45" "origin" "630 526 56" "classname" "monster_enforcer" } { "spawnflags" "1" "origin" "520 560 32" "classname" "item_health" } { "model" "*19" "spawnflags" "2048" "speed" "500" "angle" "-2" "classname" "func_door" "wait" "-1" } { "model" "*20" "targetname" "t51" "spawnflags" "2048" "speed" "500" "angle" "-2" "classname" "func_door" "wait" "-1" } { "model" "*21" "sounds" "1" "wait" "-1" "target" "t13" "angle" "90" "classname" "func_button" "spawnflags" "2048" } { "model" "*22" "lip" "4" "sounds" "2" "wait" "-1" "targetname" "t13" "angle" "-2" "classname" "func_door" "spawnflags" "2048" } { "model" "*23" "sounds" "2" "wait" "-1" "targetname" "t13" "angle" "-2" "classname" "func_door" "spawnflags" "2048" } { "model" "*24" "sounds" "2" "wait" "-1" "targetname" "t14" "angle" "-2" "classname" "func_door" "spawnflags" "2048" } { "model" "*25" "sounds" "1" "wait" "-1" "angle" "270" "target" "t14" "classname" "func_button" "spawnflags" "2048" } { "model" "*26" "sounds" "2" "targetname" "t16" "wait" "-1" "angle" "90" "classname" "func_door" "spawnflags" "2048" } { "model" "*27" "sounds" "2" "targetname" "t16" "wait" "-1" "angle" "270" "classname" "func_door" "spawnflags" "2048" } { "model" "*28" "target" "t16" "wait" "-1" "angle" "270" "classname" "func_button" "spawnflags" "2048" } { "model" "*29" "sounds" "2" "spawnflags" "2056" "classname" "func_door" "angle" "0" "wait" "-1" "speed" "400" } { "model" "*30" "classname" "func_door" "angle" "180" "spawnflags" "2056" "wait" "-1" "speed" "400" } { "sounds" "3" "spawnflags" "2048" "classname" "item_key2" "origin" "-160 -752 -8" } { "classname" "item_health" "origin" "2064 48 -16" } { "origin" "2064 112 -48" "classname" "item_health" "spawnflags" "1024" } { "classname" "item_shells" "origin" "1936 240 -112" } { "classname" "path_corner" "origin" "712 328 -184" "targetname" "t18" "target" "t19" } { "origin" "712 568 -184" "classname" "path_corner" "targetname" "t19" "target" "t20" } { "classname" "path_corner" "origin" "520 568 -184" "target" "t17" "targetname" "t20" } { "origin" "520 328 -184" "classname" "path_corner" "targetname" "t17" "target" "t18" } { "classname" "monster_army" "origin" "640 584 -168" "target" "t20" } { "classname" "monster_army" "origin" "560 496 -168" "spawnflags" "256" "target" "t17" } { "classname" "monster_dog" "origin" "680 408 -168" "spawnflags" "768" "target" "t19" } { "classname" "monster_enforcer" "origin" "-2 342 -136" "angle" "45" } { "classname" "monster_enforcer" "origin" "38 510 -24" "spawnflags" "768" "angle" "0" } { "classname" "weapon_supershotgun" "origin" "872 560 32" "spawnflags" "2048" } { "classname" "weapon_nailgun" "origin" "-336 -816 -288" "spawnflags" "2048" } { "classname" "item_artifact_super_damage" "origin" "1280 -704 -8" } { "model" "*31" "classname" "func_wall" "spawnflags" "2048" } { "model" "*32" "classname" "func_wall" "spawnflags" "2048" } { "classname" "monster_army" "origin" "464 448 24" "angle" "270" "spawnflags" "256" } { "classname" "path_corner" "origin" "-192 -1232 -72" "targetname" "t21" "target" "t22" } { "origin" "-192 -984 -72" "classname" "path_corner" "target" "t21" "targetname" "t22" } { "classname" "monster_army" "origin" "-168 -1104 -56" "target" "t22" } { "classname" "monster_army" "origin" "-456 -920 -56" "angle" "270" "spawnflags" "256" } { "classname" "monster_army" "origin" "-336 -1088 -288" "angle" "180" } { "angle" "180" "origin" "-296 -976 -288" "classname" "monster_army" "spawnflags" "256" } { "spawnflags" "768" "classname" "monster_army" "origin" "-56 -1032 -288" "angle" "180" } { "classname" "monster_dog" "origin" "-80 -1120 -288" "angle" "180" "spawnflags" "256" } { "classname" "monster_army" "origin" "40 -1176 -288" "angle" "90" } { "classname" "monster_enforcer" "origin" "-570 -706 -264" "angle" "270" "targetname" "t30" } { "classname" "monster_dog" "origin" "-536 -880 -264" "angle" "0" } { "classname" "item_artifact_super_damage" "origin" "-152 -728 -104" } { "classname" "item_armor1" "origin" "-216 288 -160" } { "targetname" "t55" "angle" "90" "origin" "-392 224 -136" "classname" "monster_army" } { "classname" "item_spikes" "origin" "-592 -1032 -288" } { "model" "*33" "classname" "trigger_teleport" "target" "t23" } { "classname" "info_teleport_destination" "origin" "-72 -576 8" "angle" "0" "targetname" "t23" } { "classname" "path_corner" "origin" "-296 -720 -280" "targetname" "t24" "target" "t25" } { "origin" "-296 72 -152" "classname" "path_corner" "target" "t24" "targetname" "t25" } { "classname" "monster_army" "origin" "-328 184 -136" "target" "t25" } { "classname" "path_corner" "origin" "-320 -576 -120" "targetname" "t26" "target" "t27" } { "origin" "624 -576 -120" "classname" "path_corner" "target" "t26" "targetname" "t27" } { "classname" "monster_enforcer" "origin" "206 -594 -104" "target" "t27" } { "classname" "path_corner" "origin" "784 -312 -120" "targetname" "t28" "target" "t29" } { "origin" "784 -840 -120" "classname" "path_corner" "target" "t28" "targetname" "t29" } { "classname" "monster_enforcer" "origin" "782 -586 -104" "target" "t28" } { "classname" "monster_enforcer" "origin" "686 -578 -104" "spawnflags" "256" "angle" "0" } { "model" "*34" "classname" "trigger_once" "target" "t30" } { "classname" "monster_enforcer" "origin" "40 -1104 -168" "angle" "180" "spawnflags" "256" } { "classname" "monster_army" "origin" "40 -1216 -168" "angle" "180" } { "classname" "monster_dog" "origin" "368 -1040 -56" "angle" "180" } { "classname" "monster_army" "origin" "376 -1240 -56" "angle" "180" "spawnflags" "256" } { "classname" "monster_enforcer" "origin" "582 -1130 -56" "spawnflags" "768" "angle" "180" } { "classname" "item_shells" "origin" "-384 128 -160" "spawnflags" "1" } { "classname" "monster_army" "origin" "-752 -952 -264" "angle" "90" "spawnflags" "256" } { "classname" "monster_enforcer" "origin" "-690 -458 -264" "spawnflags" "256" "angle" "45" } { "classname" "monster_dog" "origin" "-488 -368 -264" "angle" "90" "spawnflags" "768" } { "classname" "monster_army" "origin" "-408 -272 -24" "angle" "90" "spawnflags" "256" } { "classname" "monster_enforcer" "origin" "-450 -410 -24" "spawnflags" "256" "angle" "270" } { "classname" "path_corner" "origin" "-264 -136 -40" "targetname" "t31" "target" "t32" } { "origin" "-264 -440 -40" "classname" "path_corner" "target" "t31" "targetname" "t32" } { "classname" "monster_army" "origin" "-256 -328 -24" "target" "t32" } { "classname" "path_corner" "origin" "896 -1128 -56" "targetname" "t34" "target" "t35" } { "origin" "896 -1344 -56" "classname" "path_corner" "target" "t34" "targetname" "t35" } { "classname" "monster_army" "origin" "904 -1272 -40" "target" "t34" } { "classname" "monster_enforcer" "origin" "990 -1346 -24" "angle" "180" "spawnflags" "256" } { "classname" "path_corner" "origin" "1280 -1192 -24" "targetname" "t36" "target" "t37" } { "origin" "1280 -1352 -24" "classname" "path_corner" "target" "t36" "targetname" "t37" } { "classname" "monster_enforcer" "origin" "1270 -1282 -8" "target" "t36" } { "classname" "monster_army" "origin" "1104 -1344 -24" "angle" "180" "spawnflags" "256" } { "classname" "monster_dog" "origin" "1184 -1344 -24" "angle" "180" "spawnflags" "768" } { "classname" "monster_army" "origin" "1280 -784 -8" "angle" "270" } { "classname" "monster_enforcer" "origin" "-162 -330 -136" "angle" "180" "spawnflags" "768" } { "classname" "item_health" "origin" "-208 -1208 -80" } { "classname" "item_health" "origin" "-440 -936 -80" "spawnflags" "1" } { "classname" "path_corner" "origin" "1480 -328 -40" "targetname" "t38" "target" "t39" } { "origin" "1080 -328 -40" "classname" "path_corner" "targetname" "t39" "target" "t40" } { "classname" "path_corner" "origin" "1080 -824 -40" "targetname" "t40" "target" "t41" } { "origin" "1480 -824 -40" "classname" "path_corner" "target" "t38" "targetname" "t41" } { "classname" "monster_army" "origin" "1536 -496 -24" "target" "t38" "spawnflags" "256" } { "classname" "monster_army" "origin" "1024 -304 -24" "spawnflags" "256" "target" "t39" } { "classname" "monster_enforcer" "origin" "1030 -770 -24" "target" "t40" } { "classname" "monster_dog" "origin" "1560 -856 -24" "target" "t41" } { "classname" "monster_enforcer" "origin" "1278 -442 -8" "angle" "90" "spawnflags" "768" } { "classname" "monster_enforcer" "origin" "1150 -578 -24" "spawnflags" "768" "angle" "270" } { "classname" "monster_army" "origin" "-152 40 -24" "angle" "270" "spawnflags" "256" } { "classname" "path_corner" "origin" "-448 -8 -40" "targetname" "t42" "target" "t43" } { "origin" "-272 152 -40" "classname" "path_corner" "target" "t42" "targetname" "t43" } { "classname" "monster_army" "origin" "-256 88 -24" "target" "t43" } { "classname" "monster_enforcer" "origin" "-458 166 -24" "spawnflags" "256" "angle" "270" } { "classname" "monster_army" "origin" "-112 320 -24" "angle" "135" } { "classname" "monster_army" "origin" "-176 456 -24" "spawnflags" "256" "angle" "225" } { "classname" "path_corner" "origin" "56 32 -40" "targetname" "t44" "target" "t45" } { "origin" "608 32 -40" "classname" "path_corner" "target" "t44" "targetname" "t45" } { "classname" "monster_enforcer" "origin" "286 30 -24" "target" "t44" } { "classname" "monster_army" "origin" "672 40 -24" "angle" "180" "spawnflags" "256" } { "classname" "monster_dog" "origin" "696 152 -24" "spawnflags" "256" "angle" "270" } { "classname" "item_spikes" "origin" "544 -1040 -80" "spawnflags" "1537" } { "classname" "item_shells" "origin" "544 -1272 -80" "spawnflags" "1537" } { "classname" "item_health" "origin" "-48 416 -48" "spawnflags" "1024" } { "origin" "16 416 -48" "classname" "item_health" "spawnflags" "1" } { "classname" "item_health" "origin" "80 512 -48" "spawnflags" "1536" } { "classname" "monster_army" "origin" "1064 184 -24" "angle" "180" } { "model" "*35" "sounds" "2" "speed" "500" "classname" "func_door" "angle" "-1" "spawnflags" "1" "targetname" "t46" "wait" "20" } //{ //"model" "*36" //"spawnflags" "1792" //"classname" "trigger_multiple" //"target" "t46" //"wait" "20" //} { "model" "*37" "sounds" "2" "speed" "500" "classname" "func_door" "angle" "-1" "spawnflags" "1" "targetname" "t47" "wait" "20" } //{ //"model" "*38" //"spawnflags" "1792" //"classname" "trigger_multiple" //"target" "t47" //"wait" "20" //} { "model" "*39" "sounds" "2" "speed" "500" "classname" "func_door" "angle" "-1" "spawnflags" "1" "targetname" "t48" "wait" "20" } //{ //"model" "*40" //"spawnflags" "1792" //"classname" "trigger_multiple" //"target" "t48" //"wait" "20" //} { "classname" "monster_dog" "origin" "1432 192 -24" "angle" "180" "spawnflags" "256" } { "classname" "monster_army" "origin" "2016 192 -88" "angle" "270" } { "classname" "monster_enforcer" "origin" "1894 70 -88" "angle" "135" "spawnflags" "256" } { "classname" "monster_army" "origin" "1712 240 -88" "angle" "180" } { "angle" "180" "origin" "1712 160 -88" "classname" "monster_army" "spawnflags" "256" } { "spawnflags" "256" "angle" "0" "origin" "1944 -152 -88" "classname" "monster_army" } { "angle" "90" "origin" "2048 -176 -88" "classname" "monster_army" } { "spawnflags" "256" "angle" "180" "origin" "2182 -394 -24" "classname" "monster_enforcer" } { "angle" "180" "origin" "2320 -640 -24" "classname" "monster_army" } { "spawnflags" "768" "angle" "90" "origin" "2112 -616 -24" "classname" "monster_army" } { "model" "*41" "spawnflags" "2048" "classname" "func_wall" } { "model" "*42" "spawnflags" "2048" "classname" "func_wall" } { "spawnflags" "1" "origin" "2512 -544 -48" "classname" "item_shells" } { "model" "*43" "target" "t51" "classname" "trigger_once" } { "spawnflags" "1" "origin" "80 400 -48" "classname" "item_shells" } { "model" "*44" "spawnflags" "2048" "sounds" "2" "wait" "-1" "speed" "500" "targetname" "t52" "angle" "90" "classname" "func_door" } { "model" "*45" "spawnflags" "2048" "sounds" "2" "wait" "-1" "speed" "500" "targetname" "t52" "angle" "270" "classname" "func_door" } { "model" "*46" "spawnflags" "2048" "target" "t52" "classname" "trigger_once" } { "targetname" "t52" "angle" "180" "origin" "2486 -410 -24" "classname" "monster_enforcer" } { "targetname" "t52" "spawnflags" "256" "classname" "monster_enforcer" "origin" "2486 -642 -24" "angle" "180" } { "model" "*47" "sounds" "1" "spawnflags" "1025" "classname" "func_plat" } { "light" "200" "origin" "1760 -368 8" "classname" "light" } { "model" "*48" "lip" "-1" "sounds" "2" "targetname" "t5" "spawnflags" "2048" "angle" "-2" "classname" "func_door" "wait" "-1" } { "light" "200" "origin" "616 352 104" "classname" "light" } { "classname" "light" "origin" "248 -1032 -56" "light" "150" } { "classname" "light" "origin" "1280 -1224 24" "light" "150" } { "classname" "light" "origin" "2520 -632 48" "light" "150" } { "light" "150" "origin" "2520 -424 48" "classname" "light" } { "classname" "light" "origin" "2336 -528 48" } { "classname" "light" "origin" "-192 -928 -40" "light" "150" } { "light" "200" "origin" "112 328 -88" "classname" "light" } { "light" "100" "origin" "-552 -840 -232" "classname" "light" } { "light" "150" "origin" "-264 -1216 -200" "classname" "light" } { "light" "200" "origin" "1096 440 -40" "classname" "light" } { "light" "200" "classname" "light" "origin" "1464 440 -40" } { "light" "150" "origin" "1280 1168 24" "classname" "light" } { "light" "200" "origin" "696 72 -184" "classname" "light" } { "light" "200" "origin" "704 280 56" "classname" "light" } { "origin" "824 888 -248" "classname" "light" } { "light" "250" "classname" "light" "origin" "376 888 -272" } { "spawnflags" "1024" "origin" "-608 -848 -288" "classname" "item_health" } { "classname" "item_health" "origin" "-592 -688 -288" "spawnflags" "1024" } { "classname" "light" "origin" "-592 -1016 -232" "light" "200" } { "classname" "light" "origin" "-760 -456 -232" "light" "200" } { "model" "*49" "target" "t55" "classname" "trigger_once" } { "light" "150" "origin" "1160 -800 -216" "classname" "light" } { "classname" "light" "origin" "1016 -800 -216" "light" "150" } { "light" "200" "origin" "1368 -800 -216" "classname" "light" } { "light" "100" "origin" "-440 -696 -120" "classname" "light" } { "classname" "light" "origin" "-304 -696 -232" "light" "150" } { "light" "150" "origin" "-304 -440 -232" "classname" "light" } { "spawnflags" "2048" "origin" "24 -1256 -312" "classname" "item_shells" } { "model" "*50" "targetname" "t56" "speed" "150" //Q-Man "angle" "-2" "classname" "func_door" "wait" "4" "sounds" "2" } { "light" "250" "origin" "656 664 112" "classname" "light_fluorospark" "style" "10" } { "light" "130" "origin" "536 600 112" "classname" "light" } { "model" "*51" "target" "t56" "angle" "180" "classname" "func_button" } { "light" "200" "origin" "864 464 -96" "classname" "light" } { "light" "200" "origin" "-376 -440 160" "classname" "light" } { "light" "180" "origin" "1984 -608 24" "classname" "light" } { "model" "*52" "spawnflags" "2048" "classname" "func_wall" } { "model" "*53" "spawnflags" "2048" "classname" "func_wall" } { "light" "150" "origin" "2072 -896 0" "classname" "light" } { "classname" "light" "origin" "2144 -792 0" "light" "150" } { "classname" "light" "origin" "1920 -896 0" "light" "150" } { "model" "*54" "speed" "400" "targetname" "t57" "spawnflags" "1793" "angle" "0" "classname" "func_door" "sounds" "2" } { "model" "*55" "spawnflags" "1792" "target" "t57" "classname" "trigger_multiple" } { "classname" "light" "origin" "1760 -664 8" "light" "200" } { "classname" "light" "origin" "1760 -680 -152" "light" "200" } { "light" "200" "origin" "1760 -536 120" "classname" "light" } { "model" "*56" "target" "t5" "classname" "trigger_once" } { "light" "200" "origin" "616 -208 -216" "classname" "light" } { "classname" "light" "origin" "592 -808 -216" "light" "200" } { "light" "120" "origin" "2008 216 -56" "classname" "light" } { "light" "200" "origin" "-192 -1168 -40" "classname" "light" } { "classname" "light" "origin" "-432 -920 8" "light" "200" } { "light" "200" "origin" "176 -296 -360" "classname" "light" } { "classname" "light" "origin" "176 -120 -360" "light" "200" } { "light" "200" "origin" "224 -464 -360" "classname" "light" } { "classname" "light" "origin" "224 -704 -360" "light" "200" } { "light" "200" "origin" "64 -576 -360" "classname" "light" } { "classname" "light" "origin" "-32 -480 -360" "light" "200" } { "light" "200" "origin" "-32 -672 -360" "classname" "light" } { "classname" "light" "origin" "16 64 -200" "light" "300" } { "classname" "monster_army" "origin" "2216 -656 -24" "angle" "90" "spawnflags" "768" } { "classname" "light" "origin" "1120 368 -312" "light" "200" } { "light" "200" "origin" "1440 368 -312" "classname" "light" } { "classname" "light" "origin" "1280 368 -312" "light" "200" } { "light" "200" "origin" "1536 696 -312" "classname" "light" } { "classname" "light" "origin" "1056 696 -312" "light" "200" } { "light" "200" "origin" "1056 512 -312" "classname" "light" } { "classname" "light" "origin" "1536 528 -312" "light" "200" } { "classname" "light" "origin" "1024 832 -312" "light" "200" } { "light" "200" "origin" "1536 832 -312" "classname" "light" } { "light" "150" "origin" "1032 1088 -232" "classname" "light" } { "classname" "light" "origin" "1528 1088 -232" "light" "150" } { "light" "200" "origin" "464 304 48" "classname" "light" } { "light" "150" "origin" "-56 528 8" "classname" "light" } { "model" "*57" "classname" "trigger_secret" } { "model" "*58" "classname" "trigger_secret" } { "model" "*59" "classname" "trigger_secret" } { "model" "*60" "classname" "trigger_secret" } { "classname" "light" "origin" "248 -576 120" "light" "200" } { "model" "*61" "classname" "trigger_secret" } { "light" "200" "origin" "872 -696 -320" "classname" "light" } { "classname" "light" "origin" "872 -456 -320" "light" "200" } { "light" "200" "origin" "872 -584 -320" "classname" "light" } { "light" "200" "origin" "1280 -696 -320" "classname" "light" } { "classname" "light" "origin" "1160 -576 -320" "light" "200" } { "origin" "-414 -334 24" "classname" "ambient_comp_hum" } { "classname" "ambient_comp_hum" "origin" "-478 -206 24" } { "origin" "-334 -270 24" "classname" "ambient_comp_hum" } { "classname" "info_intermission" "origin" "880 -208 128" "mangle" "20 300 0" } { "classname" "info_intermission" "origin" "1096 624 -256" "mangle" "-20 60 0" } { "classname" "info_intermission" "origin" "360 1056 144" "mangle" "20 315 0" } { "classname" "info_intermission" "origin" "328 -1272 32" "mangle" "20 150 0" } { "classname" "ambient_comp_hum" "origin" "1986 -606 112" } { "classname" "ambient_swamp1" "origin" "1730 -574 -136" } { "classname" "ambient_swamp2" "origin" "1274 -78 -136" } { "classname" "ambient_swamp1" "origin" "1282 570 -136" } { "classname" "ambient_swamp2" "origin" "602 -310 -136" } { "classname" "ambient_swamp1" "origin" "410 138 -288" } { "classname" "ambient_swamp2" "origin" "50 -222 -288" } { "classname" "ambient_swamp1" "origin" "610 890 -288" } { "spawnflags" "1792" "origin" "-408 120 -48" "classname" "weapon_lightning" } { "angle" "90" "origin" "544 392 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "592 416 56" "angle" "90" } { "angle" "90" "origin" "640 416 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "680 392 56" "angle" "90" } { "model" "*62" "spawnflags" "1792" "classname" "func_wall" } { "light" "200" "origin" "-432 -584 -120" "classname" "light" } { "model" "*63" "targetname" "t58" "sounds" "3" "angle" "180" "spawnflags" "5" "classname" "func_door_secret" } { "model" "*64" "spawnflags" "1" "classname" "func_plat" } { "model" "*65" "target" "t58" "classname" "trigger_once" } { "origin" "1954 34 48" "classname" "ambient_comp_hum" } { "origin" "2082 98 -72" "classname" "ambient_comp_hum" } { "origin" "1890 242 -80" "classname" "ambient_comp_hum" } { "classname" "light" "origin" "1992 -400 136" "light" "200" } { "model" "*66" "classname" "trigger_once" "target" "t16" } { "model" "*67" "spawnflags" "1792" "classname" "func_wall" } //{ //"model" "*68" //"spawnflags" "2048" //"target" "t46" //"classname" "trigger_once" //} //{ //"model" "*69" //"target" "t47" //"spawnflags" "2048" //"classname" "trigger_once" //} //{ //"model" "*70" //"spawnflags" "2048" //"target" "t48" //"classname" "trigger_once" //} { "classname" "item_shells" "origin" "808 544 32" } { "classname" "item_shells" "origin" "288 560 -160" } { "model" "*71" "classname" "func_wall" "spawnflags" "2048" } { "classname" "ambient_drone" "origin" "2426 -526 48" } { "model" "*72" "classname" "func_button" "angle" "0" "target" "t56" } //Q-Man { "origin" "702 575 56" "classname" "item_flag_team1" } { "origin" "617 353 72" "classname" "info_player_team1" "angle" "90" } { "origin" "770 604 56" "classname" "info_player_team1" } { "origin" "654 335 -168" "classname" "info_player_team1" "angle" "180" } { "origin" "654 528 -168" "classname" "info_player_team1" "angle" "180" } { "origin" "340 528 -136" "classname" "info_player_team1" "angle" "180" } { "origin" "340 335 -136" "classname" "info_player_team1" "angle" "180" } { "origin" "2336 -528 -8" "classname" "item_flag_team2" } { "origin" "2090 -434 -24" "classname" "info_player_team2" "angle" "315" } { "origin" "2234 -593 -24" "classname" "info_player_team2" "angle" "135" } { "origin" "2121 -873 -40" "classname" "info_player_team2" "angle" "225" } { "origin" "2029 -252 -56" "classname" "info_player_team2" "angle" "90" } { "origin" "1992 -6 -88" "classname" "info_player_team2" "angle" "135" } { "origin" "1738 208 -88" "classname" "info_player_team2" "angle" "180" } // ================================ // begin extra BSP entity list for e3m1 // ================================ { "classname" "item_shells" "origin" "680 506 -192" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "680 448 -192" } { "classname" "item_shells" "origin" "680 390 -192" "spawnflags" "1" } { "classname" "item_spikes" "origin" "564 506 -192" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "564 448 -192" } { "classname" "item_spikes" "origin" "564 390 -192" "spawnflags" "1" } { "classname" "item_health" "origin" "622 506 -192" } { "classname" "item_armor2" "origin" "622 448 -192" } { "classname" "item_health" "origin" "622 390 -192" } { "classname" "item_shells" "origin" "2233 -472 -48" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "2233 -530 -48" } { "classname" "item_shells" "origin" "2233 -588 -48" "spawnflags" "1" } { "classname" "item_spikes" "origin" "2117 -472 -48" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "2117 -530 -48" } { "classname" "item_spikes" "origin" "2117 -588 -48" "spawnflags" "1" } { "classname" "item_health" "origin" "2175 -472 -48" } { "classname" "item_armor2" "origin" "2175 -530 -48" } { "classname" "item_health" "origin" "2175 -588 -48" } // ================================ // end extra BSP entity list for e3m1 // ================================ { "origin" "-290 185 -24" "classname" "item_cells" "spawnflags" "1" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m2.ent000066400000000000000000000713521475442401000252020ustar00rootroot00000000000000{ "worldtype" "1" "wad" "gfx/metal.wad" "classname" "worldspawn" "sounds" "8" "message" "The Vaults of Zin" } { "angle" "270" "origin" "192 1120 40" "classname" "info_player_start" } { "origin" "192 512 168" "classname" "light" } { "origin" "192 800 160" "classname" "light" "light" "200" } { "origin" "192 672 160" "classname" "light" "light" "200" } { "sounds" "1" "targetname" "t3" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*1" } { "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*2" } { "targetname" "t3" "angle" "180" "origin" "336 672 24" "classname" "monster_zombie" } { "target" "t3" "classname" "trigger_once" "model" "*3" } { "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*4" } { "targetname" "t3" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*5" } { "targetname" "t3" "angle" "0" "origin" "48 672 24" "classname" "monster_zombie" } { "sounds" "1" "targetname" "t3" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*6" } { "targetname" "t3" "angle" "-1" "wait" "-1" "classname" "func_door" "model" "*7" } { "targetname" "t3" "angle" "180" "origin" "336 800 24" "classname" "monster_zombie" } { "targetname" "t3" "angle" "0" "origin" "48 800 24" "classname" "monster_zombie" } { "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*8" } { "angle" "-2" "wait" "-1" "classname" "func_door" "model" "*9" } { "origin" "312 736 160" "classname" "light" } { "origin" "80 736 160" "classname" "light" } { "target" "t4" "classname" "trigger_once" "model" "*10" } { "light" "200" "origin" "352 512 168" "classname" "light" } { "light" "200" "origin" "-96 512 168" "classname" "light" } { "origin" "480 512 168" "classname" "light" } { "origin" "32 512 168" "classname" "light" } { "origin" "192 352 168" "classname" "light" } //{ //"sounds" "3" //"angle" "-2" //"targetname" "t4" //"speed" "300" //"wait" "-1" //"classname" "func_door" //"spawnflags" "4" //"model" "*11" //} { "speed" "100" "spawnflags" "5" "wait" "-1" "targetname" "t4" "angle" "180" "classname" "func_door" "model" "*12" } { "sounds" "1" "speed" "100" "spawnflags" "5" "wait" "-1" "targetname" "t4" "angle" "0" "classname" "func_door" "model" "*13" } { "light" "400" "origin" "192 168 104" "classname" "light" } { "light" "400" "origin" "304 320 152" "classname" "light" } { "light" "400" "origin" "80 320 152" "classname" "light" } { "origin" "-384 512 168" "classname" "light" } //{ //"message" "This door is opened elsewhere..." //"sounds" "1" //"wait" "-1" //"angle" "-1" //"classname" "func_door" //"targetname" "t13" //"model" "*14" //} { "target" "t6" "origin" "46 126 -232" "classname" "monster_ogre" "spawnflags" "1" } //{ //"target" "t5" //"classname" "trigger_teleport" //"model" "*15" //} //{ //"targetname" "t5" //"angle" "0" //"origin" "-80 512 24" //"classname" "info_teleport_destination" //} { "light" "200" "origin" "64 368 -192" "classname" "light" } { "target" "t6" "targetname" "t7" "angle" "180" "origin" "288 264 -248" "classname" "path_corner" } { "target" "t7" "targetname" "t6" "angle" "0" "origin" "64 128 -248" "classname" "path_corner" } { "origin" "768 512 168" "classname" "light" } { "origin" "768 352 168" "classname" "light" } { "origin" "-384 352 168" "classname" "light" } { "classname" "func_plat" "model" "*16" } { "light" "200" "origin" "-432 -8 -40" "classname" "light" } { "light" "200" "origin" "-328 -8 -40" "classname" "light" } { "light" "200" "origin" "-432 -120 -32" "classname" "light" } { "light" "200" "origin" "-336 -120 -40" "classname" "light" } { "origin" "-384 -416 -40" "classname" "light" } { "origin" "-384 128 256" "classname" "light" } { "origin" "-384 -256 256" "classname" "light" } { "origin" "-216 -32 256" "classname" "light" } { "origin" "-552 -32 256" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "-118 162 12" } { "classname" "light" "origin" "-152 160 0" "light" "200" } { "origin" "-118 -30 12" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-118 -222 12" } { "origin" "-646 -222 12" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-646 -30 12" } { "origin" "-646 162 12" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-144 -32 0" "classname" "light" } { "classname" "light" "origin" "-152 -224 0" "light" "200" } { "light" "200" "origin" "-608 -224 0" "classname" "light" } { "classname" "light" "origin" "-632 -32 0" "light" "200" } { "light" "200" "origin" "-640 160 0" "classname" "light" } { "classname" "func_button" "angle" "-2" "target" "t10" "wait" "-1" "model" "*17" } { "message" "This door is opened elsewhere..." "sounds" "1" "classname" "func_door" "angle" "-1" "targetname" "t10" "wait" "-1" "spawnflags" "2048" "model" "*18" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "456 376 -272" "targetname" "t3" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "496 296 -272" "targetname" "t3" } { "classname" "light" "origin" "480 336 -224" } { "classname" "light" "origin" "488 360 112" } { "classname" "weapon_grenadelauncher" "origin" "480 176 0" "spawnflags" "256" } { "classname" "item_rockets" "origin" "16 720 0" } { "sounds" "1" "wait" "-1" "classname" "func_button" "target" "t13" "model" "*19" } { "light" "500" "origin" "512 -272 -8" "classname" "light" } { "light" "500" "origin" "512 -32 -8" "classname" "light" } { "light" "500" "origin" "512 96 104" "classname" "light" } { "spawnflags" "2" "origin" "464 464 -280" "classname" "item_health" } { "wait" "-1" "targetname" "t14" "speed" "200" "lip" "24" "angle" "-2" "classname" "func_door" "model" "*20" } { "speed" "200" "classname" "func_plat" "model" "*21" } { "target" "t14" "classname" "trigger_multiple" "wait" "4" "model" "*22" } { "spawnflags" "2048" "origin" "192 320 48" "classname" "item_key1" "sounds" "2" } { "classname" "light" "origin" "-192 -128 -96" } { "classname" "path_corner" "origin" "192 -216 -32" "angle" "270" "targetname" "t15" "target" "t16" } { "classname" "path_corner" "origin" "192 -488 -32" "angle" "90" "targetname" "t16" "target" "t15" } { "origin" "192 -416 144" "classname" "light" } { "origin" "192 -288 144" "classname" "light" } { "angle" "90" "target" "t15" "origin" "198 -290 -32" "classname" "monster_ogre" "spawnflags" "768" } { "light" "600" "origin" "504 -648 312" "classname" "light" } { "light" "600" "origin" "192 -800 304" "classname" "light" } { "targetname" "t8" "angle" "90" "origin" "768 320 24" "classname" "monster_zombie" } { "angle" "90" "targetname" "t8" "origin" "768 400 24" "classname" "monster_zombie" } { "classname" "func_plat" "model" "*23" } { "message" "This door is opened elsewhere..." "sounds" "1" "targetname" "t21" "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "2048" "model" "*24" } { "sounds" "1" "target" "t21" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*25" } { "speed" "50" "angle" "-1" "wait" "-1" "targetname" "t21" "classname" "func_door" "model" "*26" } { "lip" "-8" "wait" "-1" "targetname" "t21" "speed" "300" "angle" "180" "classname" "func_door" "model" "*27" } { "origin" "448 -480 -216" "classname" "light" } { "targetname" "t21" "angle" "270" "origin" "448 -384 -352" "classname" "monster_zombie" } { "targetname" "t21" "angle" "270" "origin" "544 -384 -352" "classname" "monster_zombie" } { "targetname" "t21" "angle" "270" "origin" "640 -384 -352" "classname" "monster_zombie" } { "lip" "-8" "speed" "300" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*28" } { "origin" "290 -1006 -188" "classname" "light_torch_small_walltorch" } { "origin" "98 -1006 -188" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "192 -928 -192" "classname" "light" "target" "t50" "style" "2" } { "origin" "-176 208 192" "classname" "item_rockets" } { "origin" "-624 208 192" "classname" "item_health" } { "origin" "-384 96 208" "classname" "item_armor2" } { "origin" "-6 -606 -184" "classname" "light_torch_small_walltorch" } { "spawnflags" "4" "targetname" "t24" "lip" "8" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*29" } { "sounds" "1" "speed" "200" "targetname" "t22" "lip" "-100" "angle" "-2" "classname" "func_door" "model" "*30" } { "origin" "-144 -1280 -216" "classname" "light" "light" "200" } { "origin" "480 -1296 -216" "classname" "light" } { "origin" "184 -1280 -216" "classname" "light" } { "origin" "192 -1120 24" "classname" "light" } { "origin" "208 -1288 56" "classname" "light" } { "wait" "7" "target" "t22" "classname" "trigger_multiple" "model" "*31" } { "angle" "180" "origin" "494 -1282 -264" "classname" "monster_ogre" "spawnflags" "256" } { "angle" "0" "origin" "-50 -1282 -264" "classname" "monster_ogre" } { "sounds" "1" "target" "t23" "wait" "-1" "angle" "0" "classname" "func_button" "model" "*32" } { "origin" "192 -1536 -88" "classname" "light" } { "origin" "352 -1536 -88" "classname" "light" } { "sounds" "2" "angle" "0" "targetname" "t23" "wait" "-1" "classname" "func_door_secret" "model" "*33" } { "sounds" "1" "wait" "-1" "target" "t24" "angle" "0" "classname" "func_button" "model" "*34" } { "target" "t25" "classname" "trigger_teleport" "model" "*35" } { "targetname" "t25" "angle" "90" "origin" "192 -896 -48" "classname" "info_teleport_destination" } { "classname" "light_torch_small_walltorch" "origin" "-6 -734 -184" } { "origin" "-6 -862 -184" "classname" "light_torch_small_walltorch" } { "light" "100" "origin" "16 -672 -192" "classname" "light" } { "classname" "light" "origin" "16 -800 -192" "light" "100" } { "light" "100" "origin" "16 -528 -192" "classname" "light" } { "target" "t27" "targetname" "t26" "angle" "180" "origin" "576 -576 -248" "classname" "path_corner" } { "target" "t26" "targetname" "t27" "angle" "0" "origin" "64 -576 -248" "classname" "path_corner" } { "targetname" "t35" "angle" "0" "origin" "78 -562 -40" "classname" "monster_ogre" } { "origin" "-432 528 0" "classname" "item_health" } { "origin" "-432 480 0" "classname" "item_health" } { "origin" "-384 384 8" "classname" "weapon_supernailgun" } { "light" "600" "origin" "960 32 424" "classname" "light" } { "light" "500" "origin" "1176 24 424" "classname" "light" } { "light" "500" "origin" "960 -192 424" "classname" "light" } { "light" "600" "origin" "1168 -192 424" "classname" "light" } { "targetname" "t34" "wait" "-1" "classname" "func_door" "angle" "-2" "model" "*36" } { "targetname" "t34" "angle" "-2" "wait" "-1" "classname" "func_door" "sounds" "1" "model" "*37" } //{ //"sounds" "1" //"classname" "func_door" //"angle" "-1" //"targetname" "t28" //"wait" "-1" //"spawnflags" "4" //"model" "*38" //} //{ //"sounds" "1" //"wait" "-1" //"classname" "func_button" //"angle" "270" //"target" "t28" //"model" "*39" //} { "spawnflags" "256" "targetname" "t29" "classname" "monster_shambler" "origin" "1160 -168 -184" "angle" "45" "target" "t65" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t29" "model" "*40" } { "targetname" "t29" "wait" "-1" "spawnflags" "4" "angle" "270" "classname" "func_door" "model" "*41" } { "targetname" "t29" "wait" "-1" "spawnflags" "4" "angle" "0" "classname" "func_door" "model" "*42" } { "targetname" "t29" "spawnflags" "4" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*43" } { "sounds" "1" "targetname" "t29" "wait" "-1" "spawnflags" "4" "angle" "180" "classname" "func_door" "model" "*44" } { "targetname" "t34" "angle" "270" "origin" "880 112 24" "classname" "monster_zombie" } { "targetname" "t34" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*45" } { "light" "200" "origin" "1202 -214 -60" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "938 -214 -60" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "946 50 -60" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "1202 50 -60" "classname" "light_torch_small_walltorch" } { "sounds" "1" "target" "t31" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*46" } { "sounds" "1" "targetname" "t31" "wait" "-1" "classname" "func_door" "angle" "0" "model" "*47" } { "light" "200" "origin" "1168 -352 -136" "classname" "light" } { "target" "t32" "classname" "trigger_teleport" "model" "*48" } { "targetname" "t32" "angle" "90" "origin" "1376 -352 16" "classname" "info_teleport_destination" } { "light" "180" "origin" "976 -360 -136" "classname" "light" } { "origin" "896 216 16" "classname" "item_health" } { "origin" "960 216 16" "classname" "item_health" } { "origin" "1328 384 16" "classname" "item_health" } { "origin" "536 -1224 -288" "classname" "item_rockets" } { "targetname" "t33" "angle" "90" "origin" "190 -1514 -264" "classname" "monster_ogre" } { "target" "t33" "classname" "trigger_once" "model" "*49" } { "light" "200" "origin" "-768 64 16" "classname" "light" } { "origin" "1168 200 -208" "classname" "weapon_supershotgun" } { "targetname" "t34" "angle" "90" "origin" "1072 112 24" "classname" "monster_zombie" } { "wait" "-1" "targetname" "t34" "angle" "-1" "classname" "func_door" "model" "*50" } { "target" "t34" "classname" "trigger_once" "model" "*51" } { "targetname" "t34" "wait" "-1" "angle" "-1" "classname" "func_door" "sounds" "1" "model" "*52" } { "targetname" "t34" "classname" "func_door" "angle" "-1" "wait" "-1" "model" "*53" } { "targetname" "t34" "angle" "90" "origin" "880 -272 24" "classname" "monster_zombie" } { "targetname" "t34" "angle" "90" "origin" "1264 -272 24" "classname" "monster_zombie" } { "targetname" "t34" "angle" "270" "origin" "1072 -272 24" "classname" "monster_zombie" } { "origin" "1344 512 176" "classname" "light" } { "origin" "1600 512 176" "classname" "light" } { "origin" "1344 352 176" "classname" "light" } { "sounds" "3" "angle" "-2" "health" "1" "classname" "func_door" "wait" "4" "speed" "200" //Q-Man "model" "*54" } { "target" "t35" "classname" "trigger_once" "model" "*55" } { "origin" "240 -1552 -288" "classname" "item_shells" } { "sounds" "1" "target" "t36" "angle" "90" "classname" "func_button" "model" "*56" } { "origin" "48 176 -256" "classname" "item_rockets" } { "targetname" "t38" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*57" } //{ //"target" "t38" //"classname" "trigger_once" //"model" "*58" //} { "angle" "0" "origin" "144 -688 -40" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "192 904 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "1360 -80 24" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "208 104 -232" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-608 160 216" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "800 -976 -160" "classname" "weapon_rocketlauncher" } { "target" "t25" "classname" "trigger_teleport" "model" "*59" } { "light" "200" "origin" "882 -878 -92" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "714 -878 -92" "classname" "light_torch_small_walltorch" } { "sounds" "2" "angle" "90" "classname" "func_door_secret" "model" "*60" } { "classname" "light" "origin" "-512 64 56" "target" "t39" } { "classname" "info_null" "origin" "-628 68 -12" "targetname" "t39" } { "classname" "monster_zombie" "origin" "-736 64 -40" "angle" "0" } { "spawnflags" "256" "classname" "monster_wizard" "origin" "-384 -176 264" "angle" "270" } { "classname" "monster_ogre" "origin" "-914 -146 48" "targetname" "t10" } { "classname" "monster_ogre" "origin" "-914 -274 48" "targetname" "t10" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-770 -146 48" "targetname" "t10" } { "classname" "monster_ogre" "origin" "-770 -274 48" "targetname" "t10" "spawnflags" "768" } { "targetname" "t10" "classname" "trigger_teleport" "target" "t43" "spawnflags" "2" "model" "*61" } { "targetname" "t10" "classname" "trigger_teleport" "target" "t42" "spawnflags" "2" "model" "*62" } { "classname" "trigger_teleport" "target" "t40" "targetname" "t10" "spawnflags" "2" "model" "*63" } { "targetname" "t10" "classname" "trigger_teleport" "target" "t41" "spawnflags" "2" "model" "*64" } { "classname" "info_teleport_destination" "origin" "-200 -128 -56" "angle" "180" "targetname" "t41" } { "classname" "info_teleport_destination" "origin" "-256 96 -56" "angle" "270" "targetname" "t43" } { "classname" "info_teleport_destination" "origin" "176 744 8" "angle" "270" "targetname" "t42" } { "classname" "info_teleport_destination" "origin" "-568 -248 -56" "angle" "0" "targetname" "t40" } { "classname" "monster_ogre" "origin" "254 -846 184" "angle" "0" "targetname" "t35" "spawnflags" "257" } { "classname" "monster_ogre" "origin" "590 -538 184" "angle" "180" "targetname" "t35" } { "classname" "func_door" "angle" "-2" "health" "1" "model" "*65" } { "classname" "trigger_teleport" "target" "t45" "model" "*66" } { "classname" "info_teleport_destination" "origin" "416 -352 176" "angle" "270" "targetname" "t45" } { "classname" "item_rockets" "origin" "16 -904 160" } { "classname" "item_shells" "origin" "656 -816 160" } { "map" "e3m3" "classname" "trigger_changelevel" "model" "*67" } { "target" "t8" "classname" "trigger_once" "model" "*68" } { "classname" "light" "origin" "1744 496 88" } { "classname" "light" "origin" "1848 496 128" } { "classname" "light" "origin" "400 -1536 -184" "light" "150" "target" "t49" "style" "2" } { "classname" "light" "origin" "768 192 128" } { "classname" "light" "origin" "792 -264 128" } { "classname" "light" "origin" "1360 -368 128" } { "classname" "light" "origin" "1360 200 128" } { "classname" "light" "origin" "1288 -80 128" } { "classname" "light" "origin" "856 -80 128" } { "classname" "light" "origin" "800 -640 -112" "light" "100" } { "classname" "light" "origin" "800 -784 -120" "light" "100" } { "classname" "light" "origin" "1168 192 -160" } { "classname" "light" "origin" "976 -320 -160" } { "light" "150" "origin" "552 152 -192" "classname" "light" } { "light" "200" "origin" "256 -576 -248" "classname" "light" } { "sounds" "1" "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "2064" "model" "*69" } { "sounds" "1" "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "2056" "model" "*70" } { "spawnflags" "2048" "classname" "item_key2" "origin" "976 -160 -184" "sounds" "2" } { "classname" "item_health" "origin" "176 -360 -64" } { "classname" "item_health" "origin" "176 -416 -64" } { "classname" "light" "origin" "-152 512 112" "light" "200" } { "light" "150" "origin" "536 512 112" "classname" "light" } { "light" "150" "origin" "192 872 112" "classname" "light" } { "classname" "light" "origin" "392 736 8" "light" "200" } { "classname" "light" "origin" "312 736 88" "target" "t46" "style" "2" } { "classname" "info_null" "origin" "380 732 44" "targetname" "t46" } { "classname" "light" "origin" "480 512 -144" } { "classname" "light" "origin" "480 656 80" "light" "150" } { "classname" "light" "origin" "480 624 -64" "light" "200" } { "classname" "light" "origin" "-384 -104 64" "target" "t47" "style" "2" } { "classname" "info_null" "origin" "-380 -60 4" "targetname" "t47" } { "classname" "func_door" "angle" "-1" "targetname" "t36" "sounds" "3" "model" "*71" } { "angle" "90" "origin" "-384 48 264" "classname" "monster_wizard" } { "classname" "light" "origin" "-384 -232 168" "light" "150" } { "light" "150" "origin" "-384 -128 168" "classname" "light" } { "classname" "light" "origin" "-384 -8 168" "light" "150" } { "light" "150" "origin" "-376 80 168" "classname" "light" } { "classname" "light" "origin" "-376 176 168" "light" "150" } { "spawnflags" "769" "angle" "0" "origin" "102 -834 184" "classname" "monster_ogre" "targetname" "t35" } { "classname" "trigger_secret" "model" "*72" } { "classname" "trigger_secret" "model" "*73" } { "classname" "info_null" "origin" "572 -1276 -228" "targetname" "t48" } { "classname" "light" "origin" "512 -1272 -184" "target" "t48" "style" "2" } { "classname" "info_null" "origin" "444 -1532 -228" "targetname" "t49" } { "classname" "light" "origin" "176 -1536 104" } { "origin" "328 -1536 104" "classname" "light" } { "classname" "light" "origin" "192 -1440 104" } { "classname" "light" "origin" "456 -1536 -272" "light" "200" } { "classname" "func_door" "angle" "90" "wait" "-1" "sounds" "4" "model" "*74" } { "message" "This door is opened elsewhere..." "sounds" "1" "classname" "func_door" "angle" "270" "targetname" "t24" "wait" "-1" "model" "*75" } { "classname" "light" "origin" "-96 -1280 -136" "light" "200" } { "classname" "light" "origin" "-40 -1288 -216" "light" "200" } { "classname" "info_null" "origin" "188 -988 -212" "targetname" "t50" } { "classname" "light" "origin" "328 -960 -192" "light" "200" } { "light" "200" "origin" "48 -952 -192" "classname" "light" } { "classname" "info_null" "origin" "1068 -76 12" "targetname" "t51" } { "classname" "light" "origin" "1080 -88 72" "style" "2" "target" "t51" } { "classname" "info_null" "origin" "1076 -204 52" "targetname" "t52" } { "classname" "light" "origin" "1072 -144 88" "target" "t52" "style" "2" } { "classname" "light" "origin" "968 16 -104" "target" "t53" "style" "2" } { "classname" "info_null" "origin" "1172 236 -148" "targetname" "t54" } { "classname" "light" "origin" "1176 168 -112" "style" "2" "target" "t54" } { "classname" "light" "origin" "96 1056 112" "light" "250" } { "light" "250" "origin" "288 1056 112" "classname" "light" } { "classname" "trigger_monsterjump" "angle" "90" "model" "*76" } { "light" "200" "origin" "480 -384 -344" "classname" "light" } { "classname" "light" "origin" "608 -384 -344" "light" "200" } { "origin" "320 352 -256" "classname" "item_health" } { "classname" "item_health" "origin" "320 304 -256" } { "origin" "-624 -160 -64" "classname" "item_spikes" } { "origin" "-800 64 -40" "classname" "item_artifact_super_damage" } { "origin" "800 -1016 -136" "classname" "item_artifact_invisibility" "spawnflags" "2048" } { "light" "150" "origin" "800 -1024 -72" "classname" "light" } { "spawnflags" "1792" "classname" "func_wall" "model" "*77" } { "mangle" "20 315 0" "origin" "736 224 272" "classname" "info_intermission" } { "mangle" "5 40 0" "origin" "360 -664 48" "classname" "info_intermission" } { "origin" "992 -8 -208" "classname" "item_health" } { "classname" "item_health" "origin" "1136 -16 -208" } { "origin" "104 -952 160" "classname" "item_health" } { "classname" "item_health" "origin" "272 -952 160" } { "origin" "184 -968 160" "classname" "item_health" } { "spawnflags" "1" "origin" "272 976 0" "classname" "item_health" } { "classname" "item_health" "origin" "80 976 0" "spawnflags" "1" } { "classname" "trigger_secret" "model" "*78" } { "spawnflags" "2048" "wait" "5" "classname" "trigger_multiple" "message" "Walk through the rune gate to exit\nthe level" "model" "*79" } { "angle" "315" "origin" "112 1120 24" "classname" "info_player_coop" } { "angle" "225" "origin" "272 1120 24" "classname" "info_player_coop" } { "angle" "270" "origin" "192 1008 24" "classname" "info_player_coop" } { "classname" "monster_zombie" "origin" "192 -464 -40" "angle" "90" "spawnflags" "1280" } { "classname" "item_health" "origin" "-88 -1232 -288" } { "origin" "536 -1368 -288" "classname" "item_health" } { "classname" "item_spikes" "origin" "-88 -1368 -288" "spawnflags" "1" } { "classname" "item_spikes" "origin" "176 192 -256" } { "classname" "item_rockets" "origin" "752 112 0" "spawnflags" "1025" } { "classname" "monster_ogre" "origin" "1368 520 24" "angle" "270" "spawnflags" "256" } { "spawnflags" "768" "angle" "270" "origin" "1648 624 24" "classname" "monster_ogre" } { "classname" "item_health" "origin" "1648 368 16" } { "classname" "item_health" "origin" "1360 -240 16" } { "classname" "weapon_grenadelauncher" "origin" "192 800 0" "spawnflags" "3584" } { "classname" "item_artifact_super_damage" "origin" "480 176 24" "spawnflags" "3584" } { "spawnflags" "512" "targetname" "t29" "origin" "976 -80 -128" "classname" "monster_wizard" } { "targetname" "t29" "origin" "1168 -80 -128" "classname" "monster_wizard" } { "spawnflags" "1536" "targetname" "t29" "origin" "1152 -160 -184" "classname" "monster_demon1" } { "light" "150" "origin" "480 176 56" "classname" "light" } { "origin" "240 -128 -48" "classname" "light" "light" "125" } { "light" "125" "classname" "light" "origin" "144 -128 -48" } { "light" "125" "classname" "light" "origin" "48 -128 -48" } { "light" "125" "classname" "light" "origin" "-48 -128 -48" } { "classname" "light" "origin" "288 -928 72" "light" "200" } { "light" "200" "origin" "96 -928 72" "classname" "light" } { "classname" "light" "origin" "192 -88 -88" "target" "t55" "light" "250" } { "classname" "info_null" "origin" "192 -84 20" "targetname" "t55" } { "light" "250" "origin" "120 -88 -88" "classname" "light" "target" "t56" } { "origin" "120 -84 20" "classname" "info_null" "targetname" "t56" } { "classname" "light" "origin" "32 -88 -88" "light" "250" "target" "t57" } { "classname" "info_null" "origin" "32 -84 20" "targetname" "t57" } { "light" "250" "origin" "-48 -88 -88" "classname" "light" "target" "t58" } { "origin" "-48 -84 20" "classname" "info_null" "targetname" "t58" } { "classname" "light" "origin" "-48 -168 -88" "light" "250" "target" "t62" } { "classname" "info_null" "origin" "-48 -172 20" "targetname" "t62" } { "light" "250" "origin" "32 -168 -88" "classname" "light" "target" "t61" } { "origin" "32 -172 20" "classname" "info_null" "targetname" "t61" } { "classname" "light" "origin" "120 -168 -88" "light" "250" "target" "t60" } { "classname" "info_null" "origin" "120 -172 20" "targetname" "t60" } { "light" "250" "origin" "248 -128 -160" "classname" "light" "target" "t59" } { "origin" "252 -128 20" "classname" "info_null" "targetname" "t59" } { "light" "250" "origin" "0 -136 -160" "classname" "light" } { "spawnflags" "1" "origin" "176 -1176 0" "classname" "item_spikes" } { "light" "150" "origin" "576 512 56" "classname" "light" } { "light" "100" "origin" "880 112 88" "classname" "light" } { "classname" "light" "origin" "1072 112 88" "light" "100" } { "light" "100" "origin" "1264 112 88" "classname" "light" } { "classname" "light" "origin" "1264 -272 88" "light" "100" } { "light" "100" "origin" "1072 -272 88" "classname" "light" } { "classname" "light" "origin" "880 -272 88" "light" "100" } { "origin" "1248 96 0" "classname" "item_rockets" } { "origin" "752 -400 0" "classname" "item_spikes" } { "classname" "monster_zombie" "origin" "472 504 24" "angle" "180" "spawnflags" "768" } { "classname" "monster_zombie" "origin" "0 504 24" "angle" "0" "spawnflags" "768" } { "classname" "path_corner" "origin" "-224 136 -56" "targetname" "t64" "target" "t63" } { "origin" "-224 -224 -56" "classname" "path_corner" "targetname" "t63" "target" "t64" } { "classname" "monster_ogre" "origin" "-208 56 -40" "angle" "270" "target" "t63" "spawnflags" "768" } { "classname" "monster_wizard" "origin" "-560 216 48" "angle" "315" "spawnflags" "769" } { "classname" "item_spikes" "origin" "-576 -304 -64" "spawnflags" "768" } { "spawnflags" "768" "origin" "-528 -304 -64" "classname" "item_spikes" } { "classname" "monster_demon1" "origin" "192 -568 -232" "angle" "180" "target" "t27" "spawnflags" "1" } { "classname" "monster_demon1" "origin" "96 -856 -232" "angle" "45" "spawnflags" "1" } { "angle" "90" "origin" "248 -864 -232" "classname" "monster_demon1" "spawnflags" "769" } { "classname" "monster_demon1" "origin" "336 112 -232" "angle" "0" "targetname" "t38" "spawnflags" "768" } { "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t65" "target" "t66" "model" "*80" } { "classname" "monster_shambler" "origin" "1616 -200 24" "angle" "180" "spawnflags" "768" "targetname" "t65" } { "classname" "info_teleport_destination" "origin" "1360 184 8" "angle" "270" "targetname" "t66" } { "classname" "monster_demon1" "origin" "768 -200 32" "angle" "90" "spawnflags" "768" } { "classname" "item_shells" "origin" "1288 512 0" "spawnflags" "2816" } { "spawnflags" "2816" "origin" "1288 464 0" "classname" "item_shells" } { "classname" "item_rockets" "origin" "1168 88 -200" "spawnflags" "2816" } { "classname" "item_shells" "origin" "784 528 0" "spawnflags" "2816" } { "target" "t66" "classname" "trigger_teleport" "model" "*81" } //Q-Man { "classname" "item_flag_team1" "origin" "1075 -81 20" } { "classname" "info_player_team1" "origin" "1074 -179 16" "angle" "270" } { "classname" "info_player_team1" "origin" "191 761 24" "angle" "270" } { "classname" "info_player_team1" "origin" "886 -287 24" "angle" "90" } { "classname" "info_player_team1" "origin" "1074 96 24" "angle" "90" } { "classname" "info_player_team1" "origin" "1264 127 24" "angle" "270" } { "classname" "item_flag_team2" "origin" "193 319 -232" } { "classname" "info_player_team2" "origin" "194 220 -232" "angle" "90" } { "classname" "info_player_team2" "origin" "50 119 -232" "angle" "45" } { "classname" "info_player_team2" "origin" "196 80 -232" "angle" "90" } { "classname" "info_player_team2" "origin" "338 334 -232" "angle" "235" } { "classname" "info_player_team2" "origin" "363 80 -232" } { "classname" "weapon_rocketlauncher" "origin" "1676 498 24" } { "classname" "item_armor2" "origin" "337 736 24" } { "origin" "321 208 -232" "classname" "weapon_supershotgun" } { "origin" "192 -940 -232" "classname" "weapon_supernailgun" } { "origin" "-383 -243 232" "classname" "weapon_grenadelauncher" } { "classname" "item_spikes" "origin" "20 -750 -232" "spawnflags" "1" } //"origin" "194 1118 40" { "classname" "item_rockets" "origin" "56 -904 184" "spawnflags" "1" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m3.ent000066400000000000000000001006041475442401000251740ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/metal.wad" "angle" "180" "worldtype" "1" "sounds" "9" "message" "the Tomb of Terror" "targetname" "t41" } { "classname" "light" "origin" "720 -528 432" "light" "550" } { "classname" "info_player_start" "origin" "576 -152 48" "angle" "270" "targetname" "start1" } { "classname" "light" "origin" "576 -560 328" "light" "400" } { "classname" "light" "origin" "720 -592 432" "light" "550" } { "classname" "light" "origin" "432 -592 432" "light" "550" } { "classname" "light" "origin" "424 -528 432" "light" "550" } { "classname" "light" "origin" "432 -672 432" } { "classname" "light" "origin" "728 -672 432" } { "light" "550" "origin" "440 48 456" "classname" "light" } { "light" "550" "origin" "448 176 456" "classname" "light" } { "light" "550" "origin" "696 48 456" "classname" "light" } { "light" "550" "origin" "696 176 456" "classname" "light" } { "light" "200" "origin" "424 176 120" "classname" "light" } { "light" "200" "origin" "464 16 120" "classname" "light" } { "light" "200" "origin" "672 -16 120" "classname" "light" } { "light" "200" "origin" "728 176 120" "classname" "light" } { "light" "200" "origin" "576 -152 344" "classname" "light" } { "light" "200" "origin" "576 -224 344" "classname" "light" } { "light" "200" "origin" "576 -288 344" "classname" "light" } { "light" "200" "origin" "576 -360 344" "classname" "light" } { "sounds" "3" "spawnflags" "2048" "targetname" "t13" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*1" } { "light" "150" "origin" "576 -832 56" "classname" "light" } { "spawnflags" "2048" "angle" "270" "classname" "func_door" "targetname" "t14" "wait" "-1" "message" "This door is opened elsewhere..." "model" "*2" } { "angle" "90" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*3" } { "light" "300" "origin" "-128 -544 224" "classname" "light" } { "light" "300" "origin" "-128 -832 224" "classname" "light" } { "light" "300" "origin" "232 -536 224" "classname" "light" } { "light" "300" "origin" "232 -832 224" "classname" "light" } { "light" "400" "origin" "56 -784 424" "classname" "light" } { "light" "400" "origin" "48 -592 424" "classname" "light" } { "classname" "light" "origin" "-72 -640 0" "light" "150" } { "classname" "light" "origin" "-72 -784 0" "light" "150" } { "classname" "light" "origin" "136 -640 0" "light" "150" } { "classname" "light" "origin" "136 -784 0" "light" "150" } { "classname" "func_door" "angle" "-1" "targetname" "t2" "speed" "50" "sounds" "4" "model" "*4" } { "classname" "func_door" "targetname" "t2" "angle" "-1" "speed" "50" "sounds" "4" "model" "*5" } { "classname" "func_door" "angle" "-1" "targetname" "t2" "speed" "50" "sounds" "4" "model" "*6" } { "classname" "func_door" "targetname" "t2" "angle" "-1" "speed" "50" "sounds" "4" "model" "*7" } { "classname" "light" "origin" "40 -648 48" "light" "200" } { "classname" "func_button" "angle" "-2" "target" "t2" "wait" "7" "model" "*8" } { "classname" "light" "origin" "48 -992 232" } { "classname" "light" "origin" "-128 -1168 232" } { "classname" "light" "origin" "224 -1168 232" } { "classname" "light" "origin" "48 -1344 232" } { "classname" "light" "origin" "48 -1168 232" } { "classname" "func_door" "angle" "-1" "targetname" "t3" "wait" "-1" "model" "*9" } { "classname" "light" "origin" "-160 -1408 304" } { "classname" "light" "origin" "-528 -1088 440" "light" "400" } { "classname" "light" "origin" "-528 -1216 440" "light" "400" } { "origin" "-772 -1328 366" "classname" "light" "light" "400" } { "classname" "func_plat" "model" "*10" } { "classname" "light" "origin" "-672 -1364 100" "light" "200" } { "classname" "light" "origin" "-500 -1376 100" "light" "200" } { "classname" "light" "origin" "-676 -968 60" "light" "200" } { "classname" "light" "origin" "-668 -1140 92" "light" "200" } { "classname" "light" "origin" "-776 -1136 366" "light" "400" } { "classname" "func_door" "angle" "-1" "targetname" "t4" "speed" "250" "wait" "10" "model" "*11" } { "wait" "10" "speed" "250" "targetname" "t4" "angle" "90" "classname" "func_door" "model" "*12" } { "origin" "576 304 336" "classname" "light" } { "origin" "-656 184 32" "classname" "light" } { "origin" "-648 -184 32" "classname" "light" } { "origin" "-1024 184 32" "classname" "light" } { "origin" "-1008 -184 32" "classname" "light" } { "origin" "-832 0 184" "classname" "light" } { "origin" "-832 384 224" "classname" "light" } { "origin" "-1216 0 224" "classname" "light" } { "origin" "-448 32 224" "classname" "light" } { "light" "600" "origin" "-832 0 504" "classname" "light" } { "light" "400" "origin" "-576 -704 424" "classname" "light" } { "light" "400" "origin" "-816 -704 424" "classname" "light" } { "light" "400" "origin" "-832 -624 424" "classname" "light" } { "light" "400" "origin" "-688 -704 424" "classname" "light" } { "light" "400" "origin" "-528 -800 424" "classname" "light" } { "wait" "-1" "spawnflags" "1" "targetname" "t5" "angle" "270" "classname" "func_door" "sounds" "3" "speed" "200" "model" "*13" } { "wait" "-1" "spawnflags" "1" "targetname" "t6" "angle" "180" "classname" "func_door" "sounds" "3" "speed" "200" "model" "*14" } { "wait" "-1" "spawnflags" "1" "targetname" "t6" "angle" "0" "classname" "func_door" "sounds" "3" "speed" "200" "model" "*15" } { "targetname" "t73" "wait" "-1" "spawnflags" "1" "angle" "90" "classname" "func_door" "sounds" "3" "speed" "200" "model" "*16" } { "target" "t5" "angle" "-2" "classname" "func_button" "wait" "-1" "model" "*17" } { "target" "t6" "angle" "-2" "classname" "func_button" "wait" "-1" "model" "*18" } { "angle" "-2" "target" "t8" "classname" "func_button" "wait" "12" "model" "*19" } { "target" "t8" "angle" "-2" "classname" "func_button" "wait" "12" "model" "*20" } { "classname" "light" "origin" "-832 -352 224" } //{ //"classname" "func_train" //"wait" "13" //"spawnflags" "1" //"target" "t64" //"sounds" "1" //"speed" "50" //"targetname" "t6" //"dmg" "30" //"model" "*21" //} { "classname" "monster_ogre" "origin" "430 -434 24" "angle" "270" "target" "t9" } { "classname" "path_corner" "origin" "424 -784 8" "angle" "0" "targetname" "t9" "target" "t10" } { "classname" "path_corner" "origin" "744 -792 8" "angle" "90" "targetname" "t10" "target" "t11" } { "classname" "path_corner" "origin" "728 -312 8" "angle" "180" "targetname" "t11" "target" "t12" } { "classname" "path_corner" "origin" "416 -320 8" "angle" "270" "targetname" "t12" "target" "t9" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t13" "model" "*22" } { "spawnflags" "2048" "classname" "func_button" "angle" "90" "target" "t14" "wait" "-1" "model" "*23" } { "classname" "light" "origin" "192 -256 128" } { "classname" "monster_hell_knight" "origin" "238 -266 24" "target" "t15" "angle" "0" } { "classname" "path_corner" "origin" "704 -256 8" "angle" "180" "targetname" "t15" "target" "t16" } { "classname" "path_corner" "origin" "288 -256 8" "targetname" "t16" "target" "t15" } { "classname" "monster_ogre" "origin" "46 -818 96" "target" "t17" "spawnflags" "768" } { "classname" "path_corner" "origin" "48 -1080 80" "angle" "90" "targetname" "t18" "target" "t17" } { "classname" "path_corner" "origin" "48 -880 80" "angle" "270" "targetname" "t17" "target" "t18" } { "classname" "monster_zombie" "origin" "-160 -1440 96" "targetname" "t3" } { "classname" "monster_zombie" "origin" "-160 -1488 96" "angle" "90" "targetname" "t3" } { "classname" "trigger_once" "target" "t3" "model" "*24" } { "origin" "696 -136 0" "classname" "item_shells" } { "origin" "440 -136 0" "classname" "item_health" } { "angle" "180" "origin" "232 -1168 96" "classname" "monster_zombie" "targetname" "t37" } { "origin" "-136 -1504 80" "classname" "item_spikes" } { "origin" "-216 -1504 80" "classname" "item_health" } { "origin" "48 -1624 72" "classname" "item_health" } { "origin" "-456 -984 72" "classname" "item_shells" } { "spawnflags" "1" "origin" "168 -1212 76" "classname" "item_shells" } { "target" "t24" "origin" "-776 -1392 168" "classname" "monster_hell_knight" "spawnflags" "1" } { "target" "t24" "targetname" "t25" "angle" "270" "origin" "-768 -960 152" "classname" "path_corner" } { "target" "t25" "targetname" "t24" "angle" "90" "origin" "-768 -1352 152" "classname" "path_corner" } { "target" "t26" "origin" "-528 -976 248" "classname" "monster_zombie" } { "target" "t26" "targetname" "t27" "angle" "90" "origin" "-528 -1480 232" "classname" "path_corner" } { "target" "t27" "targetname" "t26" "angle" "270" "origin" "-528 -1032 232" "classname" "path_corner" } { "angle" "90" "origin" "-776 -1472 168" "classname" "monster_hell_knight" "spawnflags" "768" } { "classname" "light" "origin" "432 -816 64" "light" "200" } { "classname" "light" "origin" "720 -816 64" "light" "200" } { "classname" "light" "origin" "-128 -640 224" } { "classname" "light" "origin" "-128 -736 224" } { "classname" "light" "origin" "232 -640 224" } { "classname" "light" "origin" "232 -736 224" } { "classname" "light" "origin" "48 -1608 224" "light" "300" } { "classname" "light" "origin" "48 -1608 120" "light" "150" } { "classname" "light" "origin" "48 -1344 120" "light" "150" } { "classname" "light" "origin" "224 -1168 112" "light" "150" } { "classname" "light" "origin" "-160 -1168 120" "light" "150" } { "classname" "light" "origin" "48 -992 120" "light" "150" } { "classname" "light" "origin" "-528 -904 272" "light" "150" } { "classname" "light" "origin" "-792 -704 184" "light" "150" } { "classname" "light" "origin" "-512 -672 280" "light" "100" } { "classname" "light" "origin" "-824 -552 280" "light" "150" } //{ //"classname" "trigger_teleport" //"target" "t28" //"model" "*25" //} { "classname" "light" "origin" "-832 592 208" "light" "200" } { "classname" "info_teleport_destination" "origin" "576 -152 40" "targetname" "t28" "angle" "270" } { "classname" "light" "origin" "584 -576 120" "light" "200" } { "classname" "light" "origin" "112 -424 88" "light" "200" } { "classname" "light" "origin" "576 416 336" "light" "200" } { "spawnflags" "2048" "sounds" "2" "classname" "item_key1" "origin" "576 640 24" } { "classname" "trigger_multiple" "target" "t29" "wait" "1" "model" "*26" } //{ //"classname" "trap_spikeshooter" //"origin" "-512 -1328 216" //"angle" "-1" //"targetname" "t29" //"delay" "1" //"spawnflags" "1" //} //{ //"classname" "trap_spikeshooter" //"origin" "-552 -1328 216" //"angle" "-1" //"targetname" "t29" //"delay" "1" //"spawnflags" "1" //} //{ //"delay" "1" //"angle" "-1" //"origin" "-544 -1168 216" //"classname" "trap_spikeshooter" //"targetname" "t29" //"spawnflags" "1" //} //{ //"classname" "trap_spikeshooter" //"origin" "-504 -1168 216" //"angle" "-1" //"delay" "1" //"targetname" "t29" //"spawnflags" "1" //} //{ //"delay" "1" //"angle" "-1" //"origin" "-544 -1008 216" //"classname" "trap_spikeshooter" //"targetname" "t29" //"spawnflags" "1" //} //{ //"classname" "trap_spikeshooter" //"origin" "-504 -1008 216" //"angle" "-1" //"delay" "1" //"targetname" "t29" //"spawnflags" "1" //} { "classname" "monster_wizard" "origin" "-832 0 304" "angle" "270" } { "classname" "trigger_teleport" "target" "t30" "targetname" "t6" "spawnflags" "2" "model" "*27" } { "classname" "trigger_teleport" "target" "t31" "targetname" "t6" "spawnflags" "2" "model" "*28" } { "classname" "trigger_teleport" "target" "t32" "targetname" "t6" "spawnflags" "2" "model" "*29" } { "classname" "monster_zombie" "origin" "-1504 -480 24" "targetname" "t6" "angle" "90" "spawnflags" "512" } { "classname" "monster_zombie" "origin" "-1272 -496 24" "targetname" "t6" "angle" "90" "spawnflags" "512" } { "classname" "info_teleport_destination" "origin" "-832 -400 160" "angle" "90" "targetname" "t31" } { "classname" "info_teleport_destination" "origin" "-968 -384 160" "angle" "90" "targetname" "t30" } { "classname" "info_teleport_destination" "origin" "-664 -384 160" "angle" "90" "targetname" "t32" } { "classname" "trap_spikeshooter" "origin" "392 -32 216" "spawnflags" "1" "angle" "0" "targetname" "t34" } { "angle" "0" "spawnflags" "1" "origin" "392 48 216" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "trap_spikeshooter" "origin" "392 112 216" "spawnflags" "1" "angle" "0" "targetname" "t34" } { "angle" "0" "spawnflags" "1" "origin" "392 176 216" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "trap_spikeshooter" "origin" "760 -32 216" "angle" "180" "targetname" "t34" } { "angle" "180" "origin" "760 48 216" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "trap_spikeshooter" "origin" "760 112 216" "angle" "180" "targetname" "t34" } { "angle" "180" "origin" "760 176 216" "classname" "trap_spikeshooter" "targetname" "t34" } { "classname" "trigger_multiple" "wait" "1" "target" "t34" "model" "*30" } { "classname" "func_button" "angle" "-2" "target" "t4" "wait" "10" "model" "*31" } { "classname" "light" "origin" "-1376 -592 112" } { "classname" "light" "origin" "-1248 -592 112" } { "classname" "light" "origin" "-1504 -592 112" } { "classname" "light" "origin" "-680 -864 28" "light" "200" } { "light" "600" "origin" "1272 -24 320" "classname" "light" } { "light" "600" "origin" "1304 416 320" "classname" "light" } { "light" "600" "origin" "1368 272 320" "classname" "light" } { "origin" "1328 144 -240" "classname" "light" } { "origin" "1352 328 -240" "classname" "light" } { "origin" "1344 256 224" "classname" "light" } { "light" "600" "origin" "1424 48 328" "classname" "light" } { "origin" "1376 48 168" "classname" "light" } { "light" "100" "origin" "1232 320 -72" "classname" "light" } { "light" "100" "origin" "1232 152 8" "classname" "light" } { "wait" "-1" "classname" "func_button" "angle" "270" "target" "t42" "model" "*32" } { "classname" "light" "origin" "1432 392 -64" } { "targetname" "t41" "classname" "func_door" "angle" "90" "wait" "-1" "model" "*33" } { "classname" "light" "origin" "1456 272 -216" "light" "200" } { "classname" "light" "origin" "1296 0 -216" "light" "200" } { "wait" "-1" "classname" "func_door" "lip" "-10" "speed" "300" "angle" "-2" "targetname" "t36" "model" "*34" } { "classname" "trigger_once" "target" "t36" "model" "*35" } { "classname" "trigger_once" "target" "t37" "model" "*36" } { "classname" "monster_zombie" "origin" "-160 -1568 96" "angle" "270" } { "classname" "light" "origin" "1360 -136 48" "light" "600" } { "classname" "light" "origin" "1400 -176 48" "light" "600" } { "light" "200" "origin" "1232 -184 -192" "classname" "light" } { "target" "t38" "light" "400" "origin" "1088 288 -16" "classname" "light" } { "target" "t39" "light" "400" "origin" "1088 160 -16" "classname" "light" } { "target" "t40" "light" "400" "origin" "1088 32 -16" "classname" "light" } { "light" "200" "origin" "1088 352 -112" "classname" "light" } { "light" "200" "origin" "1088 -64 -112" "classname" "light" } { "targetname" "t38" "origin" "1028 284 -252" "classname" "info_null" } { "targetname" "t39" "origin" "1028 156 -252" "classname" "info_null" } { "targetname" "t40" "origin" "1028 28 -252" "classname" "info_null" } { "targetname" "t42" "angle" "90" "origin" "1382 -146 -232" "classname" "monster_ogre" } { "spawnflags" "256" "targetname" "t42" "angle" "90" "origin" "1238 -170 -232" "classname" "monster_ogre" } { "angle" "270" "origin" "1110 -282 -232" "classname" "monster_ogre" } { "wait" "-1" "target" "t41" "angle" "270" "classname" "func_button" "model" "*37" } { "targetname" "t42" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*38" } { "wait" "-1" "targetname" "t42" "angle" "-1" "classname" "func_door" "model" "*39" } //{ //"angle" "-1" //"wait" "-1" //"targetname" "t42" //"classname" "func_door" //"model" "*40" //} { "target" "t43" "classname" "trigger_once" "model" "*41" } { "targetname" "t43" "wait" "-1" "angle" "180" "classname" "func_door" "model" "*42" } { "origin" "1752 400 -64" "classname" "light" } { "light" "100" "origin" "1800 528 -56" "classname" "light" } { "light" "100" "origin" "1800 272 -56" "classname" "light" } { "origin" "1832 400 -80" "classname" "light" } { "origin" "1832 400 -8" "classname" "light" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "1622 446 -104" "angle" "180" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "-826 -706 168" "angle" "0" } { "classname" "trigger_teleport" "target" "t45" "targetname" "t47" "spawnflags" "2" "model" "*43" } { "classname" "trigger_teleport" "target" "t46" "targetname" "t47" "spawnflags" "2" "model" "*44" } { "classname" "monster_zombie" "origin" "-1256 -680 24" "angle" "90" "targetname" "t47" } { "classname" "monster_zombie" "origin" "-1512 -688 24" "angle" "90" "targetname" "t47" } { "angle" "270" "classname" "info_teleport_destination" "origin" "-832 416 152" "targetname" "t45" } { "angle" "270" "classname" "info_teleport_destination" "origin" "-976 376 152" "targetname" "t44" } { "angle" "270" "classname" "info_teleport_destination" "origin" "-696 376 152" "targetname" "t46" } { "classname" "trigger_once" "target" "t47" "model" "*45" } { "classname" "monster_hell_knight" "origin" "-522 -994 96" "angle" "270" "targetname" "t48" "spawnflags" "257" } { "classname" "trigger_once" "target" "t48" "model" "*46" } { "classname" "item_health" "origin" "-688 -896 -96" "spawnflags" "2" } { "spawnflags" "3072" "classname" "item_health" "origin" "-1096 312 144" } { "classname" "item_health" "origin" "-632 336 144" } { "classname" "item_shells" "origin" "-800 -64 144" } { "classname" "item_health" "origin" "824 -272 0" } { "classname" "item_health" "origin" "864 -272 0" } { "classname" "item_health" "origin" "1072 -136 -256" } { "classname" "trigger_teleport" "target" "t44" "targetname" "t47" "spawnflags" "2" "model" "*47" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "430 -746 168" "angle" "90" } { "classname" "trigger_changelevel" "map" "e3m4" "model" "*48" } { "sounds" "4" "spawnflags" "2064" "wait" "-1" "classname" "func_door" "angle" "270" "model" "*49" } { "spawnflags" "2048" "wait" "-1" "classname" "func_door" "angle" "90" "model" "*50" } { "light" "150" "origin" "752 -256 40" "classname" "light" } { "classname" "light" "origin" "416 -256 40" "light" "150" } { "origin" "40 -592 -128" "classname" "light" } { "origin" "40 -720 -128" "classname" "light" } { "origin" "8 -656 -128" "classname" "light" } { "classname" "light" "origin" "88 -696 -128" } { "angle" "90" "target" "t52" "origin" "408 -120 24" "classname" "light" } { "targetname" "t52" "origin" "388 -100 140" "classname" "info_null" } { "light" "150" "origin" "424 -136 24" "classname" "light" } { "target" "t53" "angle" "90" "origin" "744 -120 8" "classname" "light" } { "targetname" "t53" "origin" "764 -100 140" "classname" "info_null" } { "light" "150" "origin" "728 -136 24" "classname" "light" } { "light" "200" "style" "2" "target" "t54" "origin" "576 -776 64" "classname" "light" } { "targetname" "t54" "origin" "580 -708 44" "classname" "info_null" } { "light" "200" "origin" "576 -696 8" "classname" "light" } { "light" "550" "origin" "720 -464 432" "classname" "light" } { "classname" "light" "origin" "424 -464 432" "light" "550" } { "classname" "light" "origin" "520 -408 24" "light" "150" } { "light" "150" "origin" "632 -408 24" "classname" "light" } { "targetname" "t56" "origin" "660 -444 140" "classname" "info_null" } { "targetname" "t55" "origin" "492 -444 140" "classname" "info_null" } { "target" "t56" "origin" "656 -424 8" "classname" "light" } { "target" "t55" "classname" "light" "origin" "496 -424 8" } { "light" "150" "origin" "576 -152 32" "classname" "light" } { "light" "150" "origin" "576 -272 136" "classname" "light" } { "target" "t57" "origin" "-368 -944 86" "classname" "light" } { "targetname" "t57" "origin" "-388 -956 170" "classname" "info_null" } { "light" "150" "origin" "-400 -968 94" "classname" "light" } { "targetname" "t58" "origin" "-388 -1380 170" "classname" "info_null" } { "light" "150" "origin" "-400 -1360 94" "classname" "light" } { "target" "t58" "origin" "-368 -1392 86" "classname" "light" } { "light" "200" "origin" "-432 -1168 128" "classname" "light" } { "origin" "-744 -960 262" "classname" "light" } { "light" "200" "origin" "-524 -960 100" "classname" "light" } { "angle" "90" "target" "t59" "origin" "400 -848 160" "classname" "light" } { "angle" "90" "target" "t60" "origin" "752 -848 160" "classname" "light" } { "targetname" "t59" "origin" "388 -860 268" "classname" "info_null" } { "targetname" "t60" "classname" "info_null" "origin" "764 -860 268" } { "light" "150" "origin" "432 -816 192" "classname" "light" } { "classname" "light" "origin" "720 -816 192" "light" "150" } { "light" "150" "origin" "848 -208 32" "classname" "light" } { "light" "150" "origin" "848 -304 32" "classname" "light" } { "classname" "light" "origin" "976 -208 32" "light" "150" } { "light" "150" "origin" "976 -304 32" "classname" "light" } { "light" "150" "origin" "1080 -312 96" "classname" "light" } { "classname" "light" "origin" "1080 -200 96" "light" "150" } { "light" "150" "origin" "1192 -200 96" "classname" "light" } { "classname" "light" "origin" "1200 -312 96" "light" "150" } { "light" "150" "origin" "1272 -264 96" "classname" "light" } { "classname" "light" "origin" "1272 -128 96" "light" "150" } { "light" "150" "origin" "1192 -128 96" "classname" "light" } { "message" "This door is opened elsewhere..." "wait" "-1" "angle" "270" "classname" "func_door" "model" "*51" } { "speed" "250" "origin" "200 -824 -8" "classname" "misc_fireball" } { "classname" "misc_fireball" "origin" "-88 -824 -8" "speed" "250" } { "speed" "250" "origin" "-88 -664 -8" "classname" "misc_fireball" } { "classname" "misc_fireball" "origin" "216 -568 -8" "speed" "250" } { "targetname" "t62" "sounds" "4" "angle" "270" "classname" "func_door" "model" "*52" } { "origin" "-232 -832 64" "classname" "light" } { "target" "t61" "classname" "trigger_teleport" "model" "*53" } { "targetname" "t61" "angle" "270" "origin" "-64 -592 256" "classname" "info_teleport_destination" } { "target" "t62" "health" "1" "angle" "180" "classname" "func_button" "model" "*54" } { "classname" "trigger_secret" "model" "*55" } { "origin" "160 -688 240" "classname" "item_armorInv" } { "light" "150" "origin" "-456 -1024 280" "classname" "light" } { "classname" "light" "origin" "-456 -1112 280" "light" "150" } { "light" "150" "origin" "-456 -1192 280" "classname" "light" } { "classname" "light" "origin" "-456 -1312 280" "light" "150" } { "light" "150" "origin" "-600 -1312 280" "classname" "light" } { "classname" "light" "origin" "-600 -1192 280" "light" "150" } { "light" "150" "origin" "-600 -1112 280" "classname" "light" } { "classname" "light" "origin" "-600 -1024 280" "light" "150" } { "light" "200" "origin" "-768 -1488 352" "classname" "light" } { "light" "200" "classname" "light" "origin" "-536 -1488 352" } { "light" "200" "origin" "-640 -1488 352" "classname" "light" } { "light" "150" "origin" "-728 -1488 288" "classname" "light" } { "classname" "light" "origin" "-568 -1488 288" "light" "150" } { "light" "200" "origin" "-768 -1488 192" "classname" "light" } { "spawnflags" "256" "classname" "monster_hell_knight" "origin" "1232 -112 168" "angle" "90" } { "classname" "trigger_teleport" "target" "t28" "model" "*56" } { "classname" "light" "origin" "576 648 64" } { "origin" "576 344 112" "classname" "light" } { "mangle" "30 315 0" "origin" "416 208 296" "classname" "info_intermission" } { "classname" "item_health" "origin" "1032 -288 -256" } { "classname" "func_wall" "spawnflags" "1792" "model" "*57" } { "classname" "info_player_coop" "origin" "464 -168 24" "angle" "270" } { "angle" "270" "origin" "688 -168 24" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "728 -224 24" "angle" "270" } { "angle" "270" "origin" "432 -232 24" "classname" "info_player_coop" } { "spawnflags" "2" "origin" "560 -824 144" "classname" "item_health" } { "origin" "48 -1168 72" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "classname" "weapon_rocketlauncher" "origin" "-64 -688 240" } { "classname" "trigger_secret" "model" "*58" } { "spawnflags" "2304" "origin" "-536 -280 144" "classname" "item_health" } { "spawnflags" "1024" "classname" "item_health" "origin" "-1136 -296 144" } { "spawnflags" "1792" "origin" "576 640 24" "classname" "item_artifact_invisibility" } { "angle" "90" "origin" "576 -392 200" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "576 -256 176" "classname" "weapon_supernailgun" } { "light" "125" "origin" "576 -152 48" "classname" "light" } { "light" "125" "origin" "576 -152 208" "classname" "light" } { "angle" "270" "origin" "576 -216 32" "classname" "info_player_deathmatch" } { "angle" "45" "origin" "-608 -1320 96" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-528 -1496 248" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-728 392 168" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "1232 -120 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "1456 312 -232" "classname" "info_player_deathmatch" } //{ //"origin" "1392 -176 -256" //"classname" "weapon_rocketlauncher" //"spawnflags" "1792" //} //{ //"spawnflags" "1792" //"origin" "1584 520 -128" //"classname" "item_armor2" //} { "classname" "path_corner" "origin" "-1376 -64 220" "target" "t63" "targetname" "t64" } { "classname" "path_corner" "origin" "-1376 -64 136" "targetname" "t63" "target" "t64" } //{ //"speed" "50" //"sounds" "1" //"spawnflags" "1" //"wait" "13" //"classname" "func_train" //"target" "t65" //"targetname" "t6" //"dmg" "30" //"model" "*59" //} { "origin" "-400 -64 220" "classname" "path_corner" "targetname" "t65" "target" "t66" } { "origin" "-400 -64 136" "classname" "path_corner" "targetname" "t66" "target" "t65" } { "classname" "item_armor2" "origin" "184 -216 0" } { "classname" "item_health" "origin" "128 -392 0" "spawnflags" "1" } { "spawnflags" "1" "origin" "80 -440 0" "classname" "item_health" } { "classname" "monster_hell_knight" "origin" "48 -920 96" "angle" "90" "spawnflags" "1280" "target" "t17" } { "classname" "item_rockets" "origin" "0 -1624 72" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-624 -1080 72" } { "origin" "-624 -1128 72" "classname" "item_spikes" } { "classname" "weapon_supershotgun" "origin" "-528 -1216 224" "spawnflags" "1792" } { "classname" "item_health" "origin" "-520 -680 224" "spawnflags" "1" } { "spawnflags" "1" "origin" "-568 -680 224" "classname" "item_health" } { "classname" "item_spikes" "origin" "-472 8 144" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-1224 -40 144" } { "classname" "monster_wizard" "origin" "-1168 -976 184" "angle" "90" "targetname" "t8" "spawnflags" "256" } { "angle" "90" "origin" "-1088 -976 184" "classname" "monster_wizard" "targetname" "t8" "spawnflags" "768" } { "classname" "monster_wizard" "origin" "-1008 -976 184" "angle" "90" "targetname" "t8" } { "classname" "trigger_teleport" "targetname" "t8" "target" "t69" "spawnflags" "2" "model" "*60" } { "classname" "trigger_teleport" "targetname" "t8" "target" "t68" "spawnflags" "2" "model" "*61" } { "classname" "trigger_teleport" "targetname" "t8" "target" "t67" "spawnflags" "2" "model" "*62" } { "classname" "info_teleport_destination" "origin" "-832 -264 336" "angle" "90" "targetname" "t67" } { "angle" "270" "origin" "-824 256 336" "classname" "info_teleport_destination" "targetname" "t69" } { "classname" "info_teleport_destination" "origin" "-1032 224 336" "angle" "315" "targetname" "t68" } { "spawnflags" "1" "angle" "270" "origin" "576 -384 200" "classname" "monster_hell_knight" } { "spawnflags" "1" "origin" "600 328 64" "classname" "item_health" } { "spawnflags" "1" "origin" "520 328 64" "classname" "item_spikes" } { "origin" "-880 -560 144" "classname" "item_spikes" } { "angle" "270" "origin" "1232 -56 24" "classname" "monster_hell_knight" "spawnflags" "768" } { "spawnflags" "256" "targetname" "t6" "angle" "90" "origin" "-1376 -472 24" "classname" "monster_hell_knight" } { "origin" "1240 -312 8" "classname" "item_rockets" } { "targetname" "t71" "target" "t70" "origin" "1312 112 -56" "classname" "path_corner" } { "target" "t71" "targetname" "t70" "classname" "path_corner" "origin" "1312 304 -56" } { "target" "t70" "angle" "90" "origin" "1312 192 -40" "classname" "monster_wizard" } { "origin" "1312 408 -256" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "1360 408 -256" } { "targetname" "t42" "angle" "0" "origin" "1088 -32 -232" "classname" "monster_hell_knight" } { "origin" "1192 -248 -256" "classname" "item_shells" } { "origin" "1552 264 -128" "classname" "item_health" } { "angle" "90" "origin" "710 -746 168" "classname" "monster_ogre" "spawnflags" "768" } { "spawnflags" "3584" "origin" "656 -136 0" "classname" "item_spikes" } { "angle" "270" "origin" "-536 -864 248" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "-552 -1128 248" "angle" "270" } { "target" "t73" "targetname" "t8" "classname" "trigger_counter" "model" "*63" } { "spawnflags" "2561" "origin" "1192 -312 8" "classname" "item_spikes" } { "spawnflags" "3584" "origin" "1032 80 -256" "classname" "item_spikes" } { "spawnflags" "1536" "angle" "180" "origin" "1568 448 -104" "classname" "monster_hell_knight" } { "spawnflags" "1" "origin" "1312 472 -128" "classname" "item_shells" } { "classname" "monster_demon1" "origin" "944 -256 24" "angle" "180" } { "classname" "monster_wizard" "origin" "-832 -312 320" "angle" "90" "spawnflags" "769" } { "classname" "monster_demon1" "origin" "-1376 -656 24" "angle" "90" "targetname" "t47" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "-168 -1168 96" "angle" "0" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "576 600 24" "angle" "270" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "1360 16 -232" "angle" "90" } { "classname" "monster_hell_knight" "origin" "1232 424 -104" "angle" "270" "spawnflags" "768" } { "classname" "trigger_teleport" "target" "t74" "spawnflags" "2" "targetname" "t41" "model" "*64" } { "classname" "trigger_teleport" "target" "t75" "spawnflags" "2" "targetname" "t41" "model" "*65" } { "classname" "trigger_teleport" "target" "t76" "spawnflags" "2" "targetname" "t41" "model" "*66" } { "classname" "monster_wizard" "origin" "1184 720 -96" "angle" "270" "spawnflags" "768" } { "angle" "270" "origin" "1248 720 -96" "classname" "monster_wizard" } { "classname" "monster_wizard" "origin" "1312 720 -96" "angle" "270" "spawnflags" "768" } { "classname" "info_teleport_destination" "origin" "1448 432 -40" "angle" "270" "targetname" "t75" } { "angle" "270" "origin" "1240 384 40" "classname" "info_teleport_destination" "targetname" "t74" } { "classname" "info_teleport_destination" "origin" "1424 64 -104" "angle" "225" "targetname" "t76" } { "classname" "monster_ogre" "origin" "1088 256 -232" "angle" "0" "targetname" "t42" "spawnflags" "768" } { "classname" "item_shells" "origin" "1032 344 -256" } { "classname" "item_shells" "origin" "1192 24 0" "spawnflags" "2817" } { "classname" "trigger_teleport" "spawnflags" "2" "target" "t77" "targetname" "t78" "model" "*67" } { "classname" "info_teleport_destination" "origin" "-536 -744 240" "angle" "270" "targetname" "t77" } { "classname" "trigger_once" "target" "t78" "model" "*68" } { "classname" "monster_hell_knight" "origin" "-408 -1328 96" "angle" "90" "spawnflags" "769" } { "targetname" "t78" "spawnflags" "768" "angle" "270" "origin" "-408 -512 248" "classname" "monster_hell_knight" } { "spawnflags" "1792" "origin" "1280 456 -128" "classname" "weapon_supershotgun" } { "classname" "weapon_grenadelauncher" "origin" "-832 384 144" "spawnflags" "1792" } { "spawnflags" "2049" "origin" "-816 -968 144" "classname" "item_rockets" } { "classname" "item_spikes" "origin" "1400 -248 -256" } { "classname" "trigger_teleport" "target" "t75" "model" "*69" } { "classname" "item_armor1" "origin" "1632 280 -128" } //Q-Man { "classname" "item_flag_team1" "origin" "-832 384 144" } { "classname" "info_player_team1" "origin" "-833 -388 200" "angle" "90" } { "classname" "info_player_team1" "origin" "-831 -5 200" "angle" "90" } { "classname" "info_player_team1" "origin" "-357 0 200" "angle" "180" } { "classname" "info_player_team1" "origin" "-1307 0 200" } { "classname" "info_player_team1" "origin" "-932 384 200" "angle" "315" } { "classname" "info_player_team1" "origin" "-732 384 200" "angle" "225" } { "classname" "item_flag_team2" "origin" "1090 -234 -232" } { "classname" "info_player_team2" "origin" "1314 -211 -232" "angle" "135" } { "classname" "info_player_team2" "origin" "1100 -12 -232" "angle" "90" } { "classname" "info_player_team2" "origin" "1100 179 -232" "angle" "90" } { "classname" "info_player_team2" "origin" "1227 166 -232" "angle" "90" } { "classname" "info_player_team2" "origin" "1405 414 -104" } { "classname" "info_player_team2" "origin" "1230 2 24" "angle" "90" } { "classname" "item_artifact_invisibility" "origin" "579 -753 24" } { "classname" "item_artifact_invisibility" "origin" "-689 -1376 24" } { "classname" "item_armor2" "origin" "-1215 0 200" } { "classname" "item_artifact_invisibility" "origin" "-92 -592 376" } { "classname" "item_spikes" "origin" "48 -1168 72" } { "classname" "item_spikes" "origin" "576 -256 176" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m4.ent000066400000000000000000001660011475442401000252000ustar00rootroot00000000000000{ "worldtype" "1" "wad" "gfx/metal.wad" "classname" "worldspawn" "sounds" "8" "message" "Satan's Dark Delight" } { "angle" "270" "origin" "672 -40 -96" "classname" "info_player_start" } { "light" "150" "origin" "-32 -2048 288" "classname" "light" } { "classname" "light" "origin" "-32 -1920 288" "light" "150" } { "target" "t1" "origin" "-32 -2048 272" "classname" "light" } { "target" "t2" "classname" "light" "origin" "-32 -1920 272" } { "targetname" "t2" "origin" "-28 -1924 180" "classname" "info_null" } { "targetname" "t1" "classname" "info_null" "origin" "-28 -2044 180" } { "classname" "light" "origin" "96 -2048 288" "light" "150" } { "light" "150" "origin" "96 -1920 288" "classname" "light" } { "target" "t3" "classname" "light" "origin" "96 -2048 272" } { "target" "t4" "origin" "96 -1920 272" "classname" "light" } { "targetname" "t4" "classname" "info_null" "origin" "100 -1924 180" } { "targetname" "t3" "origin" "100 -2044 180" "classname" "info_null" } { "light" "150" "origin" "224 -2048 288" "classname" "light" } { "classname" "light" "origin" "224 -1920 288" "light" "150" } { "target" "t6" "origin" "224 -2048 272" "classname" "light" } { "target" "t5" "classname" "light" "origin" "224 -1920 272" } { "targetname" "t5" "origin" "228 -1924 180" "classname" "info_null" } { "targetname" "t6" "classname" "info_null" "origin" "228 -2044 180" } { "classname" "light" "origin" "352 -2048 288" "light" "150" } { "light" "150" "origin" "352 -1920 288" "classname" "light" } { "target" "t7" "classname" "light" "origin" "352 -2048 272" } { "target" "t8" "origin" "352 -1920 272" "classname" "light" } { "targetname" "t8" "classname" "info_null" "origin" "356 -1924 180" } { "targetname" "t7" "origin" "356 -2044 180" "classname" "info_null" } { "light" "150" "origin" "-112 -2128 536" "classname" "light" } { "classname" "light" "origin" "112 -2128 536" "light" "150" } { "light" "150" "origin" "208 -2128 536" "classname" "light" } { "classname" "light" "origin" "432 -2128 536" "light" "150" } { "light" "150" "origin" "432 -1840 536" "classname" "light" } { "classname" "light" "origin" "208 -1840 536" "light" "150" } { "light" "150" "origin" "112 -1840 536" "classname" "light" } { "classname" "light" "origin" "-112 -1840 536" "light" "150" } { "target" "t15" "origin" "-112 -1840 520" "classname" "light" } { "target" "t16" "classname" "light" "origin" "112 -1840 520" } { "target" "t17" "origin" "208 -1840 520" "classname" "light" } { "target" "t14" "classname" "light" "origin" "432 -1840 520" } { "target" "t13" "origin" "432 -2128 520" "classname" "light" } { "target" "t11" "classname" "light" "origin" "208 -2128 520" } { "target" "t12" "origin" "112 -2128 520" "classname" "light" } { "target" "t9" "classname" "light" "origin" "-112 -2128 520" } { "targetname" "t9" "origin" "-116 -2132 188" "classname" "info_null" } { "targetname" "t12" "classname" "info_null" "origin" "108 -2132 188" } { "targetname" "t11" "origin" "212 -2132 188" "classname" "info_null" } { "targetname" "t13" "classname" "info_null" "origin" "436 -2132 188" } { "targetname" "t14" "origin" "436 -1836 188" "classname" "info_null" } { "targetname" "t17" "classname" "info_null" "origin" "212 -1836 188" } { "targetname" "t16" "origin" "108 -1836 188" "classname" "info_null" } { "targetname" "t15" "classname" "info_null" "origin" "-116 -1836 188" } { "light" "150" "origin" "-32 -2048 432" "classname" "light" } { "classname" "light" "origin" "96 -2048 432" "light" "150" } { "light" "150" "origin" "224 -2048 432" "classname" "light" } { "classname" "light" "origin" "352 -2048 432" "light" "150" } { "light" "150" "origin" "352 -1920 432" "classname" "light" } { "classname" "light" "origin" "224 -1920 432" "light" "150" } { "light" "150" "origin" "96 -1920 432" "classname" "light" } { "classname" "light" "origin" "-32 -1920 432" "light" "150" } { "classname" "light" "origin" "592 -16 168" "light" "150" } { "light" "150" "origin" "592 -144 168" "classname" "light" } { "classname" "light" "origin" "592 -272 168" "light" "150" } { "light" "150" "origin" "752 -272 168" "classname" "light" } { "classname" "light" "origin" "752 -144 168" "light" "150" } { "light" "150" "origin" "752 -16 168" "classname" "light" } { "target" "t20" "origin" "592 -16 152" "classname" "light" } { "target" "t23" "classname" "light" "origin" "752 -16 152" } { "target" "t21" "origin" "592 -144 152" "classname" "light" } { "target" "t24" "classname" "light" "origin" "752 -144 152" } { "target" "t22" "origin" "592 -272 152" "classname" "light" } { "target" "t25" "classname" "light" "origin" "752 -272 152" } { "targetname" "t20" "origin" "588 -12 20" "classname" "info_null" } { "targetname" "t21" "classname" "info_null" "origin" "588 -140 20" } { "targetname" "t22" "origin" "588 -268 20" "classname" "info_null" } { "targetname" "t25" "classname" "info_null" "origin" "756 -268 20" } { "targetname" "t24" "origin" "756 -140 20" "classname" "info_null" } { "targetname" "t23" "classname" "info_null" "origin" "756 -12 20" } { "light" "150" "origin" "944 16 112" "classname" "light" } { "classname" "light" "origin" "816 16 112" "light" "150" } { "light" "150" "origin" "816 -112 112" "classname" "light" } { "classname" "light" "origin" "944 -112 112" "light" "150" } { "light" "150" "origin" "944 -240 112" "classname" "light" } { "classname" "light" "origin" "944 -368 112" "light" "150" } { "classname" "light" "origin" "816 -240 112" "light" "150" } { "target" "t30" "origin" "944 16 96" "classname" "light" } { "target" "t33" "classname" "light" "origin" "944 -112 96" } { "target" "t27" "origin" "944 -240 96" "classname" "light" } { "target" "t26" "classname" "light" "origin" "944 -368 96" } { "target" "t29" "classname" "light" "origin" "816 -240 96" } { "target" "t32" "origin" "816 -112 96" "classname" "light" } { "target" "t31" "classname" "light" "origin" "816 16 96" } { "targetname" "t30" "origin" "940 12 -124" "classname" "info_null" } { "targetname" "t27" "classname" "info_null" "origin" "940 -244 -124" } { "targetname" "t33" "origin" "940 -116 -124" "classname" "info_null" } { "targetname" "t26" "classname" "info_null" "origin" "940 -364 -124" } { "targetname" "t29" "classname" "info_null" "origin" "820 -236 -124" } { "targetname" "t32" "origin" "820 -116 -124" "classname" "info_null" } { "targetname" "t31" "classname" "info_null" "origin" "820 12 -124" } { "classname" "light" "origin" "528 16 112" "light" "150" } { "light" "150" "origin" "400 16 112" "classname" "light" } { "classname" "light" "origin" "400 -112 112" "light" "150" } { "light" "150" "origin" "528 -112 112" "classname" "light" } { "classname" "light" "origin" "528 -240 112" "light" "150" } { "classname" "light" "origin" "400 -368 112" "light" "150" } { "light" "150" "origin" "400 -240 112" "classname" "light" } { "target" "t39" "classname" "light" "origin" "528 16 96" } { "target" "t40" "origin" "528 -112 96" "classname" "light" } { "target" "t37" "classname" "light" "origin" "528 -240 96" } { "target" "t34" "classname" "light" "origin" "400 -368 96" } { "target" "t36" "origin" "400 -240 96" "classname" "light" } { "target" "t41" "classname" "light" "origin" "400 -112 96" } { "target" "t38" "origin" "400 16 96" "classname" "light" } { "targetname" "t38" "origin" "404 12 -124" "classname" "info_null" } { "targetname" "t39" "classname" "info_null" "origin" "524 12 -124" } { "targetname" "t41" "origin" "404 -116 -124" "classname" "info_null" } { "targetname" "t40" "classname" "info_null" "origin" "524 -116 -124" } { "targetname" "t37" "origin" "524 -236 -124" "classname" "info_null" } { "targetname" "t34" "origin" "404 -364 -124" "classname" "info_null" } { "targetname" "t36" "classname" "info_null" "origin" "404 -236 -124" } { "light" "150" "origin" "672 -32 -48" "classname" "light" } { "classname" "light" "origin" "672 -128 -120" "light" "150" } { "light" "150" "origin" "672 -200 -120" "classname" "light" } { "classname" "light" "origin" "672 -264 -120" "light" "150" } { "classname" "light" "origin" "672 -48 192" "light" "150" } { "light" "150" "origin" "672 -144 192" "classname" "light" } { "classname" "light" "origin" "672 -240 192" "light" "150" } { "classname" "light" "origin" "672 -48 176" "target" "t44" } { "origin" "672 -144 176" "classname" "light" "target" "t43" } { "classname" "light" "origin" "672 -240 176" "target" "t42" } { "classname" "info_null" "origin" "668 -44 20" "targetname" "t44" } { "origin" "668 -140 20" "classname" "info_null" "targetname" "t43" } { "classname" "info_null" "origin" "668 -236 20" "targetname" "t42" } { "light" "150" "origin" "944 -432 112" "classname" "light" } { "origin" "944 -432 96" "classname" "light" "target" "t45" } { "origin" "948 -428 -124" "classname" "info_null" "targetname" "t45" } { "classname" "light" "origin" "400 -432 112" "light" "150" } { "classname" "light" "origin" "400 -432 96" "target" "t46" } { "classname" "info_null" "origin" "396 -428 -124" "targetname" "t46" } { "classname" "light" "origin" "912 -576 112" "light" "150" } { "classname" "light" "origin" "912 -576 96" "target" "t47" } { "classname" "info_null" "origin" "916 -580 -124" "targetname" "t47" } { "light" "150" "origin" "880 -752 112" "classname" "light" } { "origin" "880 -752 96" "classname" "light" "target" "t51" } { "origin" "884 -756 -124" "classname" "info_null" "targetname" "t51" } { "classname" "light" "origin" "672 -672 112" } { "origin" "672 -544 112" "classname" "light" } { "light" "150" "origin" "432 -576 112" "classname" "light" } { "classname" "light" "origin" "464 -752 112" "light" "150" } { "origin" "432 -576 96" "classname" "light" "target" "t52" } { "classname" "light" "origin" "464 -752 96" "target" "t53" } { "classname" "info_null" "origin" "460 -756 -124" "targetname" "t53" } { "origin" "428 -580 -124" "classname" "info_null" "targetname" "t52" } { "classname" "light" "origin" "488 -456 -184" "light" "200" } { "light" "200" "origin" "856 -456 -184" "classname" "light" } { "classname" "light" "origin" "592 -336 -80" "light" "125" } { "light" "125" "origin" "752 -336 -80" "classname" "light" } { "classname" "light" "origin" "592 -336 -96" "target" "t54" } { "origin" "752 -336 -96" "classname" "light" "target" "t55" } { "classname" "info_null" "origin" "588 -332 -220" "targetname" "t54" } { "origin" "756 -332 -220" "classname" "info_null" "targetname" "t55" } { "classname" "light" "origin" "672 -368 -216" "light" "125" } { "light" "125" "origin" "672 -496 -216" "classname" "light" } { "classname" "light" "origin" "784 -576 -216" "light" "125" } { "light" "125" "origin" "560 -576 -216" "classname" "light" } { "light" "125" "origin" "832 -704 -216" "classname" "light" } { "classname" "light" "origin" "512 -704 -216" "light" "125" } { "classname" "light" "origin" "672 -456 -40" "light" "150" } { "classname" "light" "origin" "896 -640 -216" "light" "125" } { "light" "125" "origin" "448 -640 -216" "classname" "light" } { "classname" "trigger_once" "target" "t56" "model" "*1" } { "origin" "800 -992 -152" "classname" "light" } { "classname" "light" "origin" "544 -1000 -152" } { "origin" "128 -512 -152" "classname" "light" } { "classname" "light" "origin" "216 -784 -152" } { "origin" "280 -984 -152" "classname" "light" } { "light" "150" "origin" "944 -1104 -192" "classname" "light" } { "target" "t57" "origin" "944 -1104 -176" "classname" "light" } { "targetname" "t57" "origin" "932 -1116 -100" "classname" "info_null" } { "classname" "light" "origin" "976 -880 -192" "light" "150" } { "target" "t58" "classname" "light" "origin" "944 -880 -176" } { "targetname" "t58" "classname" "info_null" "origin" "932 -868 -100" } { "origin" "1216 -512 128" "classname" "light" } { "classname" "light" "origin" "1216 -704 128" } { "origin" "1280 -864 128" "classname" "light" } { "classname" "light" "origin" "1448 -872 128" } { "origin" "1632 -872 128" "classname" "light" } { "classname" "light" "origin" "1776 -784 128" } { "light" "150" "origin" "1008 -464 -192" "classname" "light" } { "classname" "light" "origin" "1008 -688 -192" "light" "150" } { "light" "150" "origin" "1328 -464 -192" "classname" "light" } { "classname" "light" "origin" "1328 -656 -192" "light" "150" } { "target" "t60" "classname" "light" "origin" "1008 -688 -176" } { "target" "t59" "origin" "1008 -464 -176" "classname" "light" } { "target" "t61" "classname" "light" "origin" "1328 -464 -176" } { "target" "t62" "origin" "1328 -656 -176" "classname" "light" } { "target" "t63" "classname" "light" "origin" "1392 -720 -176" } { "light" "150" "origin" "1392 -720 -192" "classname" "light" } { "targetname" "t60" "classname" "info_null" "origin" "996 -684 -100" } { "targetname" "t59" "origin" "996 -452 -100" "classname" "info_null" } { "targetname" "t61" "classname" "info_null" "origin" "1340 -452 -100" } { "targetname" "t62" "origin" "1340 -652 -100" "classname" "info_null" } { "targetname" "t63" "classname" "info_null" "origin" "1396 -708 -100" } { "light" "150" "origin" "1016 -576 -216" "classname" "light" } { "classname" "light" "origin" "1152 -576 -216" "light" "150" } { "light" "150" "origin" "1152 -704 -216" "classname" "light" } { "classname" "light" "origin" "1152 -832 -216" "light" "175" } { "light" "175" "origin" "1248 -896 -216" "classname" "light" } { "classname" "light" "origin" "1408 -896 -216" "light" "175" } { "light" "175" "origin" "1536 -896 -216" "classname" "light" } { "classname" "light" "origin" "1672 -896 -216" "light" "175" } { "light" "150" "origin" "1792 -896 -216" "classname" "light" } { "classname" "light" "origin" "1792 -768 -216" "light" "175" } { "light" "175" "origin" "1792 -648 -216" "classname" "light" } { "targetname" "t64" "origin" "1548 -708 -100" "classname" "info_null" } { "targetname" "t65" "classname" "info_null" "origin" "1604 -660 -100" } { "targetname" "t66" "origin" "1604 -468 -100" "classname" "info_null" } { "targetname" "t67" "classname" "info_null" "origin" "1548 -412 -100" } { "classname" "light" "origin" "1568 -720 -192" "light" "150" } { "light" "150" "origin" "1616 -656 -192" "classname" "light" } { "classname" "light" "origin" "1616 -440 -192" "light" "150" } { "light" "150" "origin" "1552 -400 -192" "classname" "light" } { "target" "t64" "origin" "1552 -720 -176" "classname" "light" } { "target" "t65" "classname" "light" "origin" "1616 -656 -176" } { "target" "t66" "origin" "1616 -464 -176" "classname" "light" } { "target" "t67" "classname" "light" "origin" "1552 -400 -176" } { "classname" "light" "origin" "1792 -520 -216" "light" "175" } { "light" "175" "origin" "1792 -392 -216" "classname" "light" } { "classname" "light" "origin" "1792 -264 -216" "light" "175" } { "light" "175" "origin" "1664 -256 -216" "classname" "light" } { "classname" "light" "origin" "1536 -256 -216" "light" "175" } { "light" "175" "origin" "1408 -256 -216" "classname" "light" } { "classname" "light" "origin" "1280 -256 -216" "light" "175" } { "light" "400" "origin" "1464 -568 184" "classname" "light" } { "classname" "light" "origin" "1104 -1104 -192" "light" "150" } { "light" "150" "origin" "1264 -1104 -192" "classname" "light" } { "classname" "light" "origin" "1424 -1104 -192" "light" "150" } { "light" "150" "origin" "1616 -1104 -192" "classname" "light" } { "classname" "light" "origin" "1776 -1104 -192" "light" "150" } { "light" "150" "origin" "2000 -1104 -192" "classname" "light" } { "target" "t68" "origin" "2000 -1104 -176" "classname" "light" } { "target" "t69" "classname" "light" "origin" "1776 -1104 -176" } { "target" "t70" "origin" "1616 -1104 -176" "classname" "light" } { "target" "t71" "classname" "light" "origin" "1424 -1104 -176" } { "target" "t72" "origin" "1264 -1104 -176" "classname" "light" } { "target" "t73" "classname" "light" "origin" "1104 -1104 -176" } { "targetname" "t68" "origin" "2012 -1116 -100" "classname" "info_null" } { "targetname" "t69" "classname" "info_null" "origin" "1772 -1116 -100" } { "targetname" "t70" "origin" "1612 -1116 -100" "classname" "info_null" } { "targetname" "t71" "classname" "info_null" "origin" "1428 -1116 -100" } { "targetname" "t72" "origin" "1268 -1116 -100" "classname" "info_null" } { "targetname" "t73" "classname" "info_null" "origin" "1108 -1116 -100" } { "classname" "light" "origin" "1264 -48 -192" "light" "150" } { "light" "150" "origin" "1360 -48 -192" "classname" "light" } { "classname" "light" "origin" "1488 -48 -192" "light" "150" } { "light" "150" "origin" "1648 -48 -192" "classname" "light" } { "classname" "light" "origin" "1808 -48 -192" "light" "150" } { "light" "150" "origin" "2000 -48 -192" "classname" "light" } { "classname" "light" "origin" "2000 -272 -192" "light" "150" } { "light" "150" "origin" "2000 -432 -192" "classname" "light" } { "classname" "light" "origin" "2000 -592 -192" "light" "150" } { "light" "150" "origin" "2000 -752 -192" "classname" "light" } { "target" "t74" "origin" "1264 -48 -176" "classname" "light" } { "target" "t75" "classname" "light" "origin" "1360 -48 -176" } { "target" "t76" "origin" "1488 -48 -176" "classname" "light" } { "target" "t77" "classname" "light" "origin" "1648 -48 -176" } { "target" "t78" "origin" "1808 -48 -176" "classname" "light" } { "target" "t79" "classname" "light" "origin" "2000 -48 -176" } { "target" "t80" "origin" "2000 -272 -176" "classname" "light" } { "target" "t81" "classname" "light" "origin" "2000 -432 -176" } { "target" "t82" "origin" "2000 -592 -176" "classname" "light" } { "target" "t83" "classname" "light" "origin" "2000 -752 -176" } { "targetname" "t74" "classname" "info_null" "origin" "1252 -36 -100" } { "targetname" "t75" "origin" "1356 -36 -100" "classname" "info_null" } { "targetname" "t76" "classname" "info_null" "origin" "1484 -36 -100" } { "targetname" "t77" "origin" "1652 -36 -100" "classname" "info_null" } { "targetname" "t78" "classname" "info_null" "origin" "1812 -36 -100" } { "targetname" "t79" "origin" "2012 -36 -100" "classname" "info_null" } { "targetname" "t80" "classname" "info_null" "origin" "2012 -268 -100" } { "targetname" "t81" "origin" "2012 -428 -100" "classname" "info_null" } { "targetname" "t82" "classname" "info_null" "origin" "2012 -596 -100" } { "targetname" "t83" "origin" "2012 -756 -100" "classname" "info_null" } { "classname" "light" "origin" "2000 -912 -192" "light" "150" } { "target" "t84" "classname" "light" "origin" "2000 -912 -176" } { "targetname" "t84" "classname" "info_null" "origin" "2012 -908 -100" } { "target" "t86" "classname" "light" "origin" "1392 -400 -192" "light" "150" } { "origin" "1392 -400 -176" "classname" "light" } { "targetname" "t86" "origin" "1396 -412 -100" "classname" "info_null" } { "light" "150" "origin" "1264 -400 -192" "classname" "light" } { "target" "t85" "classname" "light" "origin" "1264 -400 -176" } { "targetname" "t85" "classname" "info_null" "origin" "1260 -412 -100" } { "origin" "1776 -632 128" "classname" "light" } { "classname" "light" "origin" "1776 -448 128" } { "origin" "1784 -272 128" "classname" "light" } { "classname" "light" "origin" "1624 -272 128" } { "origin" "1456 -272 128" "classname" "light" } { "classname" "light" "origin" "1312 -272 128" } { "sounds" "4" "speed" "200" "angle" "270" "targetname" "t87" "classname" "func_door" "model" "*2" } { "target" "t87" "classname" "trigger_multiple" "model" "*3" } { "sounds" "4" "speed" "300" "targetname" "t87" "angle" "-2" "classname" "func_door" "model" "*4" } { "origin" "1152 -184 264" "classname" "light" } { "classname" "light" "origin" "1152 -240 0" "light" "200" } { "origin" "1664 64 288" "classname" "light" "light" "325" } { "classname" "light" "origin" "1472 64 288" "light" "325" } { "origin" "1280 64 288" "classname" "light" "light" "325" } { "classname" "light" "origin" "1152 64 264" } { "sounds" "4" "lip" "-264" "targetname" "t88" "angle" "-1" "classname" "func_door" "model" "*5" } { "target" "t88" "angle" "270" "classname" "func_button" "model" "*6" } { "origin" "992 -576 -16" "classname" "light" } { "light" "300" "origin" "824 -576 448" "classname" "light" } { "origin" "256 -576 272" "classname" "light" } { "classname" "light" "origin" "480 -576 440" "light" "250" } { "light" "175" "origin" "1464 -56 56" "classname" "light" } { "light" "150" "origin" "1376 -448 96" "classname" "light" } { "classname" "light" "origin" "1568 -448 96" "light" "150" } { "light" "150" "origin" "1568 -672 96" "classname" "light" } { "classname" "light" "origin" "1376 -672 96" "light" "150" } { "target" "t89" "origin" "1376 -448 80" "classname" "light" } { "target" "t90" "classname" "light" "origin" "1376 -672 80" } { "target" "t91" "origin" "1568 -672 80" "classname" "light" } { "target" "t92" "classname" "light" "origin" "1568 -448 80" } { "targetname" "t89" "origin" "1364 -436 -60" "classname" "info_null" } { "targetname" "t92" "classname" "info_null" "origin" "1580 -436 -60" } { "targetname" "t91" "origin" "1580 -684 -60" "classname" "info_null" } { "targetname" "t90" "classname" "info_null" "origin" "1364 -684 -60" } { "light" "200" "origin" "1480 -568 24" "classname" "light" } { "style" "2" "target" "t93" "origin" "1472 -40 -24" "classname" "light" } { "targetname" "t93" "origin" "1532 -36 -20" "classname" "info_null" } { "light" "150" "origin" "1536 -40 -56" "classname" "light" } { "wait" "-1" "targetname" "t94" "classname" "func_door" "angle" "270" "spawnflags" "1" "model" "*7" } { "wait" "-1" "target" "t94" "angle" "0" "classname" "func_button" "model" "*8" } { "targetname" "t94" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*9" } { "sounds" "1" "wait" "-1" "angle" "180" "classname" "func_door" "model" "*10" } { "light" "150" "origin" "1472 -376 -32" "classname" "light" } { "origin" "1152 -240 -40" "classname" "monster_ogre" } { "light" "200" "origin" "1152 -96 0" "classname" "light" } { "classname" "light" "origin" "1176 48 0" "light" "200" } { "light" "200" "origin" "1320 48 0" "classname" "light" } { "classname" "light" "origin" "1504 48 0" "light" "200" } { "light" "200" "origin" "1704 48 0" "classname" "light" } { "classname" "light" "origin" "1376 -8 192" "light" "200" } { "light" "200" "origin" "1568 -16 192" "classname" "light" } { "classname" "light" "origin" "1168 -32 192" "light" "200" } { "light" "200" "origin" "1760 24 192" "classname" "light" } { "classname" "trigger_once" "target" "t95" "model" "*11" } { "spawnflags" "2048" "sounds" "1" "classname" "func_door" "angle" "180" "wait" "-1" "model" "*12" } { "spawnflags" "2048" "classname" "func_door" "angle" "0" "targetname" "t96" "wait" "-1" "model" "*13" } { "spawnflags" "2048" "classname" "func_door" "angle" "90" "targetname" "t121" "wait" "-1" "model" "*14" } { "spawnflags" "2048" "message" "This door is opened elsewhere..." "sounds" "1" "classname" "func_door" "angle" "270" "wait" "-1" "model" "*15" } { "spawnflags" "2048" "targetname" "t121" "classname" "func_door" "angle" "90" "wait" "-1" "model" "*16" } { "spawnflags" "2048" "classname" "func_door" "angle" "0" "targetname" "t96" "wait" "-1" "model" "*17" } { "classname" "func_door" "angle" "180" "wait" "-1" "spawnflags" "2048" "model" "*18" } { "targetname" "t95" "classname" "monster_ogre" "origin" "1472 -480 -40" "angle" "90" "target" "t96" } { "targetname" "t95" "angle" "270" "origin" "1472 -40 -40" "classname" "monster_ogre" } { "classname" "light" "origin" "2240 -832 -24" } { "light" "200" "origin" "1560 -1344 -24" "classname" "light" } { "message" "This door opens elsewhere" "targetname" "t97" "wait" "-1" "angle" "270" "classname" "func_door" "spawnflags" "2048" "model" "*19" } { "classname" "func_door" "angle" "90" "wait" "-1" "spawnflags" "2048" "model" "*20" } { "light" "200" "classname" "light" "origin" "1472 -1216 0" } { "origin" "2112 -576 -24" "classname" "light" } { "wait" "-1" "target" "t97" "angle" "315" "classname" "func_button" "spawnflags" "2048" "model" "*21" } { "style" "2" "target" "t98" "origin" "2280 -1432 -120" "classname" "light" } { "targetname" "t98" "origin" "2316 -1492 -124" "classname" "info_null" } { "light" "200" "origin" "2288 -1456 -120" "classname" "light" } { "targetname" "t113" "angle" "270" "origin" "2240 -1208 24" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "1784 -1344 24" "angle" "180" } { "origin" "2048 -1344 96" "classname" "light" } { "classname" "light" "origin" "2304 -1344 224" } { "origin" "2048 -1472 224" "classname" "light" } { "classname" "light" "origin" "2304 -1472 224" } { "target" "t99" "light" "150" "origin" "1968 -1168 -32" "classname" "light" } { "origin" "1968 -1168 -48" "classname" "light" } { "targetname" "t99" "origin" "1956 -1156 -188" "classname" "info_null" } { "light" "150" "origin" "1872 -1520 -32" "classname" "light" } { "target" "t100" "classname" "light" "origin" "1872 -1520 -48" } { "targetname" "t100" "classname" "info_null" "origin" "1860 -1532 -196" } { "classname" "light" "origin" "2352 -1200 -32" "light" "150" } { "target" "t101" "origin" "2352 -1200 -48" "classname" "light" } { "targetname" "t101" "origin" "2364 -1212 -196" "classname" "info_null" } { "classname" "light" "origin" "1872 -1168 96" "light" "150" } { "light" "150" "origin" "2352 -1168 96" "classname" "light" } { "classname" "light" "origin" "1872 -1520 96" "light" "150" } { "target" "t99" "origin" "1872 -1168 80" "classname" "light" } { "target" "t101" "classname" "light" "origin" "2352 -1168 80" } { "target" "t100" "origin" "1872 -1520 80" "classname" "light" } { "spawnflags" "5" "angle" "0" "targetname" "t103" "classname" "func_door" "sounds" "3" "model" "*22" } { "spawnflags" "5" "angle" "0" "targetname" "t104" "classname" "func_door" "sounds" "3" "model" "*23" } { "spawnflags" "5" "angle" "0" "targetname" "t105" "classname" "func_door" "sounds" "3" "model" "*24" } { "light" "200" "origin" "2240 -1088 -40" "classname" "light" } { "light" "200" "classname" "light" "origin" "2240 -1072 72" } { "angle" "270" "target" "t102" "health" "1" "classname" "func_button" "model" "*25" } { "delay" "2" "target" "t105" "targetname" "t102" "classname" "trigger_multiple" "model" "*26" } { "delay" "1" "target" "t104" "targetname" "t102" "classname" "trigger_multiple" "model" "*27" } { "target" "t103" "targetname" "t102" "classname" "trigger_multiple" "model" "*28" } { "light" "100" "origin" "2176 -912 -56" "classname" "light" } { "classname" "light" "origin" "2176 -960 -40" "light" "100" } { "light" "100" "origin" "2176 -1000 -24" "classname" "light" } { "angle" "0" "classname" "trigger_monsterjump" "model" "*29" } { "angle" "270" "classname" "trigger_monsterjump" "model" "*30" } { "spawnflags" "768" "targetname" "t97" "angle" "180" "origin" "2568 -1288 -168" "classname" "monster_ogre" } { "spawnflags" "256" "targetname" "t97" "classname" "monster_ogre" "origin" "2568 -1376 -168" "angle" "180" } { "target" "t109" "targetname" "t97" "angle" "180" "origin" "2568 -1464 -168" "classname" "monster_ogre" } { "spawnflags" "2" "target" "t106" "classname" "trigger_teleport" "model" "*31" } { "spawnflags" "2" "target" "t107" "classname" "trigger_teleport" "model" "*32" } { "spawnflags" "2" "target" "t108" "classname" "trigger_teleport" "model" "*33" } { "targetname" "t107" "angle" "315" "origin" "1920 -1216 8" "classname" "info_teleport_destination" } { "targetname" "t108" "angle" "0" "origin" "1920 -1408 8" "classname" "info_teleport_destination" } { "targetname" "t106" "angle" "270" "origin" "2176 -1216 8" "classname" "info_teleport_destination" } { "angle" "315" "classname" "trigger_monsterjump" "model" "*34" } { "angle" "180" "classname" "trigger_monsterjump" "model" "*35" } { "angle" "90" "classname" "trigger_monsterjump" "model" "*36" } { "light" "150" "origin" "2352 -1248 -96" "classname" "light" } { "classname" "light" "origin" "2352 -1376 -96" "light" "150" } { "light" "150" "origin" "1952 -1520 -96" "classname" "light" } { "classname" "light" "origin" "2064 -1520 -96" "light" "150" } { "light" "150" "origin" "2168 -1520 -96" "classname" "light" } { "sounds" "3" "targetname" "t109" "spawnflags" "2049" "angle" "-2" "classname" "func_door" "wait" "5" "model" "*37" } { "sounds" "3" "targetname" "t109" "classname" "func_door" "angle" "-2" "spawnflags" "2049" "wait" "5" "model" "*38" } { "target" "t109" "targetname" "t97" "classname" "trigger_once" "model" "*39" } { "light" "150" "origin" "1424 -1392 96" "classname" "light" } { "target" "t110" "origin" "1424 -1392 80" "classname" "light" } { "targetname" "t110" "origin" "1412 -1404 -60" "classname" "info_null" } { "light" "200" "origin" "1792 -1344 -48" "classname" "light" } { "light" "150" "origin" "2288 -528 96" "classname" "light" } { "target" "t111" "origin" "2288 -528 80" "classname" "light" } { "targetname" "t111" "origin" "2300 -516 -60" "classname" "info_null" } { "target" "t121" "classname" "trigger_once" "model" "*40" } { "light" "200" "origin" "1792 -1344 104" "classname" "light" } { "light" "150" "origin" "1920 -1344 -80" "classname" "light" } { "classname" "light" "origin" "2240 -1208 -80" "light" "150" } { "target" "t113" "classname" "trigger_once" "model" "*41" } { "classname" "monster_wizard" "origin" "1336 -248 104" "angle" "0" "target" "t120" "spawnflags" "256" } { "classname" "path_corner" "origin" "1344 -296 88" "angle" "0" "target" "t114" "targetname" "t120" } { "classname" "path_corner" "origin" "1768 -312 88" "angle" "270" "targetname" "t114" "target" "t115" } { "classname" "path_corner" "origin" "1776 -896 88" "angle" "180" "targetname" "t115" "target" "t116" } { "classname" "path_corner" "origin" "1208 -880 88" "angle" "270" "targetname" "t116" "target" "t117" } { "classname" "path_corner" "origin" "1208 -952 88" "angle" "0" "targetname" "t117" "target" "t118" } { "classname" "path_corner" "origin" "1768 -872 88" "angle" "90" "targetname" "t118" "target" "t119" } { "classname" "path_corner" "origin" "1768 -280 88" "angle" "180" "targetname" "t119" "target" "t120" } { "classname" "monster_ogre" "origin" "328 -576 408" "angle" "0" "targetname" "t122" "spawnflags" "768" } { "classname" "trigger_monsterjump" "angle" "0" "model" "*42" } { "classname" "monster_ogre" "origin" "952 -576 408" "angle" "180" } { "classname" "trigger_monsterjump" "angle" "180" "model" "*43" } { "classname" "trigger_once" "target" "t122" "model" "*44" } { "origin" "648 -576 440" "classname" "light" } { "light" "200" "origin" "192 -1344 -152" "classname" "light" } { "classname" "light" "origin" "256 -1152 -152" } { "origin" "-352 -1152 -152" "classname" "light" } { "classname" "light" "origin" "-352 -888 -152" } { "origin" "-336 -576 -152" "classname" "light" } { "classname" "light" "origin" "-104 -584 -152" } { "origin" "-112 -768 -152" "classname" "light" } { "classname" "light" "origin" "-192 -1160 -152" } { "origin" "-168 -960 -152" "classname" "light" } { "classname" "light" "origin" "32 -936 -152" } { "dmg" "10000" "targetname" "t162" "target" "t156" "classname" "func_train" "model" "*45" } { "classname" "func_button" "angle" "270" "wait" "-1" "target" "t133" "health" "1" "model" "*46" } { "classname" "func_train" "target" "t139" "targetname" "t143" "model" "*47" } { "classname" "path_corner" "origin" "-240 -1080 -272" "target" "t135" "targetname" "t139" "wait" "4" } { "origin" "-240 -984 -272" "classname" "path_corner" "targetname" "t135" "target" "t136" } { "classname" "path_corner" "origin" "88 -984 -272" "targetname" "t136" "target" "t137" "wait" "4" } { "classname" "trigger_once" "targetname" "t133" "target" "t134" "delay" "5" "model" "*48" } { "origin" "88 -984 -272" "classname" "path_corner" "targetname" "t137" "target" "t138" } { "classname" "path_corner" "origin" "-240 -984 -272" "targetname" "t138" "target" "t139" } { "classname" "func_train" "target" "t140" "targetname" "t143" "model" "*49" } { "wait" "3" "origin" "208 -1184 -272" "classname" "path_corner" "targetname" "t140" "target" "t141" } { "classname" "path_corner" "origin" "208 -1520 -272" "targetname" "t141" "target" "t142" } { "wait" "3" "origin" "208 -1520 -272" "classname" "path_corner" "targetname" "t142" "target" "t140" } { "sounds" "1" "classname" "func_door" "angle" "-2" "targetname" "t143" "wait" "-1" "spawnflags" "1" "lip" "128" "model" "*50" } { "classname" "trigger_once" "target" "t143" "targetname" "t159" "model" "*51" } { "classname" "monster_ogre" "origin" "-352 -1344 -240" "angle" "90" } { "classname" "func_door" "angle" "-2" "dmg" "1000" "targetname" "t144" "model" "*52" } { "classname" "func_button" "angle" "270" "health" "1" "target" "t144" "model" "*53" } { "classname" "light" "origin" "-352 -1344 -240" "light" "250" } { "classname" "light" "origin" "-352 -1280 -88" "light" "250" } { "dmg" "10000" "targetname" "t162" "classname" "func_train" "target" "t150" "model" "*54" } { "origin" "-576 -1072 -152" "classname" "light" } { "classname" "path_corner" "origin" "80 -624 -272" "targetname" "t156" "target" "t157" "wait" "4" } { "origin" "80 -624 -88" "classname" "path_corner" "target" "t145" "targetname" "t157" } { "classname" "path_corner" "origin" "-400 -624 -88" "targetname" "t145" "target" "t146" "wait" "4" } { "origin" "-400 -1008 -88" "classname" "path_corner" "targetname" "t146" "target" "t147" } { "classname" "path_corner" "origin" "-624 -1008 -88" "targetname" "t147" "target" "t148" } { "origin" "-624 -1232 -88" "classname" "path_corner" "targetname" "t148" "target" "t149" } { "classname" "path_corner" "origin" "-600 -1232 -272" "targetname" "t149" "target" "t150" } { "origin" "-400 -1232 -272" "classname" "path_corner" "targetname" "t150" "target" "t151" "wait" "4" } { "classname" "path_corner" "origin" "-400 -624 -272" "targetname" "t151" "target" "t152" } { "origin" "-176 -624 -272" "classname" "path_corner" "targetname" "t152" "target" "t153" } { "classname" "path_corner" "origin" "-176 -704 -272" "targetname" "t153" "target" "t154" "wait" "2" } { "origin" "-136 -704 -272" "classname" "path_corner" "targetname" "t154" "target" "t155" "wait" "2" } { "classname" "path_corner" "origin" "-136 -624 -272" "targetname" "t155" "target" "t156" } { "classname" "light" "origin" "16 -568 -56" "light" "200" } { "classname" "light" "origin" "-352 -1208 -32" "target" "t158" "style" "2" } { "classname" "info_null" "origin" "-348 -1244 -36" "targetname" "t158" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t159" "health" "1" "model" "*55" } { "spawnflags" "2048" "sounds" "4" "speed" "50" "targetname" "t161" "classname" "func_door" "angle" "270" "wait" "-1" "model" "*56" } { "target" "t160" "classname" "trigger_once" "model" "*57" } { "spawnflags" "2048" "target" "t161" "classname" "trigger_once" "model" "*58" } { "angle" "90" "origin" "-112 -768 -240" "classname" "monster_ogre" } { "target" "t162" "classname" "trigger_once" "model" "*59" } { "sounds" "4" "targetname" "t134" "angle" "270" "classname" "func_door" "wait" "-1" "message" "This door is opened elsewhere..." "model" "*60" } { "sounds" "4" "targetname" "t134" "classname" "func_door" "angle" "0" "wait" "-1" "message" "This door is opened elsewhere..." "model" "*61" } { "classname" "light" "origin" "-368 -544 0" "light" "200" } { "sounds" "1" "classname" "func_door" "angle" "-2" "lip" "-172" "targetname" "t163" "model" "*62" } { "sounds" "1" "classname" "func_door" "angle" "-2" "targetname" "t163" "model" "*63" } { "delay" "1" "lip" "-172" "classname" "trigger_multiple" "target" "t163" "model" "*64" } { "light" "150" "origin" "-176 -352 -40" "classname" "light" } { "classname" "light" "origin" "-48 -352 -40" "light" "150" } { "light" "150" "origin" "80 -352 -40" "classname" "light" } { "classname" "light" "origin" "-528 -376 224" "light" "400" } { "light" "150" "origin" "248 -352 -8" "classname" "light" } { "origin" "248 -352 192" "classname" "light" } { "classname" "light" "origin" "264 -352 -136" "light" "200" } { "light" "100" "origin" "-112 -360 80" "classname" "light" } { "classname" "light" "origin" "24 -360 80" "light" "100" } { "light" "100" "origin" "144 -360 80" "classname" "light" } { "classname" "light" "origin" "-256 -368 80" "light" "100" } { "light" "100" "origin" "-288 -320 0" "classname" "light" } { "light" "150" "origin" "-512 -384 96" "classname" "light" } { "light" "175" "origin" "-512 -576 0" "classname" "light" } { "classname" "light" "origin" "-320 -408 0" "light" "175" } { "angle" "0" "origin" "24 -568 -72" "classname" "monster_ogre" } { "angle" "270" "origin" "256 -496 -232" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "0" "origin" "-536 -960 -160" "classname" "monster_ogre" } { "angle" "0" "origin" "-496 -560 -40" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "270" "origin" "-336 -408 -40" "classname" "monster_ogre" } { "spawnflags" "256" "angle" "315" "origin" "448 -400 -104" "classname" "monster_ogre" } { "angle" "225" "classname" "monster_ogre" "origin" "888 -400 -104" } { "origin" "224 -1728 -184" "classname" "light" } { "origin" "192 -1736 136" "classname" "light" } { "light" "200" "origin" "88 -1448 -192" "classname" "light" } { "light" "200" "classname" "light" "origin" "296 -1568 -192" } { "sounds" "4" "spawnflags" "32" "targetname" "t164" "angle" "180" "classname" "func_door" "model" "*65" } { "sounds" "4" "targetname" "t165" "classname" "func_door" "angle" "90" "model" "*66" } { "wait" "5" "target" "t164" "classname" "trigger_multiple" "model" "*67" } { "wait" "5" "target" "t164" "classname" "trigger_multiple" "model" "*68" } { "target" "t165" "classname" "trigger_multiple" "model" "*69" } { "origin" "928 -576 -352" "classname" "light" } { "target" "t167" "angle" "270" "classname" "func_button" "model" "*70" } { "sounds" "3" "targetname" "t166" "lip" "-416" "angle" "-1" "classname" "func_door" "model" "*71" } { "targetname" "t168" "angle" "0" "classname" "func_door" "model" "*72" } { "sounds" "4" "angle" "180" "classname" "func_door" "model" "*73" } { "wait" "5" "target" "t167" "angle" "-2" "classname" "func_button" "model" "*74" } { "target" "t166" "targetname" "t167" "classname" "trigger_multiple" "wait" "5" "model" "*75" } { "target" "t168" "delay" "4" "targetname" "t167" "classname" "trigger_multiple" "wait" "5" "model" "*76" } { "light" "200" "origin" "168 -1280 -16" "classname" "light" } { "classname" "light" "origin" "240 -1280 -16" "light" "200" } { "light" "200" "origin" "296 -1280 -16" "classname" "light" } { "classname" "light" "origin" "216 -1440 -16" "light" "200" } { "light" "200" "origin" "288 -1440 -16" "classname" "light" } { "classname" "item_health" "origin" "1976 -848 -208" "spawnflags" "1" } { "origin" "1976 -688 -208" "classname" "item_health" "spawnflags" "1" } { "classname" "item_health" "origin" "1976 -528 -208" "spawnflags" "1" } { "origin" "1976 -368 -208" "classname" "item_health" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1632 -592 -200" } { "classname" "item_spikes" "origin" "992 -928 -208" } { "classname" "item_spikes" "origin" "1984 -1248 0" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1920 -1280 0" "spawnflags" "1" } { "classname" "item_health" "origin" "1904 -1480 0" } { "origin" "2096 -1232 0" "classname" "item_health" } { "spawnflags" "2048" "message" "This door is opened elsewhere..." "sounds" "1" "angle" "270" "classname" "func_door" "wait" "-1" "model" "*77" } { "classname" "light" "origin" "488 -1664 -32" "light" "200" } { "light" "200" "origin" "504 -1536 -32" "classname" "light" } { "classname" "light" "origin" "472 -1400 -32" "light" "200" } { "light" "200" "origin" "512 -1256 -32" "classname" "light" } { "classname" "light" "origin" "872 -1224 -32" "light" "200" } { "light" "200" "origin" "832 -1344 -32" "classname" "light" } { "classname" "light" "origin" "856 -1464 -32" "light" "200" } { "light" "200" "origin" "840 -1624 -32" "classname" "light" } { "classname" "light" "origin" "664 -1664 -240" } { "origin" "672 -1472 -240" "classname" "light" } { "classname" "light" "origin" "680 -1280 -240" } { "classname" "light" "origin" "664 -1960 256" } { "origin" "672 -1208 416" "classname" "light" } { "classname" "light" "origin" "672 -1672 416" } { "origin" "672 -1560 416" "classname" "light" } { "classname" "light" "origin" "672 -1376 416" } { "light" "200" "origin" "840 -1200 64" "classname" "light" } { "light" "200" "classname" "light" "origin" "512 -1192 64" } { "light" "200" "origin" "488 -936 64" "classname" "light" } { "light" "200" "classname" "light" "origin" "672 -1000 64" } { "light" "200" "origin" "832 -944 64" "classname" "light" } { "target" "t119" "origin" "1720 -240 104" "classname" "monster_wizard" } { "spawnflags" "256" "angle" "90" "origin" "1152 -872 -208" "classname" "monster_fish" } { "angle" "180" "origin" "1432 -944 -208" "classname" "monster_fish" } { "angle" "180" "origin" "1656 -936 -208" "classname" "monster_fish" } { "spawnflags" "768" "angle" "270" "origin" "1840 -576 -208" "classname" "monster_fish" } { "angle" "180" "origin" "1904 -912 -24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1864 -1008 -24" "angle" "180" } { "spawnflags" "768" "angle" "180" "origin" "1816 -1008 -24" "classname" "monster_zombie" } { "angle" "0" "origin" "1184 -1008 -24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1096 -976 -24" "angle" "45" } { "spawnflags" "256" "angle" "45" "origin" "1104 -912 -24" "classname" "monster_zombie" } { "light" "200" "origin" "1152 -960 -24" "classname" "light" } { "classname" "light" "origin" "1832 -936 -24" "light" "200" } { "speed" "300" "origin" "512 -1568 -56" "classname" "misc_fireball" } { "speed" "300" "classname" "misc_fireball" "origin" "512 -1432 -56" } { "speed" "300" "origin" "840 -1408 -56" "classname" "misc_fireball" } { "speed" "300" "classname" "misc_fireball" "origin" "832 -1584 -56" } { "classname" "trigger_push" "angle" "90" "speed" "400" "model" "*78" } { "classname" "trigger_push" "angle" "90" "speed" "400" "model" "*79" } { "classname" "light" "origin" "672 -1344 -512" "light" "150" } { "origin" "672 -1152 -512" "classname" "light" "light" "150" } { "classname" "light" "origin" "672 -960 -512" "light" "150" } { "origin" "672 -768 -512" "classname" "light" "light" "150" } { "classname" "light" "origin" "672 -576 -512" "light" "150" } { "origin" "672 -384 -512" "classname" "light" "light" "150" } { "classname" "light" "origin" "672 -192 -512" "light" "150" } { "origin" "672 0 -512" "classname" "light" "light" "150" } { "classname" "light" "origin" "736 416 -720" "light" "200" } { "origin" "608 416 -720" "classname" "light" "light" "200" } { "light" "200" "origin" "784 224 -720" "classname" "light" } { "classname" "light" "origin" "560 224 -720" "light" "200" } { "classname" "light" "origin" "800 232 -736" "target" "t169" "light" "400" } { "classname" "info_null" "origin" "788 236 -996" "targetname" "t169" } { "classname" "light" "origin" "752 424 -736" "target" "t170" "light" "400" } { "origin" "624 408 -736" "classname" "light" "target" "t171" "light" "400" } { "classname" "light" "origin" "576 232 -736" "target" "t172" "light" "400" } { "origin" "748 412 -1004" "classname" "info_null" "targetname" "t170" } { "classname" "info_null" "origin" "620 420 -996" "targetname" "t171" } { "origin" "572 220 -996" "classname" "info_null" "targetname" "t172" } { "light" "150" "classname" "light" "origin" "672 160 -512" } { "origin" "672 256 -512" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "784 320 -616" } { "origin" "680 480 -616" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "560 344 -616" } { "origin" "568 176 -616" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "760 168 -616" } { "light" "150" "classname" "light" "origin" "680 264 -640" } { "origin" "680 240 -720" "classname" "light" } { "origin" "656 248 -888" "classname" "light" } { "spawnflags" "1" "origin" "1400 -576 -64" "classname" "item_health" } { "classname" "item_health" "origin" "1520 -576 -64" "spawnflags" "1" } { "origin" "1104 72 -64" "classname" "item_spikes" } { "origin" "1752 80 -64" "classname" "item_health" } { "origin" "456 -592 208" "classname" "item_health" } { "spawnflags" "1" "origin" "384 -592 208" "classname" "item_shells" } { "spawnflags" "768" "angle" "0" "origin" "80 -1408 -232" "classname" "monster_ogre" } { "spawnflags" "256" "origin" "88 -1528 -232" "classname" "monster_ogre" } { "angle" "90" "origin" "200 -1568 -232" "classname" "monster_zombie" } { "sounds" "1" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*80" } { "wait" "-1" "targetname" "t173" "angle" "180" "classname" "func_door" "model" "*81" } { "target" "t173" "classname" "trigger_once" "model" "*82" } { "spawnflags" "768" "angle" "45" "origin" "104 -1984 200" "classname" "monster_demon1" } { "angle" "135" "spawnflags" "256" "origin" "304 -1984 200" "classname" "monster_demon1" } { "angle" "90" "spawnflags" "512" "origin" "224 -1968 200" "classname" "monster_ogre" } { "angle" "45" "origin" "-24 -2000 200" "classname" "monster_ogre" } { "origin" "-64 -2112 176" "classname" "item_health" } { "classname" "item_health" "origin" "-72 -1912 176" } { "origin" "352 -2112 176" "classname" "item_health" } { "origin" "640 -2016 176" "classname" "item_rockets" } { "map" "e3m7" "classname" "trigger_changelevel" "model" "*83" } { "target" "t174" "classname" "trigger_teleport" "model" "*84" } { "targetname" "t174" "origin" "824 504 -928" "classname" "info_teleport_destination" } { "classname" "light" "origin" "664 -696 -216" "light" "125" } { "light" "125" "origin" "584 -680 -216" "classname" "light" } { "speed" "300" "angle" "225" "classname" "trigger_monsterjump" "model" "*85" } { "angle" "315" "speed" "300" "classname" "trigger_monsterjump" "model" "*86" } { "origin" "1136 -976 -48" "classname" "item_armor2" } { "origin" "1864 -984 -48" "classname" "item_shells" } { "origin" "1456 -632 -64" "classname" "item_health" } { "origin" "-624 -952 -192" "classname" "item_health" } { "spawnflags" "1" "origin" "-624 -1000 -192" "classname" "item_health" } { "origin" "288 -1584 -256" "classname" "item_health" } { "classname" "item_health" "origin" "128 -1584 -256" "spawnflags" "1" } { "origin" "-224 -368 -64" "classname" "item_health" } { "classname" "item_health" "origin" "-96 -368 -64" } { "spawnflags" "1" "origin" "152 -368 -64" "classname" "item_spikes" } { "angle" "180" "spawnflags" "768" "origin" "32 -352 -40" "classname" "monster_demon1" } { "spawnflags" "256" "angle" "270" "origin" "672 -1800 200" "classname" "monster_ogre" } { "sounds" "4" "targetname" "t175" "lip" "-238" "angle" "-1" "classname" "func_door" "model" "*87" } { "target" "t175" "classname" "trigger_multiple" "model" "*88" } { "classname" "light" "origin" "672 -1344 136" } { "origin" "672 -1536 248" "classname" "light" } { "classname" "light" "origin" "808 -1672 128" "light" "175" } { "light" "175" "origin" "552 -1672 128" "classname" "light" } { "classname" "light" "origin" "672 -1696 64" "light" "175" } { "classname" "monster_shambler" "origin" "1024 -1248 24" "angle" "180" "targetname" "t176" } { "sounds" "4" "classname" "func_door" "angle" "0" "spawnflags" "2049" "wait" "10" "model" "*89" } { "classname" "func_door" "angle" "180" "spawnflags" "2049" "targetname" "t176" "wait" "10" "model" "*90" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t176" "model" "*91" } { "classname" "trigger_teleport" "target" "t177" "targetname" "t176" "model" "*92" } { "classname" "info_teleport_destination" "origin" "672 -1224 8" "angle" "270" "targetname" "t177" } { "classname" "item_health" "origin" "464 -1088 0" } { "origin" "464 -992 0" "classname" "item_health" } { "classname" "item_health" "origin" "848 -992 0" } { "origin" "848 -1088 0" "classname" "item_health" } { "classname" "item_spikes" "origin" "48 -1488 -256" } { "classname" "trigger_once" "health" "1" "target" "t178" "model" "*93" } { "classname" "func_door_secret" "angle" "270" "targetname" "t178" "sounds" "2" "wait" "-1" "model" "*94" } // Suck & Jwiz: // We removed this because, like, it was too much for a CTF base. // { // "classname" "item_artifact_invulnerability" // "origin" "-256 -1984 216" // } { "classname" "light" "origin" "-256 -1984 344" } { "sounds" "1" "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t179" "model" "*95" } { "classname" "trigger_once" "target" "t179" "model" "*96" } { "classname" "light" "origin" "-784 -880 -264" } { "origin" "-656 -752 -264" "classname" "light" } { "classname" "light" "origin" "-808 -728 -264" } { "origin" "-792 -792 -264" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-744 -744 -264" } { "classname" "light" "origin" "-720 -816 -64" "light" "200" } { "targetname" "t180" "angle" "90" "origin" "672 -864 16" "classname" "info_teleport_destination" } { "target" "t180" "classname" "trigger_teleport" "model" "*97" } { "angle" "270" "origin" "888 -32 -104" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "456 -32 -104" "angle" "270" } { "angle" "315" "origin" "408 -184 -104" "classname" "info_player_coop" } { "angle" "225" "origin" "936 -192 -104" "classname" "info_player_coop" } { "origin" "448 -320 -128" "classname" "item_health" } { "classname" "item_health" "origin" "864 -320 -128" } { "spawnflags" "1" "origin" "528 -792 -256" "classname" "item_health" } { "classname" "item_health" "origin" "784 -792 -256" "spawnflags" "1" } { "spawnflags" "1" "origin" "544 -592 -256" "classname" "item_spikes" } { "classname" "trigger_secret" "model" "*98" } { "light" "150" "origin" "-176 -2104 328" "classname" "light" } { "angle" "-2" "classname" "func_door" "targetname" "t186" "model" "*99" } { "sounds" "1" "angle" "-1" "classname" "func_door" "model" "*100" } { "light" "175" "origin" "-976 -400 -192" "classname" "light" } { "classname" "light" "origin" "-968 -528 -192" "light" "175" } { "light" "175" "origin" "-968 -656 -192" "classname" "light" } { "classname" "light" "origin" "-968 -792 -192" "light" "175" } { "sounds" "4" "angle" "-1" "lip" "-120" "classname" "func_door" "targetname" "t185" "model" "*101" } { "light" "150" "origin" "-816 -656 80" "classname" "light" } { "classname" "light" "origin" "-816 -336 80" "light" "150" } { "light" "150" "origin" "-656 -336 80" "classname" "light" } { "classname" "light" "origin" "-656 -656 80" "light" "150" } { "targetname" "t182" "origin" "-828 -324 -220" "classname" "info_null" } { "targetname" "t181" "classname" "info_null" "origin" "-644 -324 -220" } { "targetname" "t184" "origin" "-644 -668 -220" "classname" "info_null" } { "targetname" "t183" "classname" "info_null" "origin" "-828 -668 -220" } { "target" "t181" "origin" "-656 -336 64" "classname" "light" } { "target" "t182" "classname" "light" "origin" "-816 -336 64" } { "target" "t183" "origin" "-816 -656 64" "classname" "light" } { "target" "t184" "origin" "-656 -656 64" "classname" "light" } { "light" "250" "origin" "-768 -512 -80" "classname" "light" } { "classname" "light" "origin" "672 192 200" } { "classname" "light" "origin" "800 192 96" "light" "200" } { "light" "200" "origin" "560 192 96" "classname" "light" } { "classname" "trigger_multiple" "target" "t185" "model" "*102" } { "classname" "trigger_multiple" "target" "t186" "model" "*103" } { "classname" "item_health" "origin" "-928 -416 -224" "spawnflags" "2" } { "classname" "item_armor2" "origin" "-912 -528 -224" } { "classname" "item_artifact_super_damage" "origin" "-912 -656 -200" } { "classname" "item_health" "origin" "-928 -768 -224" } { "classname" "item_cells" "origin" "-800 -416 -224" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-800 -544 -224" "spawnflags" "1" } { "classname" "info_player_deathmatch" "origin" "256 -576 -232" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "464 -144 -104" "angle" "270" } { "classname" "weapon_supershotgun" "origin" "480 -344 -128" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "872 -336 -128" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "880 -136 -104" "angle" "270" } { "classname" "item_armorInv" "origin" "672 -600 -256" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "1432 80 -40" "angle" "270" } { "classname" "weapon_supernailgun" "origin" "1920 -1336 0" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "240 -1568 -256" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "656 -1936 200" "angle" "90" } { "classname" "weapon_lightning" "origin" "672 -1216 48" } { "classname" "item_cells" "origin" "1456 -1352 -64" } { "classname" "item_cells" "origin" "2224 -592 -64" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "672 -288 24" "angle" "270" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "680 96 24" "angle" "270" } { "classname" "light" "origin" "560 -776 -216" "light" "125" } { "light" "125" "origin" "784 -768 -216" "classname" "light" } { "classname" "func_door" "lip" "-230" "angle" "-1" "targetname" "t188" "sounds" "4" "model" "*104" } { "classname" "light" "origin" "464 -752 -32" "light" "150" } { "classname" "light" "origin" "464 -752 -48" "target" "t187" } { "classname" "info_null" "origin" "452 -764 -252" "targetname" "t187" } { "classname" "trigger_multiple" "target" "t188" "model" "*105" } { "spawnflags" "2048" "classname" "func_door" "angle" "-1" "message" "This door is opened elsewhere..." "wait" "-1" "targetname" "t176" "model" "*106" } { "classname" "trigger_teleport" "spawnflags" "2" "target" "t189" "model" "*107" } { "classname" "func_wall" "spawnflags" "2048" "model" "*108" } { "classname" "info_teleport_destination" "origin" "472 -904 8" "angle" "270" "targetname" "t189" } { "classname" "light" "origin" "1152 -240 -232" "light" "200" } { "map" "e3m5" "classname" "trigger_changelevel" "model" "*109" } { "spawnflags" "1792" "classname" "func_wall" "model" "*110" } { "classname" "item_health" "origin" "224 -704 -256" } { "origin" "288 -704 -256" "classname" "item_health" } { "light" "200" "origin" "-40 -928 -512" "classname" "light" } { "classname" "light" "origin" "-192 -936 -512" "light" "200" } { "light" "200" "origin" "-168 -1056 -512" "classname" "light" } { "classname" "light" "origin" "-576 -1176 -512" "light" "200" } { "light" "200" "origin" "-328 -1216 -512" "classname" "light" } { "classname" "light" "origin" "-336 -1072 -512" "light" "200" } { "light" "200" "origin" "-344 -904 -512" "classname" "light" } { "classname" "light" "origin" "-320 -760 -512" "light" "200" } { "light" "200" "origin" "-336 -648 -512" "classname" "light" } { "classname" "light" "origin" "-224 -544 -512" "light" "200" } { "light" "200" "origin" "-104 -624 -512" "classname" "light" } { "classname" "light" "origin" "80 -536 -512" "light" "200" } { "light" "200" "origin" "136 -688 -512" "classname" "light" } { "classname" "light" "origin" "120 -824 -512" "light" "200" } { "light" "200" "origin" "256 -832 -512" "classname" "light" } { "classname" "light" "origin" "360 -984 -512" "light" "200" } { "light" "200" "origin" "264 -1184 -512" "classname" "light" } { "classname" "light" "origin" "168 -1344 -512" "light" "200" } { "light" "200" "origin" "256 -1504 -512" "classname" "light" } { "classname" "light" "origin" "320 -1360 -512" "light" "200" } { "light" "200" "origin" "128 -1024 -512" "classname" "light" } { "target" "t190" "classname" "trigger_teleport" "model" "*111" } { "targetname" "t190" "angle" "180" "origin" "344 -576 -240" "classname" "info_teleport_destination" } { "light" "250" "origin" "304 -592 -528" "classname" "light" } { "classname" "light" "origin" "240 -992 -512" } { "origin" "1424 -624 -64" "classname" "weapon_rocketlauncher" } { "origin" "672 -576 208" "classname" "weapon_supernailgun" } { "spawnflags" "1" "origin" "712 -592 208" "classname" "item_spikes" } { "spawnflags" "2" "target" "t191" "classname" "trigger_teleport" "model" "*112" } { "angle" "270" "targetname" "t191" "origin" "672 -32 -112" "classname" "info_teleport_destination" } { "spawnflags" "2048" "classname" "func_wall" "model" "*113" } { "target" "t191" "classname" "trigger_teleport" "model" "*114" } { "spawnflags" "2048" "classname" "func_wall" "model" "*115" } { "spawnflags" "1792" "classname" "func_wall" "model" "*116" } { "spawnflags" "1792" "classname" "func_wall" "model" "*117" } { "mangle" "20 315 0" "origin" "520 -1192 248" "classname" "info_intermission" } { "classname" "trigger_secret" "model" "*118" } { "classname" "trigger_once" "target" "t192" "health" "1" "model" "*119" } { "classname" "trigger_once" "target" "t192" "health" "1" "model" "*120" } { "classname" "trigger_once" "target" "t192" "health" "1" "model" "*121" } { "classname" "trigger_once" "target" "t192" "health" "1" "model" "*122" } { "classname" "trigger_counter" "targetname" "t192" "spawnflags" "1" "count" "4" "target" "t193" "model" "*123" } { "sounds" "1" "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t193" "model" "*124" } { "classname" "light" "origin" "-840 -160 -160" "light" "150" } { "light" "150" "origin" "-840 -264 -160" "classname" "light" } { "classname" "item_shells" "origin" "-168 -1424 -264" } { "classname" "info_player_deathmatch" "origin" "-192 -1416 -240" "angle" "90" } { "classname" "trigger_teleport" "target" "t191" "model" "*125" } { "origin" "922 -574 -360" "classname" "ambient_drip" } { "origin" "1146 -598 -120" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1154 -886 -120" } { "origin" "1330 -958 -120" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1682 -958 -120" } { "origin" "1826 -798 -120" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1850 -374 -120" } { "origin" "1674 -174 -120" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "1322 -182 -120" } { "origin" "-102 -574 -536" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-350 -582 -536" } { "origin" "-350 -870 -536" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-502 -1182 -536" } { "origin" "138 -718 -536" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "266 -1214 -536" } { "origin" "266 -1446 -536" "classname" "ambient_drip" } { "spawnflags" "3585" "origin" "2112 -1512 -192" "classname" "item_spikes" } { "spawnflags" "3584" "origin" "672 -1856 200" "classname" "item_artifact_super_damage" } { "classname" "trigger_teleport" "spawnflags" "2" "target" "t191" "model" "*126" } { "classname" "func_wall" "spawnflags" "2048" "model" "*127" } { "classname" "trigger_secret" "model" "*128" } { "classname" "item_artifact_invulnerability" "origin" "-840 -224 -192" } { "classname" "trigger_secret" "model" "*129" } { "spawnflags" "1792" "classname" "func_wall" "model" "*130" } // ================================ // begin extra BSP entity list for e3m4 // ================================ // Team 1 Flag { "origin" "-112 -2128 200" "classname" "item_flag_team1" } { "origin" "180.1 -2128 200" "classname" "info_player_team1" } { "origin" "-112 -1840 200" "classname" "info_player_team1" } { "origin" "180.1 -1840 200" "classname" "info_player_team1" } { "origin" "42.7 -1840 200" "classname" "info_player_team1" } { "origin" "432.0 -1840 200" "classname" "info_player_team1" } { "origin" "432.0 -1840 200" "classname" "info_player_team1" } { "origin" "432 -2128 200" "classname" "info_player_team1" } { "origin" "289.3 -1984 200" "classname" "info_player_team1" } { "origin" "62.3 -1974.5 200" "classname" "info_player_team1" } { "origin" "105.6 -1917.1 200" "classname" "item_armorInv" } { "origin" "237.9 -1922.9 200" "classname" "weapon_supernailgun" } { "origin" "365.8 -1926.3 200" "classname" "weapon_supershotgun" } { "origin" "356.2 -2055.4 200" "classname" "item_spikes" "spawnflags" "1" } { "origin" "227.7 -2052.6 200" "classname" "item_spikes" "spawnflags" "1" } { "origin" "101.7 -2046 200" "classname" "item_shells" "spawnflags" "1" } { "origin" "108.3 -2040.6 424.0" "classname" "item_artifact_invisibility" } { "classname" "item_flag_team2" "origin" "1887 -1231 0" } { "classname" "info_player_team2" "origin" "1947 -1291 24" } { "classname" "info_player_team2" "origin" "1947 -1231 24" } { "classname" "info_player_team2" "origin" "1947 -1171 24" } { "classname" "info_player_team2" "origin" "1887 -1291 24" } { "classname" "info_player_team2" "origin" "1887 -1231 24" } { "classname" "info_player_team2" "origin" "1887 -1171 24" } // ================================ // end extra BSP entity list for e3m4 // ================================ QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m5.ent000066400000000000000000001424631475442401000252070ustar00rootroot00000000000000{ "worldtype" "1" "message" "The Wind Tunnels" "classname" "worldspawn" "wad" "gfx/metal.wad" "sounds" "11" } { "classname" "info_player_start" "origin" "608 -3128 -1304" "angle" "90" } { "classname" "trigger_push" "speed" "75" "angle" "360" "model" "*1" } { "classname" "light" "origin" "600 -2584 -24" "light" "400" } { "light" "200" "origin" "616 -1832 -224" "classname" "light" } { "speed" "75" "angle" "-1" "classname" "trigger_push" "model" "*2" } { "classname" "light" "origin" "760 -1576 -288" "light" "200" } { "classname" "trigger_push" "angle" "-1" "speed" "75" "model" "*3" } { "speed" "75" "angle" "-1" "classname" "trigger_push" "model" "*4" } { "classname" "light" "origin" "792 -2392 200" "light" "250" } { "origin" "792 -2760 200" "classname" "light" "light" "250" } { "classname" "light" "origin" "408 -2760 200" "light" "250" } { "origin" "408 -2392 200" "classname" "light" "light" "250" } { "classname" "light" "origin" "608 -2584 -1176" "light" "200" } { "classname" "light" "origin" "776 -2456 -1176" "light" "250" } { "light" "250" "origin" "424 -2456 -1176" "classname" "light" } { "classname" "light" "origin" "816 -2960 -1224" "light" "250" } { "light" "250" "origin" "400 -2952 -1224" "classname" "light" } { "classname" "light" "origin" "608 -2816 -1224" "light" "200" } { "light" "250" "origin" "752 -3128 -1208" "classname" "light" } { "classname" "light" "origin" "456 -3128 -1208" "light" "250" } { "light" "200" "origin" "480 -2768 -1048" "classname" "light" } { "classname" "light" "origin" "728 -2768 -1048" "light" "200" } { "light" "200" "origin" "728 -3000 -1048" "classname" "light" } { "classname" "light" "origin" "472 -3000 -1048" "light" "200" } { "speed" "75" "angle" "-1" "classname" "trigger_push" "model" "*5" } { "light" "200" "origin" "600 -2576 -1056" "classname" "light" } { "light" "200" "origin" "600 -2576 -608" "classname" "light" } { "light" "175" "origin" "608 -2584 -160" "classname" "light" } { "origin" "296 -2136 -160" "classname" "light" } { "classname" "light" "origin" "888 -2152 -160" } { "origin" "304 -2488 -160" "classname" "light" } { "classname" "light" "origin" "904 -2488 -160" } { "origin" "760 -2856 -160" "classname" "light" } { "classname" "light" "origin" "464 -2848 -160" } { "target" "t1" "light" "300" "origin" "712 -1832 -160" "classname" "light" } { "targetname" "t1" "origin" "700 -1832 -28" "classname" "info_null" } { "target" "t2" "classname" "light" "origin" "616 -1928 -160" "light" "300" } { "targetname" "t2" "classname" "info_null" "origin" "616 -1916 -28" } { "target" "t3" "light" "300" "origin" "520 -1832 -160" "classname" "light" } { "targetname" "t3" "origin" "532 -1832 -28" "classname" "info_null" } { "target" "t4" "classname" "light" "origin" "616 -1736 -160" "light" "300" } { "targetname" "t4" "classname" "info_null" "origin" "616 -1748 -28" } { "target" "t5" "light" "300" "origin" "680 -1768 -160" "classname" "light" } { "targetname" "t5" "origin" "676 -1772 -28" "classname" "info_null" } { "target" "t8" "light" "300" "origin" "552 -1768 -160" "classname" "light" } { "targetname" "t8" "origin" "556 -1772 -28" "classname" "info_null" } { "light" "250" "origin" "616 -1968 -208" "classname" "light" } { "classname" "light" "origin" "760 -1832 -208" "light" "250" } { "light" "250" "origin" "472 -1832 -208" "classname" "light" } { "classname" "light" "origin" "616 -1696 -208" "light" "250" } { "light" "250" "origin" "704 -1920 -208" "classname" "light" } { "classname" "light" "origin" "528 -1920 -208" "light" "250" } { "light" "250" "origin" "528 -1744 -208" "classname" "light" } { "classname" "light" "origin" "704 -1744 -208" "light" "250" } { "light" "250" "origin" "816 -1768 248" "classname" "light" } { "light" "250" "classname" "light" "origin" "400 -1760 248" } { "light" "250" "origin" "624 -1384 248" "classname" "light" } { "light" "150" "origin" "384 -2112 56" "classname" "light" } { "classname" "light" "origin" "848 -2112 56" "light" "150" } { "light" "175" "origin" "616 -2192 144" "classname" "light" } { "target" "t15" "light" "300" "origin" "760 -1480 -160" "classname" "light" } { "targetname" "t15" "origin" "760 -1492 -28" "classname" "info_null" } { "target" "t11" "classname" "light" "origin" "472 -1480 -160" "light" "300" } { "targetname" "t11" "classname" "info_null" "origin" "472 -1492 -28" } { "target" "t12" "light" "300" "origin" "568 -1576 -160" "classname" "light" } { "targetname" "t12" "origin" "556 -1576 -28" "classname" "info_null" } { "target" "t14" "classname" "light" "origin" "664 -1576 -160" "light" "300" } { "targetname" "t14" "classname" "info_null" "origin" "676 -1576 -28" } { "target" "t13" "light" "300" "origin" "760 -1672 -160" "classname" "light" } { "targetname" "t13" "origin" "760 -1660 -28" "classname" "info_null" } { "target" "t9" "classname" "light" "origin" "472 -1672 -160" "light" "300" } { "targetname" "t9" "classname" "info_null" "origin" "472 -1660 -28" } { "target" "t10" "light" "300" "origin" "376 -1576 -160" "classname" "light" } { "targetname" "t10" "origin" "388 -1576 -28" "classname" "info_null" } { "target" "t16" "classname" "light" "origin" "856 -1576 -160" "light" "300" } { "targetname" "t16" "classname" "info_null" "origin" "844 -1576 -28" } { "classname" "light" "origin" "616 -2016 144" "light" "175" } { "target" "t20" "classname" "light" "origin" "824 -1512 -160" "light" "300" } { "targetname" "t20" "classname" "info_null" "origin" "820 -1516 -28" } { "target" "t19" "light" "300" "origin" "696 -1512 -160" "classname" "light" } { "targetname" "t19" "origin" "700 -1516 -28" "classname" "info_null" } { "target" "t18" "classname" "light" "origin" "536 -1512 -160" "light" "300" } { "targetname" "t18" "classname" "info_null" "origin" "532 -1516 -28" } { "target" "t17" "light" "300" "origin" "408 -1512 -160" "classname" "light" } { "targetname" "t17" "origin" "412 -1516 -28" "classname" "info_null" } { "light" "175" "origin" "616 -1344 -8" "classname" "light" } { "classname" "light" "origin" "280 -1640 -8" "light" "175" } { "light" "175" "origin" "968 -1648 -8" "classname" "light" } { "light" "200" "origin" "960 -1768 -312" "classname" "light" } { "classname" "light" "origin" "960 -1520 -312" "light" "200" } { "light" "200" "origin" "872 -1392 -312" "classname" "light" } { "classname" "light" "origin" "616 -1304 -312" "light" "200" } { "light" "200" "origin" "368 -1376 -312" "classname" "light" } { "classname" "light" "origin" "280 -1512 -312" "light" "200" } { "light" "200" "origin" "280 -1752 -312" "classname" "light" } { "light" "175" "origin" "616 -1968 256" "classname" "light" } { "origin" "616 -2808 -456" "classname" "light" } { "light" "250" "classname" "light" "origin" "608 -2448 -456" } { "origin" "616 -2144 -456" "classname" "light" } { "classname" "light" "origin" "616 -1464 -208" "light" "250" } { "light" "250" "origin" "864 -1472 -208" "classname" "light" } { "classname" "light" "origin" "368 -1472 -208" "light" "250" } { "origin" "736 -2576 -456" "classname" "light" "light" "250" } { "light" "250" "classname" "light" "origin" "608 -2704 -456" } { "origin" "480 -2568 -456" "classname" "light" "light" "250" } { "light" "100" "origin" "608 -2432 -280" "classname" "light" } { "classname" "light" "origin" "712 -2480 -280" "light" "100" } { "light" "100" "origin" "504 -2480 -280" "classname" "light" } { "classname" "light" "origin" "448 -2568 -280" "light" "100" } { "light" "100" "origin" "768 -2576 -280" "classname" "light" } { "classname" "light" "origin" "712 -2680 -280" "light" "100" } { "light" "100" "origin" "504 -2672 -280" "classname" "light" } { "classname" "light" "origin" "608 -2720 -280" "light" "100" } { "light" "150" "origin" "480 -2112 -280" "classname" "light" } { "classname" "light" "origin" "720 -2112 -280" "light" "150" } { "classname" "light" "origin" "856 -1640 128" "light" "200" } { "classname" "light" "origin" "856 -1440 312" "light" "200" } { "light" "200" "origin" "376 -1440 312" "classname" "light" } { "classname" "light" "origin" "864 -1472 80" "light" "175" } { "classname" "light" "origin" "616 -1832 -56" "light" "200" } { "classname" "light" "origin" "616 -1832 112" "light" "200" } { "classname" "light" "origin" "552 -1336 1296" "light" "150" } { "light" "150" "origin" "680 -1336 1296" "classname" "light" } { "classname" "light" "origin" "616 -1416 1424" "light" "200" } { "classname" "light" "origin" "296 -1756 1440" "light" "250" } { "light" "250" "origin" "940 -1760 1436" "classname" "light" } { "classname" "light" "origin" "768 -1968 1400" "light" "250" } { "light" "250" "origin" "464 -1976 1400" "classname" "light" } { "classname" "light" "origin" "624 -1832 1464" } { "classname" "light" "origin" "752 -1536 1280" "light" "150" } { "light" "150" "origin" "472 -1528 1280" "classname" "light" } { "classname" "light" "origin" "360 -1600 1280" "light" "150" } { "light" "150" "origin" "872 -1608 1280" "classname" "light" } { "classname" "light" "origin" "872 -1760 1280" "light" "150" } { "light" "150" "origin" "880 -1976 1280" "classname" "light" } { "classname" "light" "origin" "768 -2072 1280" "light" "150" } { "light" "150" "origin" "496 -2080 1280" "classname" "light" } { "classname" "light" "origin" "360 -1976 1280" "light" "150" } { "light" "150" "origin" "360 -1784 1280" "classname" "light" } { "classname" "light" "origin" "616 -1448 1776" "light" "250" } { "classname" "light" "origin" "864 -1432 1552" "light" "250" } { "light" "250" "origin" "384 -1440 1552" "classname" "light" } { "classname" "light" "origin" "616 -1472 1296" "light" "150" } { "classname" "light" "origin" "616 -1072 1408" "light" "200" } { "classname" "light" "origin" "616 -1072 1600" "light" "150" } { "classname" "light" "origin" "616 -1072 1728" "light" "150" } { "classname" "light" "origin" "616 -1184 1728" "light" "150" } { "light" "150" "origin" "616 -1304 1728" "classname" "light" } { "classname" "light" "origin" "616 -1480 1616" "light" "150" } { "classname" "trigger_push" "angle" "-1" "speed" "75" "model" "*6" } { "classname" "trigger_push" "speed" "100" "angle" "270" "model" "*7" } { "angle" "270" "speed" "100" "classname" "trigger_push" "model" "*8" } { "light" "250" "classname" "light" "origin" "616 -2072 1632" } { "light" "250" "origin" "616 -1632 1088" "classname" "light" } { "classname" "light" "origin" "368 -1480 1144" "light" "250" } { "light" "250" "origin" "360 -1744 1144" "classname" "light" } { "classname" "light" "origin" "360 -2008 1144" "light" "200" } { "light" "250" "origin" "616 -2016 1088" "classname" "light" } { "classname" "light" "origin" "856 -2016 1144" "light" "200" } { "light" "200" "origin" "872 -1816 1144" "classname" "light" } { "classname" "light" "origin" "864 -1520 1144" "light" "200" } { "light" "250" "origin" "832 -1184 1144" "classname" "light" } { "classname" "light" "origin" "784 -912 1144" "light" "200" } { "light" "200" "origin" "440 -912 1144" "classname" "light" } { "classname" "light" "origin" "416 -1208 1144" "light" "250" } { "classname" "light" "origin" "608 -2288 1504" "light" "250" } { "light" "250" "origin" "360 -2288 1504" "classname" "light" } { "classname" "light" "origin" "56 -2280 1504" "light" "250" } { "classname" "light" "origin" "616 -1832 1128" "light" "200" } { "light" "250" "origin" "632 -1576 600" "classname" "light" } { "classname" "light" "origin" "472 -1768 600" "light" "200" } { "light" "200" "origin" "448 -1352 600" "classname" "light" } { "classname" "light" "origin" "256 -1584 600" "light" "250" } { "light" "250" "origin" "92 -1592 676" "classname" "light" "style" "4" } { "classname" "light" "origin" "88 -1928 600" "light" "250" } { "light" "250" "origin" "480 -1960 600" "classname" "light" } { "light" "250" "origin" "40 -1432 744" "classname" "light" } { "light" "250" "origin" "192 -1208 720" "classname" "light" } { "classname" "light" "origin" "440 -1200 792" "light" "250" } { "light" "250" "origin" "592 -1216 720" "classname" "light" } { "light" "250" "origin" "336 -1736 760" "classname" "light" } { "light" "200" "origin" "56 -1728 656" "classname" "light" } { "light" "250" "origin" "740 -1464 800" "classname" "light" } { "classname" "light" "origin" "740 -1784 800" "light" "250" } { "light" "250" "origin" "-224 -2080 672" "classname" "light" } { "classname" "light" "origin" "-552 -2080 672" "light" "250" } { "origin" "56 -2280 672" "classname" "light" } { "light" "250" "origin" "64 -2280 344" "classname" "light" } { "classname" "light" "origin" "-112 -2192 344" "light" "250" } { "classname" "light" "origin" "-400 -2288 584" "light" "250" } { "light" "250" "origin" "-240 -2472 584" "classname" "light" } { "classname" "light" "origin" "104 -2472 584" "light" "250" } { "light" "250" "origin" "24 -2088 584" "classname" "light" } { "origin" "-720 -2280 648" "classname" "light" } { "light" "250" "origin" "-608 -2080 720" "classname" "light" } { "light" "250" "origin" "-320 -2152 864" "classname" "light" } { "light" "250" "origin" "-120 -2424 864" "classname" "light" } { "classname" "light" "origin" "-120 -2104 864" "light" "250" } { "classname" "light" "origin" "-720 -2280 -248" "light" "250" } { "light" "250" "origin" "-544 -2280 -248" "classname" "light" } { "light" "250" "origin" "-240 -2272 -184" "classname" "light" } { "light" "250" "origin" "56 -2288 -888" "classname" "light" } { "classname" "light" "origin" "304 -2288 -888" "light" "250" } { "light" "250" "origin" "600 -2288 -768" "classname" "light" } { "light" "200" "origin" "-336 -2528 624" "classname" "light" } { "light" "150" "origin" "-336 -2528 680" "classname" "light" } { "light" "150" "origin" "-336 -2528 808" "classname" "light" } { "light" "150" "origin" "-336 -2640 808" "classname" "light" } { "classname" "light" "origin" "-336 -2888 808" "light" "150" } { "speed" "75" "angle" "-1" "classname" "trigger_push" "model" "*9" } { "angle" "270" "speed" "100" "classname" "trigger_push" "model" "*10" } { "classname" "trigger_push" "speed" "100" "angle" "270" "model" "*11" } { "light" "200" "origin" "976 -2960 800" "classname" "light" } { "classname" "light" "origin" "768 -2960 800" "light" "200" } { "light" "200" "origin" "544 -2960 800" "classname" "light" } { "classname" "light" "origin" "320 -2960 800" "light" "200" } { "light" "200" "origin" "88 -2960 800" "classname" "light" } { "classname" "light" "origin" "-104 -2960 800" "light" "200" } { "light" "200" "origin" "-328 -2968 800" "classname" "light" } { "classname" "light" "origin" "1032 -2280 -888" "light" "250" } { "origin" "840 -2280 -848" "classname" "light" } { "classname" "light" "origin" "1336 -2280 -848" } { "light" "250 " "origin" "1336 -2280 -632" "classname" "light" } { "light" "250 " "origin" "1456 -2408 -160" "classname" "light" } { "classname" "light" "origin" "1200 -2408 -160" "light" "250 " } { "light" "250 " "origin" "1200 -2144 -160" "classname" "light" } { "classname" "light" "origin" "1464 -2144 -160" "light" "250 " } { "light" "250 " "origin" "1328 -2272 -312" "classname" "light" } { "light" "200" "origin" "1064 -2032 -72" "classname" "light" } { "classname" "light" "origin" "1080 -2520 -72" "light" "200" } { "light" "200" "origin" "1584 -2528 -72" "classname" "light" } { "classname" "light" "origin" "1560 -2048 -72" "light" "200" } { "origin" "1096 -2048 312" "classname" "light" } { "classname" "light" "origin" "1096 -2512 312" } { "origin" "1560 -2512 312" "classname" "light" } { "classname" "light" "origin" "1560 -2048 312" } { "light" "450" "origin" "1536 -2296 688" "classname" "light" } { "classname" "light" "origin" "1200 -2304 688" "light" "450" } { "angle" "360" "classname" "trigger_push" "model" "*12" } { "light" "200" "origin" "1120 -2744 824" "classname" "light" } { "classname" "light" "origin" "1288 -2744 824" "light" "200" } { "light" "200" "origin" "1472 -2744 824" "classname" "light" } { "classname" "light" "origin" "1144 -3176 824" "light" "200" } { "light" "200" "origin" "1312 -3176 824" "classname" "light" } { "classname" "light" "origin" "1496 -3176 824" "light" "200" } { "origin" "1264 -2960 824" "classname" "light" } { "classname" "light" "origin" "1552 -2960 784" } { "light" "250" "origin" "1768 -2960 720" "classname" "light" } { "speed" "150" "angle" "360" "classname" "trigger_push" "model" "*13" } { "classname" "light" "origin" "1768 -2960 384" "light" "250" } { "light" "250" "origin" "1336 -2792 384" "classname" "light" } { "classname" "light" "origin" "1336 -3128 384" "light" "250" } { "classname" "light" "origin" "1896 -2808 304" "light" "200" } { "light" "200" "origin" "1896 -3096 304" "classname" "light" } { "classname" "light" "origin" "1544 -2760 304" "light" "200" } { "light" "200" "origin" "1528 -3136 304" "classname" "light" } { "light" "250" "origin" "1952 -2360 288" "classname" "light" } { "classname" "light" "origin" "2224 -2464 288" "light" "250" } { "light" "250" "origin" "2064 -2656 288" "classname" "light" } { "classname" "light" "origin" "2224 -2976 288" "light" "250" } { "light" "250" "origin" "2016 -2968 320" "classname" "light" } { "speed" "100" "angle" "360" "classname" "trigger_push" "model" "*14" } { "light" "250" "origin" "1264 -1432 184" "classname" "light" } { "classname" "light" "origin" "1600 -1416 184" "light" "250" } { "light" "250" "origin" "1592 -1728 184" "classname" "light" } { "classname" "light" "origin" "1320 -1728 184" "light" "250" } { "light" "250" "origin" "1288 -1568 184" "classname" "light" } { "light" "250" "origin" "1248 -1408 -96" "classname" "light" } { "classname" "light" "origin" "1592 -1432 -96" "light" "250" } { "light" "250" "origin" "1592 -1720 -96" "classname" "light" } { "classname" "light" "origin" "1240 -1744 -96" "light" "250" } { "light" "250" "origin" "1448 -1584 -96" "classname" "light" } { "angle" "180" "spawnflags" "2052" "classname" "func_door_secret" "model" "*15" } { "light" "250" "origin" "1440 -1792 224" "classname" "light" } { "classname" "light" "origin" "1440 -1360 224" "light" "250" } { "light" "200" "origin" "1208 -1576 440" "classname" "light" } { "classname" "light" "origin" "1336 -1576 440" "light" "200" } { "light" "200" "origin" "1496 -1576 440" "classname" "light" } { "classname" "light" "origin" "1656 -1576 440" "light" "200" } { "classname" "light" "origin" "1016 -1576 192" "light" "200" } { "light" "200" "origin" "816 -1576 192" "classname" "light" } { "classname" "light" "origin" "760 -1568 0" "light" "200" } { "classname" "light" "origin" "472 -1576 0" "light" "200" } { "classname" "light" "origin" "472 -1576 216" "light" "200" } { "light" "200" "origin" "608 -2272 -272" "classname" "light" } { "light" "250" "origin" "336 -2632 -1184" "classname" "light" } { "classname" "light" "origin" "872 -2632 -1184" "light" "250" } { "target" "t21" "origin" "608 -2664 -1056" "classname" "light" } { "targetname" "t21" "origin" "608 -2660 -1136" "classname" "info_null" } { "target" "t22" "classname" "light" "origin" "520 -2576 -1056" } { "targetname" "t22" "classname" "info_null" "origin" "524 -2576 -1136" } { "target" "t23" "origin" "608 -2488 -1056" "classname" "light" } { "targetname" "t23" "origin" "608 -2492 -1136" "classname" "info_null" } { "target" "t24" "classname" "light" "origin" "696 -2576 -1056" } { "targetname" "t24" "classname" "info_null" "origin" "692 -2576 -1136" } { "light" "125" "origin" "704 -2664 -1024" "classname" "light" } { "classname" "light" "origin" "512 -2664 -1024" "light" "125" } { "light" "125" "origin" "512 -2480 -1024" "classname" "light" } { "classname" "light" "origin" "712 -2480 -1024" "light" "125" } { "light" "125" "origin" "696 -2920 -1304" "classname" "light" } { "classname" "light" "origin" "568 -2920 -1304" "light" "125" } { "wait" "15" "message" "Jump up here...." "classname" "trigger_multiple" "model" "*16" } { "targetname" "t29" "message" "This air tube is sealed..." "speed" "30" "classname" "func_door" "wait" "-1" "angle" "-2" "lip" "8" "sounds" "4" "spawnflags" "2048" "model" "*17" } { "classname" "light" "origin" "616 -1912 -256" "light" "125" } { "light" "125" "origin" "696 -1832 -256" "classname" "light" } { "classname" "light" "origin" "616 -1752 -256" "light" "125" } { "light" "125" "origin" "536 -1832 -256" "classname" "light" } { "message" "This air tube is sealed..." "targetname" "t28" "speed" "30" "sounds" "4" "lip" "8" "angle" "-2" "wait" "-1" "classname" "func_door" "spawnflags" "2048" "model" "*18" } { "targetname" "t25" "lip" "48" "speed" "500" "angle" "-1" "classname" "func_door" "wait" "-1" "model" "*19" } { "targetname" "t25" "sounds" "4" "wait" "-1" "angle" "-1" "speed" "500" "classname" "func_door" "model" "*20" } { "origin" "392 -1512 1792" "classname" "light" } { "classname" "light" "origin" "400 -1920 1792" } { "origin" "832 -1496 1792" "classname" "light" } { "classname" "light" "origin" "832 -1920 1792" } { "light" "200" "origin" "616 -1656 1776" "classname" "light" } { "classname" "light" "origin" "616 -1856 1776" "light" "250" } { "classname" "light" "origin" "504 -1648 1400" "light" "250" } { "light" "250" "origin" "768 -1648 1400" "classname" "light" } { "target" "t25" "classname" "trigger_once" "model" "*21" } { "light" "350" "origin" "432 -1072 1424" "classname" "light" } { "classname" "light" "origin" "800 -1072 1424" "light" "350" } { "light" "150" "origin" "616 -1208 1344" "classname" "light" } { "classname" "light" "origin" "616 -944 1344" "light" "150" } { "light" "125" "origin" "616 -1152 1288" "classname" "light" } { "classname" "light" "origin" "616 -992 1288" "light" "125" } { "light" "125" "origin" "712 -1072 1288" "classname" "light" } { "classname" "light" "origin" "520 -1072 1288" "light" "125" } { "light" "150" "origin" "800 -1072 1256" "classname" "light" } { "classname" "light" "origin" "616 -912 1256" "light" "150" } { "light" "150" "origin" "432 -1072 1256" "classname" "light" } { "light" "250" "origin" "608 -1288 1104" "classname" "light" } { "light" "175" "classname" "light" "origin" "616 -672 1112" } { "light" "250" "origin" "440 -544 1280" "classname" "light" } { "classname" "light" "origin" "792 -544 1280" "light" "250" } { "origin" "616 -832 1112" "classname" "light" "light" "175" } { "light" "125" "origin" "712 -1424 1136" "classname" "light" } { "classname" "light" "origin" "536 -1424 1136" "light" "125" } { "light" "200" "origin" "472 -1576 -168" "classname" "light" } { "light" "150" "origin" "472 -1576 432" "classname" "light" } { "classname" "light" "origin" "-240 -1592 592" "light" "250" "style" "4" } { "light" "250" "origin" "-480 -1452 592" "classname" "light" "style" "4" } { "classname" "light" "origin" "-848 -1376 592" "light" "250" "style" "4" } { "light" "250" "origin" "-688 -1632 592" "classname" "light" "style" "4" } { "classname" "light" "origin" "-848 -1860 592" "light" "250" "style" "4" } { "light" "250" "origin" "-304 -1860 592" "classname" "light" "style" "4" } { "classname" "light" "origin" "-668 -1952 592" "light" "250" "style" "4" } { "light" "250" "origin" "-80 -1376 592" "classname" "light" "style" "4" } { "light" "200" "origin" "272 -1752 896" "classname" "light" } { "classname" "light" "origin" "144 -1456 744" "light" "250" } { "classname" "light" "origin" "88 -1488 488" "light" "150" } { "light" "150" "origin" "88 -1696 488" "classname" "light" } { "classname" "light" "origin" "344 -1752 552" "light" "250" } { "classname" "light" "origin" "280 -1352 600" "light" "200" } { "light" "200" "origin" "616 -1344 600" "classname" "light" } { "classname" "light" "origin" "520 -1920 736" "light" "150" } { "light" "150" "origin" "736 -1752 736" "classname" "light" } { "classname" "light" "origin" "704 -1928 736" "light" "100" } { "targetname" "t30" "message" "This air tube is sealed..." "classname" "func_door" "wait" "-1" "angle" "-2" "lip" "8" "sounds" "4" "speed" "30" "model" "*22" } { "classname" "light" "origin" "688 -1728 528" "light" "100" } { "classname" "light" "origin" "1336 -2832 640" "light" "200" } { "light" "200" "origin" "1344 -3064 640" "classname" "light" } { "classname" "light" "origin" "1152 -2776 640" "light" "200" } { "light" "200" "origin" "1152 -3144 640" "classname" "light" } { "classname" "light" "origin" "1512 -2768 640" "light" "200" } { "light" "200" "origin" "1512 -3144 640" "classname" "light" } { "classname" "light" "origin" "1480 -2960 992" "light" "150" } { "light" "150" "origin" "1184 -2960 992" "classname" "light" } { "classname" "light" "origin" "1336 -2816 992" "light" "150" } { "light" "150" "origin" "1336 -3112 992" "classname" "light" } { "classname" "func_button" "angle" "180" "wait" "-1" "sounds" "2" "target" "t28" "model" "*23" } { "classname" "light_flame_large_yellow" "origin" "1134 -2916 296" "light" "250" } { "origin" "1134 -3038 296" "classname" "light_flame_large_yellow" "light" "250" } { "classname" "light" "origin" "1168 -2976 232" "light" "150" } { "message" "These bars are opened elsewhere..." "targetname" "t28" "classname" "func_door" "angle" "-1" "wait" "-1" "sounds" "4" "spawnflags" "2048" "model" "*24" } { "map" "e3m6" "classname" "trigger_changelevel" "model" "*25" } { "light" "125" "origin" "1608 -1576 -96" "classname" "light" } { "light" "125" "origin" "1264 -1512 -56" "classname" "light" } { "classname" "light" "origin" "1264 -1640 -56" "light" "125" } { "light" "250" "origin" "1800 -2280 304" "classname" "light" } { "light" "125" "origin" "1120 -2864 272" "classname" "light" } { "classname" "light" "origin" "1112 -3072 272" "light" "125" } { "targetname" "t28" "sounds" "4" "speed" "200" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*26" } { "light" "175" "origin" "1760 -3256 320" "classname" "light" } { "classname" "trigger_multiple" "wait" ".7" "target" "t27" "model" "*27" } { "classname" "func_illusionary" "model" "*28" } { "classname" "func_illusionary" "model" "*29" } { "classname" "light_flame_large_yellow" "origin" "1334 -2842 236" "light" "250" } { "origin" "1336 -3066 236" "classname" "light_flame_large_yellow" "light" "250" } { "classname" "light" "origin" "1336 -3028 260" "light" "125" } { "light" "125" "origin" "1338 -3102 260" "classname" "light" } { "classname" "light" "origin" "1374 -3064 260" "light" "125" } { "light" "125" "origin" "1296 -3066 260" "classname" "light" } { "light" "125" "origin" "1336 -2804 260" "classname" "light" } { "classname" "light" "origin" "1374 -2842 260" "light" "125" } { "light" "125" "origin" "1336 -2880 260" "classname" "light" } { "classname" "light" "origin" "1298 -2842 260" "light" "125" } { "target" "t29" "sounds" "2" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*30" } { "light" "200" "origin" "-614 -2498 616" "classname" "light_flame_large_yellow" } { "light" "200" "classname" "light_flame_large_yellow" "origin" "-508 -2498 616" } { "light" "150" "origin" "-560 -2464 552" "classname" "light" } { "targetname" "t45" "target" "t30" "classname" "trigger_once" "model" "*31" } { "targetname" "t29" "sounds" "4" "wait" "-1" "angle" "180" "classname" "func_door" "lip" "64" "spawnflags" "32" "model" "*32" } { "spawnflags" "2048" "classname" "trigger_once" "target" "t29" "model" "*33" } { "classname" "light" "origin" "-712 -2280 -136" "light" "200" } { "classname" "light" "origin" "-264 -2280 -352" "light" "150" } { "light" "150" "origin" "-96 -2288 -352" "classname" "light" } { "classname" "light" "origin" "16 -2280 -632" "light" "250" } { "classname" "info_teleport_destination" "origin" "608 -2276 -304" "angle" "90" "targetname" "t31" } { "classname" "trigger_teleport" "target" "t31" "model" "*34" } { "classname" "item_shells" "origin" "856 -2592 -1272" } { "classname" "item_health" "origin" "792 -2872 -1272" } { "origin" "792 -2920 -1272" "classname" "item_health" } { "classname" "item_spikes" "origin" "360 -2536 -1272" "spawnflags" "1" } { "classname" "path_corner" "origin" "864 -1952 -312" "target" "t34" "targetname" "t35" } { "origin" "864 -2344 -312" "classname" "path_corner" "targetname" "t34" "target" "t35" } { "classname" "path_corner" "origin" "408 -2352 -312" "target" "t32" "targetname" "t33" } { "origin" "408 -1944 -312" "classname" "path_corner" "targetname" "t32" "target" "t33" } { "classname" "monster_demon1" "origin" "784 -2264 -296" "spawnflags" "769" "angle" "270" "target" "t34" } { "classname" "monster_demon1" "origin" "416 -2032 -296" "angle" "90" "spawnflags" "1" "target" "t32" } { "origin" "600 -2784 -320" "classname" "item_health" } { "classname" "item_health" "origin" "648 -2784 -320" } { "origin" "816 -1768 -304" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "776 -1816 -304" } { "angle" "270" "origin" "624 -2832 -296" "classname" "monster_demon1" "spawnflags" "768" } { "targetname" "t36" "spawnflags" "1" "angle" "90" "origin" "616 -1720 280" "classname" "monster_wizard" } { "targetname" "t36" "angle" "90" "origin" "760 -1472 112" "classname" "monster_wizard" "spawnflags" "256" } { "targetname" "t36" "classname" "monster_wizard" "origin" "424 -1472 24" "angle" "90" } { "target" "t36" "classname" "trigger_once" "model" "*35" } { "targetname" "t28" "angle" "90" "origin" "1760 -3216 216" "classname" "monster_demon1" "spawnflags" "256" } { "angle" "270" "origin" "760 -944 1256" "classname" "monster_ogre" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "456 -944 1256" "angle" "270" } { "classname" "trigger_secret" "model" "*36" } { "origin" "448 -688 1232" "classname" "item_health" } { "classname" "item_health" "origin" "448 -640 1232" } { "spawnflags" "1" "origin" "752 -464 1232" "classname" "item_spikes" } { "origin" "16 -2072 536" "classname" "item_artifact_envirosuit" } { "target" "t37" "health" "1" "wait" "-1" "angle" "0" "classname" "func_button" "model" "*37" } { "targetname" "t37" "sounds" "1" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*38" } { "light" "225" "origin" "1856 -2024 336" "classname" "light" } { "classname" "trigger_secret" "model" "*39" } { "angle" "270" "origin" "1416 -1448 184" "classname" "monster_wizard" } { "angle" "90" "origin" "1408 -1712 184" "classname" "monster_wizard" } { "classname" "light" "origin" "1160 -2296 -72" "light" "200" } { "classname" "light" "origin" "1096 -2304 312" } { "light" "225" "origin" "1648 -2280 312" "classname" "light" } { "angle" "270" "origin" "1336 -2752 600" "classname" "monster_ogre" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "1336 -3168 600" "angle" "90" } { "spawnflags" "1" "origin" "360 -2584 -1272" "classname" "item_spikes" } { "light" "200" "origin" "1344 -1680 -264" "classname" "light" } { "classname" "light" "origin" "1496 -1680 -264" "light" "200" } { "light" "200" "origin" "1352 -1472 -264" "classname" "light" } { "classname" "light" "origin" "1496 -1472 -264" "light" "200" } { "classname" "trigger_secret" "model" "*40" } { "spawnflags" "1" "origin" "1368 -1472 -352" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "1432 -1472 -352" "spawnflags" "1" } { "origin" "1384 -1728 -352" "classname" "item_health" } { "classname" "item_health" "origin" "1440 -1728 -352" } { "targetname" "t47" "angle" "0" "origin" "104 -1212 656" "classname" "info_teleport_destination" } { "angle" "270" "origin" "368 -1264 664" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "528 -1232 664" "angle" "270" } { "target" "t38" "classname" "trigger_once" "spawnflags" "256" "model" "*41" } { "targetname" "t38" "angle" "315" "origin" "-232 -1320 536" "classname" "monster_demon1" "spawnflags" "256" } { "targetname" "t40" "target" "t39" "origin" "-768 -1376 536" "classname" "path_corner" } { "target" "t40" "targetname" "t39" "classname" "path_corner" "origin" "-440 -1376 536" } { "spawnflags" "1" "target" "t40" "origin" "-616 -1368 552" "classname" "monster_demon1" } { "targetname" "t42" "target" "t41" "origin" "-768 -1576 528" "classname" "path_corner" "spawnflags" "256" } { "target" "t42" "targetname" "t41" "classname" "path_corner" "origin" "-768 -1888 528" "spawnflags" "256" } { "spawnflags" "257" "target" "t42" "angle" "90" "origin" "-760 -1696 544" "classname" "monster_demon1" } { "targetname" "t44" "target" "t43" "origin" "-384 -2112 528" "classname" "path_corner" } { "target" "t44" "targetname" "t43" "classname" "path_corner" "origin" "-384 -2352 528" } { "spawnflags" "1" "target" "t44" "origin" "-400 -2240 544" "classname" "monster_hell_knight" } { "spawnflags" "257" "angle" "225" "origin" "-188 -2080 832" "classname" "monster_wizard" } { "spawnflags" "257" "angle" "315" "origin" "-616 -2080 832" "classname" "monster_wizard" } { "spawnflags" "1" "angle" "180" "origin" "-48 -2072 536" "classname" "monster_ogre" } { "targetname" "t46" "angle" "180" "origin" "56 -2232 -392" "classname" "monster_wizard" "spawnflags" "1" } { "targetname" "t46" "classname" "monster_wizard" "origin" "-32 -2336 -392" "angle" "180" "spawnflags" "1" } { "target" "t46" "classname" "trigger_once" "model" "*42" } { "light" "250" "origin" "-928 -1216 552" "classname" "light" } { "target" "t47" "classname" "trigger_teleport" "model" "*43" } { "light" "125" "origin" "-800 -1280 336" "classname" "light" } { "classname" "light" "origin" "-800 -1376 336" "light" "125" } { "light" "125" "origin" "-768 -1200 336" "classname" "light" } { "classname" "light" "origin" "-936 -1208 336" "light" "125" } { "light" "125" "origin" "-944 -1376 336" "classname" "light" } { "classname" "trigger_secret" "model" "*44" } { "angle" "0" "origin" "264 -2240 1504" "classname" "monster_wizard" "spawnflags" "1" } { "classname" "monster_wizard" "origin" "232 -2368 1504" "angle" "0" "spawnflags" "257" } { "target" "t46" "classname" "trigger_once" "model" "*45" } { "targetname" "t29" "spawnflags" "2048" "lip" "64" "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "4" "message" "These bars seal your fate..." "model" "*46" } { "light" "200" "origin" "-888 -1288 296" "classname" "light" } { "origin" "624 -1224 640" "classname" "item_health" } { "classname" "item_health" "origin" "576 -1224 640" } { "origin" "368 -1208 664" "classname" "item_artifact_super_damage" } { "spawnflags" "1" "origin" "-944 -1296 256" "classname" "item_spikes" } { "origin" "-544 -1456 512" "classname" "item_health" } { "classname" "item_health" "origin" "-448 -1456 512" } { "origin" "-728 -1608 512" "classname" "item_shells" } { "origin" "-72 -2496 512" "classname" "item_rockets" } { "classname" "item_rockets" "origin" "-24 -2496 512" } { "spawnflags" "2048" "origin" "-640 -2072 512" "classname" "item_health" } { "spawnflags" "2048" "classname" "item_health" "origin" "-640 -2120 512" } { "spawnflags" "1" "origin" "360 -1712 -304" "classname" "item_health" } { "classname" "item_health" "origin" "360 -1752 -304" "spawnflags" "1" } { "spawnflags" "1" "origin" "448 -1424 -304" "classname" "item_cells" } { "origin" "344 -1352 448" "classname" "item_shells" } { "classname" "item_shells" "origin" "392 -1352 448" } { "origin" "432 -1960 448" "classname" "item_health" } { "classname" "item_health" "origin" "384 -1960 448" } { "origin" "40 -1752 448" "classname" "item_spikes" "spawnflags" "1" } { "origin" "-480 -1824 512" "classname" "item_spikes" "spawnflags" "1" } { "sounds" "4" "wait" "-1" "angle" "-2" "classname" "func_door" "lip" "64" "spawnflags" "2048" "targetname" "t28" "message" "These bars seal your fate..." "model" "*47" } { "classname" "monster_wizard" "origin" "400 -1536 1600" "angle" "315" "spawnflags" "768" } { "angle" "225" "origin" "816 -1528 1600" "classname" "monster_wizard" } { "classname" "monster_wizard" "origin" "792 -1904 1600" "angle" "135" "spawnflags" "256" } { "classname" "item_health" "origin" "760 -1640 1312" } { "classname" "item_shells" "origin" "440 -1632 1312" } { "origin" "440 -1688 1312" "classname" "item_shells" } { "classname" "item_spikes" "origin" "536 -920 1232" } { "origin" "664 -920 1232" "classname" "item_spikes" } { "classname" "item_rockets" "origin" "600 -1968 1072" "spawnflags" "1" } { "classname" "trigger_teleport" "spawnflags" "2" "target" "t54" "targetname" "t28" "model" "*48" } { "classname" "monster_wizard" "origin" "-24 -2664 1136" "angle" "0" "target" "t49" } { "classname" "path_corner" "origin" "408 -2720 -80" "target" "t48" "targetname" "t49" } { "origin" "800 -2720 -80" "classname" "path_corner" "targetname" "t48" "target" "t49" } { "classname" "info_intermission" "origin" "872 -2768 -40" "mangle" "18 125 0" } { "classname" "info_intermission" "origin" "1416 -2272 232" "mangle" "60 180 0" } { "classname" "info_intermission" "origin" "616 -1992 1448" "mangle" "-15 90 0" } { "classname" "trigger_multiple" "wait" ".7" "target" "t50" "model" "*49" } { "classname" "path_corner" "origin" "2088 -2528 200" "target" "t51" "targetname" "t52" } { "origin" "2120 -2720 200" "classname" "path_corner" "targetname" "t51" "target" "t52" } { "classname" "monster_ogre" "origin" "2176 -2824 216" "target" "t51" } { "classname" "trigger_once" "target" "t53" "model" "*50" } { "classname" "monster_ogre" "origin" "1952 -2320 216" "angle" "0" "targetname" "t53" "spawnflags" "257" } { "angle" "0" "origin" "1952 -2232 216" "classname" "monster_ogre" "targetname" "t53" "spawnflags" "257" } { "classname" "item_spikes" "origin" "2184 -2936 192" "spawnflags" "1" } { "spawnflags" "1" "origin" "2184 -2984 192" "classname" "item_spikes" } { "classname" "item_artifact_super_damage" "origin" "1336 -2960 608" } { "classname" "item_health" "origin" "1432 -2768 584" } { "origin" "1496 -2768 584" "classname" "item_health" } { "classname" "item_health" "origin" "1136 -2768 200" } { "origin" "1184 -2768 200" "classname" "item_health" } { "classname" "item_cells" "origin" "1288 -3192 200" } { "classname" "item_health" "origin" "1688 -3272 200" "spawnflags" "1" } { "classname" "item_armor1" "origin" "1816 -3256 200" } { "classname" "item_armor1" "origin" "616 -912 1232" } { "classname" "info_teleport_destination" "origin" "376 -2680 -88" "angle" "0" "targetname" "t54" } { "classname" "item_health" "origin" "2200 -2720 192" } { "origin" "2200 -2768 192" "classname" "item_health" } { "classname" "monster_shambler" "origin" "1712 -2040 216" "angle" "270" "spawnflags" "1" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t57" "targetname" "t28" "model" "*51" } { "angle" "0" "origin" "-192 -2712 1136" "classname" "monster_wizard" "target" "t55" "spawnflags" "256" } { "classname" "path_corner" "origin" "616 -2048 -40" "target" "t55" "targetname" "t56" "spawnflags" "256" } { "origin" "608 -2352 -40" "classname" "path_corner" "targetname" "t55" "target" "t56" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "600 -2424 -40" "angle" "90" "targetname" "t57" } { "classname" "item_health" "origin" "1352 -2032 -128" } { "origin" "1304 -2032 -128" "classname" "item_health" } { "classname" "item_shells" "origin" "1112 -2552 -128" } { "origin" "1056 -2496 -128" "classname" "item_shells" } { "classname" "monster_demon1" "origin" "1096 -2040 -104" "angle" "0" } { "classname" "item_health" "origin" "1736 -2552 200" } { "classname" "item_spikes" "origin" "1648 -2632 200" } { "origin" "1104 -1944 200" "classname" "item_spikes" } { "classname" "item_health" "origin" "1264 -1936 200" "spawnflags" "1" } { "spawnflags" "1" "origin" "1312 -1936 200" "classname" "item_health" } { "classname" "item_health" "origin" "1368 -1936 200" "spawnflags" "1" } { "classname" "item_artifact_envirosuit" "origin" "1864 -1968 224" } { "classname" "item_spikes" "origin" "1848 -2032 200" "spawnflags" "1" } { "classname" "item_health" "origin" "1848 -2080 200" } { "classname" "monster_ogre" "origin" "1256 -1432 -144" "angle" "0" "spawnflags" "256" } { "spawnflags" "256" "classname" "item_health" "origin" "1600 -1472 -168" } { "origin" "1600 -1512 -168" "classname" "item_health" } { "classname" "path_corner" "origin" "-656 -1880 520" "targetname" "t59" "target" "t58" } { "origin" "-392 -1880 520" "classname" "path_corner" "targetname" "t58" "target" "t59" } { "classname" "monster_demon1" "origin" "-520 -1872 536" "angle" "0" "target" "t58" "spawnflags" "1" } { "origin" "760 -1688 1312" "classname" "item_health" } { "classname" "item_health" "origin" "264 -2264 1384" "spawnflags" "1" } { "spawnflags" "1" "origin" "312 -2264 1384" "classname" "item_health" } { "classname" "item_shells" "origin" "592 -2264 1384" } { "classname" "monster_hell_knight" "origin" "1240 -3008 216" "angle" "0" } { "angle" "0" "origin" "1240 -2904 216" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "item_rockets" "origin" "1696 -2816 192" } { "classname" "item_spikes" "origin" "1760 -2816 192" } { "origin" "1352 -3192 200" "classname" "item_cells" } { "origin" "1884 -2252 192" "classname" "item_health" } { "classname" "item_spikes" "origin" "1820 -2292 192" "spawnflags" "1" } { "classname" "item_health" "origin" "400 -1088 1232" "spawnflags" "1537" } { "classname" "item_spikes" "origin" "-352 -2544 584" "spawnflags" "2049" } { "classname" "monster_wizard" "origin" "1248 -2232 -392" "angle" "0" "targetname" "t60" "spawnflags" "256" } { "angle" "0" "origin" "1248 -2336 -448" "classname" "monster_wizard" "targetname" "t60" "spawnflags" "256" } { "classname" "trigger_once" "target" "t60" "spawnflags" "256" "model" "*52" } { "spawnflags" "768" "classname" "monster_demon1" "origin" "-216 -2272 -312" "angle" "180" } { "classname" "item_spikes" "origin" "760 -1984 1312" } { "classname" "monster_demon1" "origin" "1576 -2032 -104" "angle" "225" } { "spawnflags" "1" "origin" "360 -2288 -944" "classname" "item_health" } { "classname" "item_health" "origin" "824 -2296 -944" "spawnflags" "1" } { "classname" "light" "origin" "1264 -1640 -112" "light" "125" } { "classname" "light" "origin" "1264 -1512 -112" "light" "125" } { "classname" "func_wall" "spawnflags" "1792" "model" "*53" } { "classname" "weapon_supershotgun" "origin" "608 -2272 -312" "spawnflags" "1792" } { "classname" "weapon_rocketlauncher" "origin" "-384 -2280 520" "spawnflags" "1792" } { "classname" "weapon_supernailgun" "origin" "1336 -2960 192" "spawnflags" "1792" } { "classname" "info_player_coop" "origin" "672 -2976 -1312" "angle" "90" } { "angle" "90" "origin" "536 -2976 -1312" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "432 -2992 -1240" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "608 -3024 -1312" "angle" "90" } { "spawnflags" "1792" "classname" "weapon_nailgun" "origin" "376 -2624 -1272" } { "classname" "info_player_deathmatch" "origin" "2208 -2216 216" "angle" "225" } { "classname" "weapon_grenadelauncher" "origin" "1104 -2048 -128" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "1336 -1584 -168" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "1552 -1584 -144" "angle" "180" } { "classname" "info_player_deathmatch" "origin" "832 -1072 1256" "angle" "180" } { "classname" "weapon_nailgun" "origin" "616 -1072 1248" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "696 -1384 472" "angle" "180" } { "classname" "weapon_supernailgun" "origin" "424 -1848 448" "spawnflags" "1792" } { "spawnflags" "2048" "origin" "604 -1848 -248" "classname" "item_spikes" } { "target" "t54" "classname" "trigger_teleport" "model" "*54" } { "light" "150" "origin" "1488 -2272 520" "classname" "light" } { "classname" "monster_shambler" "origin" "1712 -2472 216" "angle" "90" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "1760 -3216 216" "angle" "90" "spawnflags" "1536" "targetname" "t28" } { "spawnflags" "768" "angle" "0" "origin" "1272 -1720 -144" "classname" "monster_ogre" } { "classname" "monster_hell_knight" "origin" "664 -1488 472" "angle" "225" "spawnflags" "768" } { "classname" "item_armor1" "origin" "664 -1576 456" "spawnflags" "3072" } { "spawnflags" "1024" "angle" "180" "origin" "-240 -2272 -312" "classname" "monster_ogre" } { "classname" "item_health" "origin" "744 -1592 -248" } { "classname" "monster_demon1" "origin" "616 -1240 1256" "angle" "270" "spawnflags" "769" } { "classname" "item_rockets" "origin" "2152 -2232 192" "spawnflags" "768" } { "target" "t31" "spawnflags" "1792" "classname" "trigger_teleport" "model" "*55" } { "spawnflags" "1792" "classname" "func_wall" "model" "*56" } { "light" "125" "origin" "-56 -1824 712" "classname" "light" } { "light" "125" "origin" "32 -1824 688" "classname" "light" } { "classname" "light" "origin" "88 -1928 688" "light" "125" } { "light" "150" "origin" "312 -1928 688" "classname" "light" } { "light" "125" "origin" "64 -1760 904" "classname" "light" } { "classname" "light" "origin" "264 -1928 904" "light" "125" } { "spawnflags" "1" "origin" "-72 -1840 640" "classname" "item_rockets" } { "spawnflags" "2048" "origin" "608 -448 1232" "classname" "weapon_rocketlauncher" } { "light" "125" "origin" "-96 -1592 536" "classname" "light" } { "speed" "100" "angle" "90" "classname" "trigger_push" "model" "*57" } { "angle" "90" "speed" "50" "classname" "trigger_push" "model" "*58" } { "classname" "ambient_suck_wind" "origin" "610 -2910 -1216" } { "origin" "602 -2614 -1216" "classname" "ambient_suck_wind" } { "classname" "ambient_suck_wind" "origin" "618 -1982 -264" } { "origin" "866 -1662 -264" "classname" "ambient_suck_wind" } { "classname" "ambient_suck_wind" "origin" "370 -1654 -264" } { "origin" "610 -1534 -264" "classname" "ambient_suck_wind" } { "classname" "ambient_suck_wind" "origin" "602 -2382 -240" } { "classname" "ambient_suck_wind" "origin" "474 -1574 592" } { "classname" "ambient_suck_wind" "origin" "-326 -2406 592" } { "classname" "ambient_suck_wind" "origin" "1202 -2958 640" } { "classname" "ambient_suck_wind" "origin" "618 -1734 1424" } { "classname" "ambient_suck_wind" "origin" "618 -1078 1312" } { "classname" "ambient_suck_wind" "origin" "1274 -1574 120" } { "origin" "738 -2254 -392" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "442 -2262 -392" } { "origin" "434 -1878 -392" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "890 -1798 -392" } { "origin" "402 -1398 -392" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "850 -1398 -392" } { "origin" "826 -2822 -392" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "394 -2822 -392" } { "spawnflags" "1" "origin" "608 -2776 -576" "classname" "item_health" } { "classname" "item_health" "origin" "656 -2776 -576" "spawnflags" "1" } { "origin" "-702 -2278 -256" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-406 -2286 -256" } { "origin" "-22 -2286 -256" "classname" "ambient_drip" } { "origin" "130 -2294 -888" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "626 -2286 -888" } { "origin" "1130 -2270 -888" "classname" "ambient_drip" } { "origin" "610 -830 1296" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "610 -462 1296" } { "origin" "858 -1222 1296" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "346 -1198 1296" } { "origin" "858 -1598 1296" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "322 -1638 1296" } { "origin" "618 -2070 1296" "classname" "ambient_drip" } { "light" "150" "origin" "608 -3136 -1232" "classname" "light" } { "target" "t61" "targetname" "t30" "spawnflags" "2" "classname" "trigger_teleport" "model" "*59" } { "targetname" "t30" "angle" "0" "origin" "-776 -2712 1136" "classname" "monster_wizard" } { "target" "t62" "targetname" "t30" "classname" "trigger_teleport" "spawnflags" "2" "model" "*60" } { "spawnflags" "256" "targetname" "t30" "classname" "monster_wizard" "origin" "-776 -2832 1136" "angle" "0" } { "targetname" "t61" "angle" "0" "origin" "-472 -2168 664" "classname" "info_teleport_destination" } { "targetname" "t62" "classname" "info_teleport_destination" "origin" "-472 -2392 664" "angle" "0" } { "origin" "96 -1448 448" "classname" "weapon_lightning" } { "classname" "item_health" "origin" "592 -472 1232" "spawnflags" "1794" } { "classname" "item_spikes" "origin" "752 -512 1232" "spawnflags" "2049" } { "classname" "item_shells" "origin" "701 -2238 -320" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "701 -2296 -320" } { "classname" "item_shells" "origin" "701 -2354 -320" "spawnflags" "1" } { "classname" "item_spikes" "origin" "585 -2238 -320" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "585 -2296 -316" } { "classname" "item_spikes" "origin" "585 -2354 -320" "spawnflags" "1" } { "classname" "item_shells" "origin" "1309 -2907 192" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "1309 -2965 192" } { "classname" "item_shells" "origin" "1309 -3023 192" "spawnflags" "1" } { "classname" "item_spikes" "origin" "1193 -2907 192" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "1193 -2965 192" } { "classname" "item_spikes" "origin" "1193 -3023 192" "spawnflags" "1" } { "classname" "item_health" "origin" "1251 -2907 192" } { "classname" "item_armor2" "origin" "1251 -2965 192" } { "classname" "item_health" "origin" "643 -2238 -320" } { "classname" "item_armor2" "origin" "643 -2296 -316" } { "classname" "weapon_supernailgun" "origin" "621 -1397 448" } { "classname" "item_shells" "origin" "621 -1455 448" "spawnflags" "1" } { "classname" "item_spikes" "origin" "505 -1339 448" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "505 -1397 448" } { "classname" "item_spikes" "origin" "505 -1455 448" "spawnflags" "1" } { "classname" "item_health" "origin" "643 -2354 -320" } { "classname" "item_flag_team1" "origin" "228 -1587 736" } { "classname" "info_player_team1" "origin" "347 -1888 472" } { "classname" "info_player_team1" "origin" "347 -1828 472" } { "classname" "info_player_team1" "origin" "347 -1768 472" } { "classname" "info_player_team1" "origin" "287 -1888 472" } { "classname" "info_player_team1" "origin" "287 -1828 472" } { "classname" "info_player_team1" "origin" "287 -1768 472" } { "classname" "info_player_team1" "origin" "227 -1888 472" } { "classname" "info_player_team1" "origin" "227 -1828 472" } { "classname" "item_flag_team2" "origin" "1108 -2967 576" } { "classname" "info_player_team2" "origin" "1168 -3027 600" } { "classname" "info_player_team2" "origin" "1168 -2967 600" } { "classname" "info_player_team2" "origin" "1168 -2907 600" } { "classname" "info_player_team2" "origin" "1108 -3027 600" } { "classname" "info_player_team2" "origin" "1108 -2967 600" } { "classname" "info_player_team2" "origin" "1108 -2907 600" } { "classname" "info_player_team2" "origin" "563 -1397 448" } { "classname" "info_player_team2" "origin" "563 -1455 448" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m6.ent000066400000000000000000001751251475442401000252110ustar00rootroot00000000000000{ "sounds" "4" "wad" "gfx/metal.wad" "classname" "worldspawn" "worldtype" "1" "message" "Chambers of Torment" } { "classname" "info_player_start" "origin" "-1088 -288 32" "angle" "270" } { "classname" "light" "origin" "464 -1640 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "-96 -624 80" "angle" "0" "light" "200" } { "classname" "light" "origin" "-96 -928 112" "angle" "0" "light" "250" } { "classname" "light" "origin" "-96 -1440 112" "angle" "0" "light" "300" } { "classname" "light" "origin" "592 -1152 32" "angle" "0" "light" "200" } { "classname" "light" "origin" "944 -928 16" "angle" "0" "light" "200" } { "classname" "light" "origin" "688 -736 96" "angle" "0" } { "classname" "light" "origin" "-32 -208 112" "angle" "0" "light" "100" } { "classname" "light" "origin" "96 -208 112" "angle" "0" "light" "100" } { "classname" "light" "origin" "-32 -496 112" "angle" "0" "light" "100" } { "classname" "light" "origin" "96 -496 112" "angle" "0" "light" "100" } { "classname" "light" "origin" "-128 -304 64" "angle" "0" "light" "100" } { "classname" "light" "origin" "-128 -400 64" "angle" "0" "light" "100" } { "classname" "light" "origin" "-64 -352 144" "angle" "0" "light" "200" } { "classname" "light" "origin" "32 -352 144" "angle" "0" "light" "200" } { "classname" "light" "origin" "160 -352 144" "angle" "0" "light" "200" } { "classname" "light" "origin" "480 -416 128" "angle" "0" "light" "200" } { "classname" "light" "origin" "480 -288 48" "angle" "0" "light" "200" } { "classname" "light" "origin" "160 -576 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "288 -576 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "480 -672 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "480 -800 64" "angle" "0" "light" "200" } { "classname" "light" "origin" "128 -896 128" "angle" "0" "light" "250" } { "classname" "info_player_deathmatch" "origin" "744 -1224 -16" "angle" "45" } { "classname" "light" "origin" "256 -1904 48" "angle" "0" "light" "200" } { "classname" "light" "origin" "40 -1928 56" "angle" "0" "light" "200" } { "classname" "light" "origin" "-64 -2232 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-156 -2236 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-252 -2228 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-380 -2180 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-380 -2084 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-372 -1988 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-380 -1892 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-324 -1764 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-228 -1764 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-124 -1764 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-20 -2180 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-20 -2076 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-192 -1968 -48" "angle" "0" "light" "200" } { "classname" "light" "origin" "-192 -1856 -64" "angle" "0" "light" "200" } { "classname" "light" "origin" "-184 -1976 72" "angle" "0" "light" "150" } { "classname" "light" "origin" "-192 -2160 -96" "angle" "0" "light" "150" } { "classname" "light" "origin" "-96 -224 16" "light" "150" } { "light" "150" "origin" "32 -232 16" "classname" "light" } { "classname" "light" "origin" "160 -224 16" "light" "150" } { "light" "150" "origin" "-96 -480 16" "classname" "light" } { "classname" "light" "origin" "32 -472 16" "light" "150" } { "light" "150" "origin" "160 -480 16" "classname" "light" } { "light" "150" "origin" "-256 -352 16" "classname" "light" } { "classname" "light" "origin" "288 -296 64" "light" "150" } { "light" "150" "origin" "288 -408 64" "classname" "light" } { "light" "150" "origin" "416 -168 64" "classname" "light" } { "origin" "-1288 -520 152" "classname" "light" } { "origin" "-1208 -904 152" "classname" "light" } { "classname" "light" "origin" "-952 -904 152" } { "classname" "light" "origin" "-1088 -1152 168" "light" "200" } { "classname" "light" "origin" "-608 -928 168" "light" "200" } { "origin" "-448 -616 104" "classname" "light" "light" "200" } { "classname" "light" "origin" "-488 -320 160" "light" "150" } { "origin" "-712 -360 -120" "classname" "light" "light" "250" } { "classname" "light" "origin" "-672 -544 -120" "light" "250" } { "origin" "-944 -424 -120" "classname" "light" } { "classname" "light" "origin" "-1256 -584 -120" } { "origin" "-1472 -360 -120" "classname" "light" "light" "250" } { "classname" "light" "origin" "-1552 -536 -120" "light" "250" } { "classname" "light" "origin" "-928 -764 64" "light" "200" } { "light" "200" "origin" "-1248 -764 64" "classname" "light" } { "classname" "light" "origin" "-928 -764 180" "light" "200" } { "light" "200" "origin" "-1248 -764 180" "classname" "light" } { "light" "400" "target" "t2" "origin" "-1656 -352 120" "classname" "light" } { "targetname" "t2" "origin" "-1916 -356 76" "classname" "info_null" } { "light" "400" "target" "t3" "classname" "light" "origin" "-1656 -600 120" } { "targetname" "t3" "classname" "info_null" "origin" "-1916 -604 76" } { "target" "t4" "light" "400" "origin" "-1536 -680 152" "classname" "light" } { "targetname" "t4" "origin" "-1540 -940 12" "classname" "info_null" } { "light" "200" "origin" "-1848 -1016 136" "classname" "light" } { "light" "150" "origin" "-1592 -760 72" "classname" "light" } { "classname" "light" "origin" "-1480 -760 72" "light" "150" } { "light" "150" "origin" "-1920 -360 176" "classname" "light" } { "classname" "light" "origin" "-1920 -600 176" "light" "150" } { "classname" "light" "origin" "-592 -720 352" "light" "200" } { "light" "200" "origin" "-1648 -720 352" "classname" "light" } { "light" "200" "origin" "-1088 -1344 168" "classname" "light" } { "classname" "light" "origin" "-848 -1536 168" "light" "200" } { "light" "200" "origin" "-1088 -1536 168" "classname" "light" } { "light" "200" "origin" "-608 -1536 168" "classname" "light" } { "classname" "light" "origin" "-608 -1320 168" "light" "200" } { "classname" "light" "origin" "-608 -1152 136" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "-977 -281 44" } { "origin" "-1201 -281 44" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "416 -488 64" "light" "150" } { "classname" "light" "origin" "-704 -616 72" "target" "t5" "light" "350" } { "classname" "info_null" "origin" "-644 -668 20" "targetname" "t5" } { "classname" "light" "origin" "-616 -792 168" "light" "150" } { "classname" "light" "origin" "-608 -880 48" "light" "150" } { "light" "150" "origin" "-400 -320 160" "classname" "light" } { "classname" "light" "origin" "-400 -672 160" "light" "150" } { "light" "150" "origin" "-496 -672 160" "classname" "light" } { "light" "200" "classname" "light" "origin" "-448 -392 104" } { "classname" "light" "origin" "-448 -304 248" "light" "150" } { "light" "150" "origin" "-448 -552 248" "classname" "light" } { "classname" "light" "origin" "-448 -696 248" "light" "150" } { "light" "200" "angle" "0" "origin" "680 -928 16" "classname" "light" } { "classname" "light" "origin" "944 -1120 16" "angle" "0" "light" "200" } { "light" "250" "angle" "0" "origin" "832 -1232 16" "classname" "light" } { "classname" "light" "origin" "800 -1712 -32" "light" "200" } { "classname" "light" "origin" "952 -1352 400" "light" "175" } { "origin" "648 -1352 400" "classname" "light" "light" "175" } { "origin" "800 -1400 344" "classname" "light" "light" "175" } { "classname" "light" "origin" "896 -1688 -124" "target" "t8" } { "origin" "704 -1688 -124" "classname" "light" "target" "t9" } { "classname" "info_null" "origin" "896 -1612 -152" "targetname" "t8" } { "origin" "704 -1612 -152" "classname" "info_null" "targetname" "t9" } { "classname" "light" "origin" "704 -1688 -96" "light" "150" } { "light" "150" "origin" "896 -1688 -96" "classname" "light" } { "classname" "light" "origin" "608 -1496 96" "light" "150" } { "light" "150" "origin" "1000 -1496 96" "classname" "light" } { "classname" "light" "origin" "800 -1312 96" "light" "150" } { "classname" "light" "origin" "912 -1600 0" "light" "150" } { "light" "150" "origin" "688 -1608 0" "classname" "light" } { "classname" "light" "origin" "688 -1392 0" "light" "150" } { "light" "150" "origin" "912 -1392 0" "classname" "light" } { "classname" "light" "origin" "616 -1592 320" "light" "200" } { "light" "200" "origin" "992 -1600 320" "classname" "light" } { "origin" "288 -2792 224" "classname" "light" } { "classname" "light" "origin" "288 -3080 224" } { "light" "175" "origin" "194 -3414 154" "classname" "light" } { "classname" "light" "origin" "376 -3416 154" "light" "175" } { "light" "175" "origin" "376 -3600 154" "classname" "light" } { "classname" "light" "origin" "190 -3602 154" "light" "175" } { "light" "200" "origin" "528 -2480 288" "classname" "light" } { "light" "200" "origin" "524 -2696 304" "classname" "light" } { "light" "150" "origin" "520 -2576 480" "classname" "light" } { "classname" "light" "origin" "48 -2480 288" "light" "200" } { "classname" "light" "origin" "56 -2576 480" "light" "150" } { "light" "200" "origin" "728 -2408 480" "classname" "light" } { "classname" "light" "origin" "-112 -2408 480" "light" "200" } { "light" "200" "origin" "288 -2416 256" "classname" "light" } { "light" "200" "origin" "216 -2824 48" "classname" "light" } { "classname" "light" "origin" "216 -2952 48" "light" "200" } { "light" "200" "origin" "208 -3184 48" "classname" "light" } { "classname" "light" "origin" "208 -3296 48" "light" "200" } { "light" "200" "origin" "368 -3296 48" "classname" "light" } { "classname" "light" "origin" "376 -3184 48" "light" "200" } { "light" "200" "origin" "360 -2952 48" "classname" "light" } { "classname" "light" "origin" "360 -2824 48" "light" "200" } { "light" "200" "origin" "288 -3360 400" "classname" "light" } { "classname" "light" "origin" "136 -3504 400" "light" "200" } { "light" "150" "origin" "284 -3508 400" "classname" "light" } { "light" "150" "origin" "172 -3508 388" "classname" "light" } { "classname" "light" "origin" "284 -3620 388" "light" "150" } { "light" "150" "origin" "284 -3396 388" "classname" "light" } { "classname" "light" "origin" "396 -3508 388" "light" "150" } { "target" "t11" "origin" "524 -2676 144" "classname" "light" } { "targetname" "t11" "origin" "524 -2668 196" "classname" "info_null" } { "target" "t12" "classname" "light" "origin" "472 -2628 144" } { "targetname" "t12" "classname" "info_null" "origin" "480 -2628 196" } { "target" "t13" "origin" "104 -2624 144" "classname" "light" } { "targetname" "t13" "origin" "96 -2624 196" "classname" "info_null" } { "target" "t14" "classname" "light" "origin" "48 -2676 144" } { "targetname" "t14" "classname" "info_null" "origin" "48 -2672 196" } { "classname" "light" "origin" "48 -2700 304" "light" "200" } { "classname" "light_flame_large_yellow" "origin" "744 -2850 248" } { "origin" "744 -3298 248" "classname" "light_flame_large_yellow" } { "origin" "-130 -2850 248" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-130 -3290 248" } { "light" "200" "origin" "752 -3176 552" "classname" "light" } { "classname" "light" "origin" "752 -3656 552" "light" "200" } { "light" "200" "origin" "616 -3656 552" "classname" "light" } { "classname" "light" "origin" "752 -2584 552" "light" "200" } { "light" "200" "origin" "752 -2736 552" "classname" "light" } { "classname" "light" "origin" "752 -2976 552" "light" "200" } { "classname" "light" "origin" "752 -3440 552" "light" "200" } { "classname" "light" "origin" "464 -3656 552" "light" "200" } { "light" "200" "origin" "288 -3656 552" "classname" "light" } { "classname" "light" "origin" "112 -3656 552" "light" "200" } { "light" "200" "origin" "-8 -3656 552" "classname" "light" } { "classname" "light" "origin" "-136 -3656 552" "light" "200" } { "light" "200" "origin" "-136 -3456 552" "classname" "light" } { "classname" "light" "origin" "-136 -3184 552" "light" "200" } { "light" "200" "origin" "-136 -2968 552" "classname" "light" } { "classname" "light" "origin" "-136 -2736 552" "light" "200" } { "light" "200" "origin" "-136 -2568 552" "classname" "light" } { "classname" "light" "origin" "32 -2384 552" "light" "200" } { "light" "200" "origin" "160 -2384 552" "classname" "light" } { "light" "200" "origin" "440 -2384 552" "classname" "light" } { "classname" "light" "origin" "592 -2384 552" "light" "200" } { "light" "200" "origin" "288 -2600 352" "classname" "light" } { "target" "t15" "origin" "404 -3388 136" "classname" "light" } { "targetname" "t15" "origin" "396 -3396 248" "classname" "info_null" } { "classname" "light" "origin" "408 -2688 16" "light" "200" } { "light" "200" "origin" "592 -2696 16" "classname" "light" } { "classname" "light" "origin" "664 -2592 16" "light" "150" } { "light" "200" "origin" "664 -2448 16" "classname" "light" } { "target" "t18" "classname" "light" "origin" "400 -3624 136" } { "targetname" "t18" "classname" "info_null" "origin" "392 -3616 248" } { "target" "t17" "origin" "168 -3624 136" "classname" "light" } { "targetname" "t17" "origin" "176 -3616 248" "classname" "info_null" } { "target" "t16" "classname" "light" "origin" "164 -3388 136" } { "targetname" "t16" "classname" "info_null" "origin" "172 -3396 248" } { "light" "200" "origin" "476 -3520 28" "classname" "light" } { "classname" "light" "origin" "100 -3516 28" "light" "200" } { "light" "200" "origin" "608 -3640 232" "classname" "light" } { "classname" "light" "origin" "8 -3640 232" "light" "200" } { "light" "200" "origin" "168 -2696 16" "classname" "light" } { "classname" "light" "origin" "-16 -2704 16" "light" "200" } { "light" "150" "origin" "-88 -2600 16" "classname" "light" } { "classname" "light" "origin" "-96 -2456 16" "light" "200" } { "light" "125" "origin" "56 -2576 312" "classname" "light" } { "classname" "light" "origin" "520 -2576 312" "light" "125" } { "light" "150" "origin" "688 -2848 192" "classname" "light" } { "classname" "light" "origin" "688 -3296 192" "light" "150" } { "light" "150" "origin" "-72 -3288 192" "classname" "light" } { "classname" "light" "origin" "-72 -2848 192" "light" "150" } { "target" "t19" "origin" "376 -2592 416" "classname" "light" } { "targetname" "t19" "origin" "380 -2588 492" "classname" "info_null" } { "target" "t20" "classname" "light" "origin" "200 -2592 416" } { "targetname" "t20" "classname" "info_null" "origin" "196 -2588 492" } { "target" "t21" "origin" "-80 -2592 416" "classname" "light" } { "targetname" "t21" "origin" "-76 -2588 492" "classname" "info_null" } { "target" "t22" "classname" "light" "origin" "656 -2592 416" } { "targetname" "t22" "classname" "info_null" "origin" "652 -2588 492" } { "light" "150" "origin" "600 -1712 -96" "classname" "light" } { "classname" "light" "origin" "1008 -1712 -96" "light" "150" } { "light" "150" "origin" "1008 -1304 -96" "classname" "light" } { "classname" "light" "origin" "600 -1304 -96" "light" "150" } { "classname" "light_flame_small_yellow" "origin" "472 -1436 -32" "light" "200" } { "light" "200" "origin" "472 -1252 -32" "classname" "light_flame_small_yellow" } { "light" "200" "origin" "396 -1096 -32" "classname" "light_flame_small_yellow" } { "classname" "light_flame_small_yellow" "origin" "172 -1096 -32" "light" "200" } { "classname" "light" "origin" "-1552 -248 -152" "light" "200" } { "classname" "light" "origin" "-1504 -160 -216" "light" "150" } { "light" "150" "origin" "-1504 -16 -216" "classname" "light" } { "classname" "light" "origin" "-1664 -16 -216" "light" "150" } { "light" "150" "origin" "-1904 -16 -216" "classname" "light" } { "classname" "light" "origin" "-1808 -120 -216" "light" "150" } { "light" "150" "origin" "-1600 -120 -216" "classname" "light" } { "classname" "light" "origin" "-1904 -200 -216" "light" "150" } { "classname" "func_plat" "spawnflags" "1" "model" "*1" } { "light" "150" "origin" "-1804 -200 -216" "classname" "light" } { "classname" "light" "origin" "-1856 -240 -116" "light" "150" } { "classname" "light" "origin" "-1856 -240 -28" "light" "150" } { "classname" "light" "origin" "-1856 -240 104" "light" "150" } { "classname" "light" "origin" "-1856 -124 104" "light" "200" } { "classname" "light" "origin" "-1856 -216 -232" "light" "150" } { "light" "150" "origin" "-1856 -144 -232" "classname" "light" } { "classname" "light" "origin" "-1856 -64 -232" "light" "150" } { "light" "150" "origin" "-1744 -64 -232" "classname" "light" } { "classname" "light" "origin" "-1640 -64 -232" "light" "150" } { "light" "150" "origin" "-1552 -64 -232" "classname" "light" } { "classname" "light" "origin" "-1552 -128 -232" "light" "150" } { "light" "150" "origin" "-1552 -208 -232" "classname" "light" } { "classname" "light" "origin" "-1736 -68 200" "light" "350" "target" "t23" } { "classname" "info_null" "origin" "-1736 -68 148" "targetname" "t23" } { "classname" "light" "origin" "-1748 -112 -80" "light" "75" } { "light" "75" "origin" "-1600 -112 -80" "classname" "light" } { "classname" "light" "origin" "-1752 -16 -80" "light" "75" } { "light" "75" "origin" "-1620 -16 -80" "classname" "light" } { "classname" "light" "origin" "-1504 -16 -80" "light" "75" } { "light" "75" "origin" "-1504 -128 -80" "classname" "light" } { "light" "350" "origin" "-1652 -68 200" "classname" "light" "target" "t24" } { "origin" "-1652 -68 148" "classname" "info_null" "targetname" "t24" } { "classname" "info_null" "origin" "-1556 -68 148" "targetname" "t25" } { "classname" "light" "origin" "-1556 -68 200" "light" "350" "target" "t25" } { "light" "350" "origin" "-1552 -172 200" "classname" "light" "target" "t26" } { "origin" "-1552 -172 148" "classname" "info_null" "targetname" "t26" } { "classname" "light" "origin" "-1860 -40 228" "light" "150" } { "classname" "light" "origin" "-1736 -480 160" "light" "200" } { "classname" "light" "origin" "-2032 -304 160" "light" "150" } { "light" "150" "origin" "-2032 -656 160" "classname" "light" } { "classname" "func_train" "target" "t27" "sounds" "1" "model" "*2" } { "classname" "path_corner" "origin" "-320 -1888 -18" "targetname" "t27" "target" "t28" } { "origin" "-320 -2240 -18" "classname" "path_corner" "targetname" "t28" "target" "t27" } { "origin" "-192 -1888 -18" "classname" "path_corner" "target" "t29" "targetname" "t30" } { "classname" "path_corner" "origin" "-192 -2240 -18" "targetname" "t29" "target" "t30" } { "spawnflags" "1" "classname" "func_train" "target" "t29" "model" "*3" } { "classname" "light" "origin" "288 -1488 -104" "light" "150" } { "classname" "light" "origin" "296 -1600 -144" "light" "150" } { "classname" "light" "origin" "288 -2288 304" "light" "200" } { "light" "200" "origin" "152 -2288 304" "classname" "light" } { "classname" "light" "origin" "288 -2288 -152" "light" "175" } { "classname" "func_plat" "spawnflags" "1" "model" "*4" } { "classname" "light" "origin" "288 -1456 -192" "light" "200" } { "classname" "light" "origin" "312 -1688 -232" "light" "200" "target" "t31" } { "classname" "info_null" "origin" "312 -1692 -196" "targetname" "t31" } { "light" "200" "origin" "232 -1688 -232" "classname" "light" "target" "t32" } { "origin" "232 -1692 -196" "classname" "info_null" "targetname" "t32" } { "classname" "light" "origin" "152 -1688 -232" "light" "200" "target" "t33" } { "classname" "info_null" "origin" "152 -1692 -196" "targetname" "t33" } { "light" "200" "origin" "88 -1688 -232" "classname" "light" "target" "t34" } { "origin" "92 -1692 -196" "classname" "info_null" "targetname" "t34" } { "classname" "light" "origin" "232 -1576 -232" "light" "200" "target" "t35" } { "classname" "info_null" "origin" "232 -1572 -196" "targetname" "t35" } { "light" "200" "origin" "152 -1576 -232" "classname" "light" "target" "t36" } { "origin" "152 -1572 -196" "classname" "info_null" "targetname" "t36" } { "classname" "light" "origin" "52 -1576 -232" "light" "200" "target" "t37" } { "classname" "info_null" "origin" "52 -1572 -196" "targetname" "t37" } { "classname" "light" "origin" "320 -1576 -232" "light" "200" "target" "t38" } { "classname" "info_null" "origin" "320 -1572 -196" "targetname" "t38" } { "light" "200" "origin" "376 -1632 -232" "classname" "light" "target" "t39" } { "origin" "380 -1632 -196" "classname" "info_null" "targetname" "t39" } { "light" "200" "origin" "-24 -1576 -232" "classname" "light" "target" "t40" } { "origin" "-28 -1572 -196" "classname" "info_null" "targetname" "t40" } { "light" "200" "origin" "-24 -1656 -232" "classname" "light" "target" "t47" } { "origin" "-28 -1656 -196" "classname" "info_null" "targetname" "t47" } { "classname" "light" "origin" "-24 -1756 -232" "light" "200" "target" "t46" } { "classname" "info_null" "origin" "-28 -1756 -196" "targetname" "t46" } { "light" "200" "origin" "-24 -1852 -232" "classname" "light" "target" "t45" } { "origin" "-28 -1852 -196" "classname" "info_null" "targetname" "t45" } { "classname" "light" "origin" "-24 -1948 -232" "light" "200" "target" "t44" } { "classname" "info_null" "origin" "-28 -1948 -196" "targetname" "t44" } { "light" "200" "origin" "-24 -2044 -232" "classname" "light" "target" "t43" } { "origin" "-28 -2044 -196" "classname" "info_null" "targetname" "t43" } { "classname" "light" "origin" "-24 -2144 -232" "light" "200" "target" "t42" } { "classname" "info_null" "origin" "-28 -2144 -196" "targetname" "t42" } { "light" "200" "origin" "-24 -2248 -232" "classname" "light" "target" "t41" } { "origin" "-28 -2248 -196" "classname" "info_null" "targetname" "t41" } { "light" "200" "origin" "88 -1760 -232" "classname" "light" "target" "t53" } { "origin" "92 -1760 -196" "classname" "info_null" "targetname" "t53" } { "classname" "light" "origin" "88 -1852 -232" "light" "200" "target" "t52" } { "classname" "info_null" "origin" "92 -1852 -196" "targetname" "t52" } { "light" "200" "origin" "88 -1948 -232" "classname" "light" "target" "t51" } { "origin" "92 -1948 -196" "classname" "info_null" "targetname" "t51" } { "classname" "light" "origin" "88 -2044 -232" "light" "200" "target" "t50" } { "classname" "info_null" "origin" "92 -2044 -196" "targetname" "t50" } { "light" "200" "origin" "88 -2144 -232" "classname" "light" "target" "t49" } { "origin" "92 -2144 -196" "classname" "info_null" "targetname" "t49" } { "classname" "light" "origin" "88 -2232 -232" "light" "200" "target" "t48" } { "classname" "info_null" "origin" "92 -2228 -196" "targetname" "t48" } { "classname" "light" "origin" "44 -2344 -232" "light" "200" "target" "t54" } { "classname" "info_null" "origin" "44 -2348 -196" "targetname" "t54" } { "light" "200" "origin" "164 -2344 -232" "classname" "light" "target" "t55" } { "origin" "164 -2348 -196" "classname" "info_null" "targetname" "t55" } { "classname" "light" "origin" "164 -2232 -232" "light" "200" "target" "t56" } { "classname" "info_null" "origin" "164 -2228 -196" "targetname" "t56" } { "classname" "light" "origin" "272 -1636 -184" "light" "120" } { "light" "120" "origin" "192 -1636 -184" "classname" "light" } { "classname" "light" "origin" "112 -1636 -184" "light" "120" } { "light" "120" "origin" "16 -1620 -184" "classname" "light" } { "classname" "light" "origin" "32 -1712 -184" "light" "120" } { "light" "120" "origin" "32 -1800 -184" "classname" "light" } { "classname" "light" "origin" "32 -1904 -184" "light" "120" } { "light" "120" "origin" "32 -1992 -184" "classname" "light" } { "classname" "light" "origin" "32 -2096 -184" "light" "120" } { "light" "120" "origin" "32 -2208 -184" "classname" "light" } { "classname" "light" "origin" "16 -2304 -184" "light" "120" } { "light" "120" "origin" "112 -2296 -184" "classname" "light" } { "classname" "light" "origin" "200 -2288 -184" "light" "100" } { "light" "150" "origin" "-256 -1824 48" "classname" "light" } { "classname" "light" "origin" "-128 -2176 48" "light" "150" } { "light" "150" "origin" "-480 -2048 144" "classname" "light" } { "light" "150" "origin" "-480 -2368 144" "classname" "light" } { "classname" "light" "origin" "-480 -2528 144" "light" "150" } { "light" "150" "origin" "-368 -2624 144" "classname" "light" } { "classname" "light" "origin" "-256 -2720 144" "light" "150" } { "light" "150" "origin" "-256 -2880 144" "classname" "light" } { "classname" "light" "origin" "-256 -3064 144" "light" "150" } { "classname" "light" "origin" "744 -1816 336" "light" "150" } { "light" "150" "origin" "856 -1816 336" "classname" "light" } { "classname" "light" "origin" "744 -1816 112" "light" "125" } { "light" "125" "origin" "856 -1816 112" "classname" "light" } { "classname" "light" "origin" "744 -1816 -48" "light" "125" } { "light" "125" "origin" "856 -1816 -48" "classname" "light" } { "classname" "light" "origin" "1112 -2624 96" "light" "200" } { "light" "200" "origin" "1216 -2512 96" "classname" "light" } { "classname" "light" "origin" "1344 -2616 96" "light" "200" } { "light" "200" "origin" "1224 -2736 96" "classname" "light" } { "classname" "trap_spikeshooter" "origin" "1216 -2608 40" "spawnflags" "1" "angle" "135" "targetname" "t76" } { "angle" "180" "spawnflags" "1" "origin" "1396 -2620 42" "classname" "trap_spikeshooter" "targetname" "t76" } { "wait" ".8" "classname" "trigger_multiple" "target" "t76" "model" "*5" } { "targetname" "t76" "spawnflags" "1" "angle" "90" "origin" "1220 -2764 298" "classname" "trap_spikeshooter" } { "targetname" "t76" "spawnflags" "1" "angle" "0" "origin" "1052 -2620 298" "classname" "trap_spikeshooter" } { "targetname" "t76" "spawnflags" "1" "angle" "135" "origin" "1216 -2608 298" "classname" "trap_spikeshooter" } { "targetname" "t76" "classname" "trap_spikeshooter" "origin" "1232 -2608 298" "angle" "45" "spawnflags" "1" } { "targetname" "t76" "spawnflags" "1" "angle" "315" "origin" "1232 -2624 298" "classname" "trap_spikeshooter" } { "targetname" "t76" "classname" "trap_spikeshooter" "origin" "1216 -2624 298" "angle" "225" "spawnflags" "1" } { "targetname" "t76" "angle" "135" "origin" "1216 -2608 184" "classname" "trap_spikeshooter" } { "targetname" "t76" "classname" "trap_spikeshooter" "origin" "1232 -2608 184" "angle" "45" } { "targetname" "t76" "angle" "315" "origin" "1232 -2624 184" "classname" "trap_spikeshooter" } { "targetname" "t76" "classname" "trap_spikeshooter" "origin" "1216 -2624 184" "angle" "225" } { "targetname" "t76" "angle" "225" "spawnflags" "1" "origin" "1216 -2624 40" "classname" "trap_spikeshooter" } { "targetname" "t76" "classname" "trap_spikeshooter" "origin" "1232 -2624 40" "spawnflags" "1" "angle" "315" } { "targetname" "t76" "angle" "45" "spawnflags" "1" "origin" "1232 -2608 40" "classname" "trap_spikeshooter" } { "targetname" "t76" "angle" "270" "spawnflags" "1" "origin" "1228 -2464 42" "classname" "trap_spikeshooter" } { "light" "200" "origin" "1228 -2476 380" "classname" "light" } { "classname" "light" "origin" "1388 -2620 380" "light" "200" } { "light" "200" "origin" "1220 -2756 380" "classname" "light" } { "classname" "light" "origin" "1060 -2620 380" "light" "200" } { "classname" "func_illusionary" "model" "*6" } { "classname" "light" "origin" "1324 -2540 524" "light" "175" } { "light" "175" "origin" "1324 -2696 524" "classname" "light" } { "classname" "light" "origin" "1124 -2540 524" "light" "175" } { "light" "175" "origin" "1128 -2692 524" "classname" "light" } { "classname" "light" "origin" "1340 -2524 264" "light" "120" } { "light" "120" "origin" "1108 -2524 264" "classname" "light" } { "classname" "light" "origin" "1108 -2712 264" "light" "120" } { "light" "120" "origin" "1340 -2708 264" "classname" "light" } { "classname" "func_plat" "spawnflags" "1" "model" "*7" } { "sounds" "1" "target" "t140" "classname" "func_door" "angle" "0" "spawnflags" "2064" "wait" "-1" "model" "*8" } { "wait" "-1" "spawnflags" "2064" "angle" "180" "classname" "func_door" "model" "*9" } { "spawnflags" "2048" "classname" "item_key1" "origin" "576 -1152 -24" } { "light" "200" "origin" "-1536 -1048 112" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "416 -576 80" "light" "200" } { "classname" "light" "origin" "800 -1824 -128" "light" "200" } { "classname" "light" "origin" "-1088 -480 48" "light" "200" } { "light" "200" "origin" "-1088 -720 48" "classname" "light" } { "classname" "light" "origin" "-1088 -880 104" "light" "200" } { "classname" "light" "origin" "-1696 -1000 72" "light" "150" } { "classname" "light" "origin" "96 -752 80" "light" "250" } { "wait" "-1" "spawnflags" "2056" "angle" "0" "classname" "func_door" "model" "*10" } { "sounds" "1" "classname" "func_door" "angle" "180" "spawnflags" "2056" "wait" "-1" "model" "*11" } { "classname" "light" "origin" "268 -2288 -48" "light" "200" } { "classname" "light" "origin" "268 -2288 72" "light" "200" } { "classname" "light" "origin" "-1448 -272 152" } { "origin" "-752 -280 152" "classname" "light" } { "classname" "light" "origin" "704 -336 112" } { "classname" "light" "origin" "688 -120 240" "light" "200 " } { "light" "200 " "origin" "896 -120 240" "classname" "light" } { "classname" "light" "origin" "896 -280 240" "light" "200 " } { "light" "200 " "origin" "896 -424 240" "classname" "light" } { "classname" "info_null" "origin" "948 -284 68" "targetname" "t77" } { "classname" "light" "origin" "704 -284 72" "light" "350" "target" "t77" } { "origin" "948 -420 68" "classname" "info_null" "targetname" "t78" } { "light" "350" "origin" "704 -420 72" "classname" "light" "target" "t78" } { "origin" "768 -68 68" "classname" "info_null" "targetname" "t79" } { "light" "350" "origin" "768 -312 72" "classname" "light" "target" "t79" } { "classname" "light" "origin" "860 -92 72" "light" "125" } { "light" "125" "origin" "924 -176 72" "classname" "light" } { "light" "100" "origin" "624 -120 80" "classname" "light" } { "light" "150" "origin" "488 -120 80" "classname" "light" } { "speed" "50" "sounds" "4" "targetname" "t80" "wait" "4" "angle" "-2" "classname" "func_door" "model" "*12" } { "target" "t80" "angle" "-2" "wait" "4" "classname" "func_button" "model" "*13" } { "light" "150" "origin" "96 -96 56" "classname" "light" } { "classname" "light" "origin" "296 -120 80" "light" "150" } { "light" "150" "origin" "192 -120 80" "classname" "light" } { "classname" "light" "origin" "32 -8 80" "light" "150" } { "wait" "-1" "speed" "50" "angle" "-2" "classname" "func_door" "targetname" "t84" "sounds" "4" "model" "*14" } { "targetname" "t81" "speed" "50" "sounds" "1" "angle" "-2" "wait" "-1" "classname" "func_door" "model" "*15" } { "target" "t81" "classname" "trigger_once" "model" "*16" } { "light" "125" "origin" "888 -592 72" "classname" "light" } { "classname" "light" "origin" "1040 -568 72" "light" "125" } { "light" "150" "origin" "1024 -656 72" "classname" "light" } { "classname" "light" "origin" "1008 -824 72" "light" "125" } { "light" "150" "origin" "1024 -768 64" "classname" "light" } { "angle" "180" "classname" "trigger_monsterjump" "model" "*17" } { "light" "150" "origin" "752 -928 248" "classname" "light" } { "classname" "light" "origin" "752 -1152 248" "light" "150" } { "light" "150" "origin" "1008 -1160 248" "classname" "light" } { "classname" "light" "origin" "1008 -928 248" "light" "150" } { "light" "150" "origin" "832 -1056 248" "classname" "light" } { "light" "125" "origin" "696 -1064 128" "classname" "light" } { "targetname" "t82" "wait" "-1" "angle" "180" "classname" "func_door" "speed" "150" "sounds" "4" "model" "*18" } { "target" "t82" "classname" "trigger_once" "model" "*19" } { "light" "125" "origin" "840 -976 136" "classname" "light" } { "classname" "light" "origin" "840 -1120 136" "light" "125" } { "light" "250" "origin" "8 -752 112" "classname" "light" } { "light" "200" "origin" "288 -1072 -48" "classname" "light" } { "light" "200" "origin" "288 -976 -8" "classname" "light" } { "sounds" "1" "wait" "-1" "angle" "90" "classname" "func_door" "targetname" "t83" "message" "This door is opened elsewhere..." "model" "*20" } { "classname" "func_door" "angle" "270" "wait" "-1" "sounds" "1" "model" "*21" } { "classname" "func_button" "angle" "90" "wait" "-1" "target" "t83" "model" "*22" } { "classname" "func_button" "angle" "-1" "wait" "-1" "health" "1" "target" "t84" "model" "*23" } { "light" "200" "origin" "-184 -1620 112" "classname" "light_flame_small_yellow" } { "classname" "light" "origin" "112 -1632 80" "light" "150" } { "spawnflags" "2048" "classname" "item_key2" "origin" "392 -1544 24" } { "classname" "light" "origin" "104 -1212 -120" "light" "150" } { "light" "150" "origin" "108 -1376 -120" "classname" "light" } { "classname" "light" "origin" "104 -1212 44" "light" "150" } { "light" "150" "origin" "108 -1376 44" "classname" "light" } { "light" "175" "origin" "320 -1792 64" "classname" "light" } { "target" "t85" "origin" "192 -1448 56" "classname" "light" } { "targetname" "t85" "origin" "192 -1560 4" "classname" "info_null" } { "light" "120" "origin" "248 -1524 20" "classname" "light" } { "classname" "light" "origin" "328 -1524 20" "light" "120" } { "target" "t86" "classname" "light" "origin" "364 -1448 56" } { "targetname" "t86" "classname" "info_null" "origin" "364 -1560 4" } //{ //"target" "t87" //"wait" "-1" //"angle" "-2" //"classname" "func_button" //"model" "*24" //} //{ //"message" "These bars are opened elsewhere..." //"targetname" "t87" //"angle" "-1" //"wait" "-1" //"classname" "func_door" //"sounds" "4" //"model" "*25" //} { "light" "250" "origin" "-784 -696 -96" "classname" "light" } { "light" "200" "origin" "-784 -696 136" "classname" "light" } { "light" "150" "origin" "-1824 -728 136" "classname" "light" } { "sounds" "1" "lip" "2" "targetname" "t88" "wait" "-1" "speed" "300" "angle" "-2" "classname" "func_door" "model" "*26" } { "target" "t88" "classname" "trigger_once" "model" "*27" } { "light" "150" "origin" "-448 -176 80" "classname" "light" } { "targetname" "t161" "speed" "200" "sounds" "1" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*28" } { "light" "150" "origin" "-640 -2264 88" "classname" "light" } { "classname" "light" "origin" "-632 -2520 88" "light" "150" } { "light" "150" "origin" "-632 -2392 88" "classname" "light" } { "target" "t89" "wait" "-1" "angle" "-2" "classname" "func_button" "model" "*29" } { "target" "t89" "angle" "-2" "wait" "-1" "classname" "func_button" "model" "*30" } { "target" "t89" "wait" "-1" "angle" "-2" "classname" "func_button" "model" "*31" } { "light" "100" "origin" "-464 -2552 16" "classname" "light" } { "classname" "light" "origin" "-504 -2424 16" "light" "100" } { "light" "100" "origin" "-456 -2296 16" "classname" "light" } { "light" "150" "origin" "800 -1984 400" "classname" "light" } { "light" "150" "classname" "light" "origin" "800 -2144 400" } { "light" "150" "origin" "1024 -2144 400" "classname" "light" } { "light" "150" "classname" "light" "origin" "1224 -2144 400" } { "light" "150" "origin" "1224 -2304 400" "classname" "light" } { "target" "t90" "origin" "800 -1984 376" "classname" "light" } { "targetname" "t90" "origin" "800 -1984 324" "classname" "info_null" } { "targetname" "t91" "classname" "info_null" "origin" "800 -2144 324" } { "targetname" "t92" "origin" "1024 -2144 324" "classname" "info_null" } { "targetname" "t93" "classname" "info_null" "origin" "1224 -2144 324" } { "targetname" "t94" "origin" "1224 -2304 324" "classname" "info_null" } { "target" "t91" "classname" "light" "origin" "800 -2144 376" } { "target" "t92" "origin" "1024 -2144 376" "classname" "light" } { "target" "t93" "classname" "light" "origin" "1224 -2144 376" } { "target" "t94" "origin" "1224 -2304 376" "classname" "light" } { "light" "130" "origin" "744 -1960 328" "classname" "light" } { "classname" "light" "origin" "856 -1960 328" "light" "130" } { "light" "130" "origin" "744 -2152 328" "classname" "light" } { "classname" "light" "origin" "832 -2176 328" "light" "130" } { "light" "130" "origin" "1024 -2112 328" "classname" "light" } { "classname" "light" "origin" "1024 -2184 328" "light" "130" } { "light" "130" "origin" "1256 -2168 328" "classname" "light" } { "classname" "light" "origin" "1256 -2360 328" "light" "130" } { "light" "130" "origin" "1192 -2360 328" "classname" "light" } { "light" "100" "origin" "1224 -2584 464" "classname" "light" } { "light" "100" "origin" "1224 -2584 392" "classname" "light" } { "light" "100" "origin" "1224 -2584 328" "classname" "light" } { "light" "100" "origin" "1224 -2584 224" "classname" "light" } { "light" "100" "origin" "1224 -2584 144" "classname" "light" } { "light" "120" "origin" "1200 -2168 328" "classname" "light" } { "light" "120" "origin" "1176 -2096 328" "classname" "light" } { "sounds" "3" "speed" "50" "targetname" "t95" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*32" } { "health" "1" "target" "t95" "angle" "-1" "wait" "-1" "classname" "func_button" "model" "*33" } { "light" "250" "origin" "800 -1496 -104" "classname" "light" } { "light" "150" "origin" "600 -1344 -24" "classname" "light" } { "light" "120" "origin" "688 -1424 -104" "classname" "light" } { "classname" "light" "origin" "688 -1568 -104" "light" "120" } { "light" "120" "origin" "912 -1568 -104" "classname" "light" } { "classname" "light" "origin" "912 -1424 -104" "light" "120" } { "classname" "light" "origin" "720 -1392 -104" "light" "120" } { "light" "120" "origin" "880 -1392 -104" "classname" "light" } { "spawnflags" "257" "targetname" "t98" "classname" "monster_ogre" "origin" "-2008 -576 88" "angle" "180" } { "targetname" "t118" "angle" "180" "origin" "-1728 -480 88" "classname" "monster_hell_knight" "spawnflags" "1" } { "target" "t97" "classname" "trigger_once" "model" "*34" } { "target" "t98" "classname" "trigger_once" "model" "*35" } { "target" "t98" "classname" "trigger_once" "model" "*36" } { "target" "t100" "targetname" "t99" "origin" "-1536 -992 8" "classname" "path_corner" } { "targetname" "t100" "target" "t99" "classname" "path_corner" "origin" "-1536 -880 8" } { "target" "t100" "angle" "90" "origin" "-1520 -976 24" "classname" "monster_ogre" "spawnflags" "1" } { "spawnflags" "1" "targetname" "t97" "angle" "180" "origin" "-936 -1472 104" "classname" "monster_hell_knight" } { "target" "t102" "targetname" "t101" "origin" "-896 -1544 88" "classname" "path_corner" } { "target" "t101" "targetname" "t102" "classname" "path_corner" "origin" "-592 -1536 88" } { "target" "t101" "spawnflags" "1" "angle" "180" "origin" "-744 -1544 104" "classname" "monster_ogre" } { "spawnflags" "257" "targetname" "t103" "angle" "180" "origin" "-1744 -64 104" "classname" "monster_wizard" } { "spawnflags" "256" "target" "t103" "classname" "trigger_once" "model" "*37" } { "targetname" "t88" "angle" "270" "origin" "-448 -200 24" "classname" "monster_demon1" } { "spawnflags" "257" "targetname" "t104" "angle" "270" "origin" "-472 -464 24" "classname" "monster_ogre" } { "target" "t104" "classname" "trigger_once" "spawnflags" "256" "model" "*38" } { "targetname" "t106" "target" "t105" "origin" "-112 -352 8" "classname" "path_corner" } { "target" "t106" "targetname" "t105" "classname" "path_corner" "origin" "184 -352 8" } { "spawnflags" "1" "target" "t105" "angle" "0" "origin" "80 -352 24" "classname" "monster_shalrath" } { "origin" "880 -104 0" "classname" "item_health" } { "classname" "item_health" "origin" "912 -144 0" } { "classname" "trigger_secret" "model" "*39" } { "targetname" "t95" "classname" "trigger_secret" "model" "*40" } { "targetname" "t111" "spawnflags" "257" "angle" "0" "origin" "624 -1592 80" "classname" "monster_ogre" } { "targetname" "t111" "spawnflags" "1" "classname" "monster_ogre" "origin" "624 -1400 80" "angle" "0" } { "spawnflags" "257" "angle" "270" "origin" "392 -208 24" "classname" "monster_ogre" } { "origin" "-1032 -504 -16" "classname" "item_health" } { "classname" "item_health" "origin" "-1032 -552 -16" } { "spawnflags" "257" "angle" "225" "origin" "-872 -840 152" "classname" "monster_ogre" } { "origin" "-1336 -840 128" "classname" "item_shells" } { "origin" "-1336 -1000 128" "classname" "item_health" } { "classname" "item_health" "origin" "-1336 -1048 128" } { "spawnflags" "1" "origin" "-896 -728 0" "classname" "item_spikes" } { "origin" "-1648 -712 0" "classname" "item_shells" } { "spawnflags" "3585" "classname" "item_health" "origin" "-1624 -928 0" } { "spawnflags" "2048" "origin" "-1880 -816 64" "classname" "item_cells" } { "spawnflags" "2048" "classname" "item_cells" "origin" "-1880 -856 64" } { "origin" "-2040 -648 64" "classname" "item_rockets" } { "spawnflags" "1" "origin" "-1768 -328 64" "classname" "item_health" } { "origin" "-1216 -512 -224" "classname" "item_health" } { "classname" "item_health" "origin" "-1176 -464 -224" } { "target" "t109" "classname" "trigger_once" "model" "*41" } { "targetname" "t109" "target" "t107" "spawnflags" "2" "classname" "trigger_teleport" "model" "*42" } { "targetname" "t109" "target" "t108" "classname" "trigger_teleport" "spawnflags" "2" "model" "*43" } { "targetname" "t109" "angle" "270" "origin" "-1120 112 -152" "classname" "monster_wizard" } { "targetname" "t109" "classname" "monster_wizard" "origin" "-1056 112 -152" "angle" "270" } { "targetname" "t107" "origin" "-1408 -544 -16" "classname" "info_teleport_destination" } { "targetname" "t108" "origin" "-712 -280 -96" "classname" "info_teleport_destination" } { "spawnflags" "256" "targetname" "t110" "angle" "0" "origin" "688 -112 24" "classname" "monster_ogre" } { "targetname" "t110" "angle" "0" "origin" "904 -376 24" "classname" "monster_ogre" } { "target" "t110" "classname" "trigger_once" "model" "*44" } { "light" "120" "origin" "-1632 -1000 40" "classname" "light" } { "target" "t111" "classname" "trigger_once" "model" "*45" } { "origin" "592 -1672 -160" "classname" "item_spikes" } { "spawnflags" "1" "origin" "984 -1664 -160" "classname" "item_health" } { "spawnflags" "1" "classname" "item_health" "origin" "984 -1704 -160" } { "origin" "512 -1400 -160" "classname" "item_shells" "spawnflags" "1" } { "angle" "180" "origin" "960 -944 200" "classname" "monster_ogre" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "960 -1128 200" "angle" "180" } { "spawnflags" "256" "target" "t112" "targetname" "t113" "origin" "872 -712 -8" "classname" "path_corner" } { "spawnflags" "256" "target" "t113" "targetname" "t112" "classname" "path_corner" "origin" "672 -712 -8" } { "spawnflags" "257" "target" "t112" "angle" "180" "origin" "792 -704 8" "classname" "monster_hell_knight" } { "target" "t115" "targetname" "t114" "origin" "720 -912 -40" "classname" "path_corner" } { "target" "t116" "targetname" "t115" "classname" "path_corner" "origin" "720 -1208 -40" } { "target" "t117" "targetname" "t116" "origin" "904 -1216 -40" "classname" "path_corner" } { "targetname" "t117" "target" "t114" "classname" "path_corner" "origin" "904 -912 -40" } { "spawnflags" "257" "target" "t114" "angle" "180" "origin" "816 -912 -24" "classname" "monster_shalrath" } { "origin" "-624 -1624 80" "classname" "item_shells" } { "spawnflags" "2560" "classname" "item_shells" "origin" "-552 -1576 80" } { "spawnflags" "1" "origin" "-624 -648 0" "classname" "item_health" } { "target" "t118" "classname" "trigger_once" "model" "*46" } { "spawnflags" "1" "origin" "-112 -496 0" "classname" "item_health" } { "classname" "item_health" "origin" "-72 -496 0" "spawnflags" "1" } { "origin" "440 -208 0" "classname" "item_spikes" } { "spawnflags" "1" "origin" "832 -1240 -48" "classname" "item_health" } { "classname" "item_health" "origin" "888 -1240 -48" "spawnflags" "1" } { "origin" "680 -1000 -48" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "680 -1040 -48" } { "origin" "184 -24 32" "classname" "item_spikes" "spawnflags" "1" } { "origin" "112 -904 0" "classname" "item_cells" "spawnflags" "2048" } { "origin" "688 -1336 56" "classname" "item_rockets" "spawnflags" "1" //Q-Man } { "origin" "848 -1608 56" "classname" "item_health" } { "classname" "item_health" "origin" "912 -1608 56" } { "spawnflags" "1281" "angle" "90" "origin" "800 -2168 296" "classname" "monster_hell_knight" } { "targetname" "t120" "target" "t119" "origin" "1224 -2128 280" "classname" "path_corner" } { "target" "t120" "targetname" "t119" "classname" "path_corner" "origin" "1224 -2384 280" } { "target" "t119" "spawnflags" "1" "angle" "270" "origin" "1216 -2256 296" "classname" "monster_hell_knight" } { "targetname" "t124" "target" "t121" "origin" "1328 -2536 440" "classname" "path_corner" } { "target" "t122" "targetname" "t121" "classname" "path_corner" "origin" "1328 -2704 440" } { "target" "t123" "targetname" "t122" "origin" "1120 -2696 440" "classname" "path_corner" } { "target" "t124" "targetname" "t123" "classname" "path_corner" "origin" "1120 -2536 440" } { "spawnflags" "257" "target" "t124" "angle" "0" "origin" "1280 -2552 456" "classname" "monster_wizard" } { "spawnflags" "1" "target" "t122" "origin" "1176 -2688 456" "classname" "monster_wizard" } { "target" "t125" "targetname" "t126" "origin" "872 -2752 8" "classname" "path_corner" } { "target" "t126" "targetname" "t125" "classname" "path_corner" "origin" "872 -3024 8" } { "target" "t125" "angle" "270" "origin" "888 -2824 24" "classname" "monster_ogre" } { "spawnflags" "257" "angle" "45" "origin" "288 -3288 144" "classname" "monster_shalrath" } { "targetname" "t161" "spawnflags" "256" "angle" "0" "origin" "-616 -2312 24" "classname" "monster_ogre" } { "targetname" "t161" "classname" "monster_ogre" "origin" "-616 -2464 24" "angle" "0" } { "target" "t127" "targetname" "t128" "origin" "-256 -2624 8" "classname" "path_corner" } { "target" "t128" "targetname" "t127" "classname" "path_corner" "origin" "-256 -2856 8" } { "target" "t127" "spawnflags" "1" "angle" "270" "origin" "-256 -2808 24" "classname" "monster_hell_knight" } { "target" "t132" "targetname" "t131" "origin" "-448 -2504 88" "classname" "path_corner" } { "target" "t131" "targetname" "t130" "classname" "path_corner" "origin" "-512 -2504 88" } { "target" "t130" "targetname" "t129" "origin" "-512 -2088 88" "classname" "path_corner" } { "targetname" "t132" "target" "t129" "classname" "path_corner" "origin" "-456 -2088 88" } { "target" "t132" "angle" "90" "spawnflags" "257" "origin" "-464 -2120 104" "classname" "monster_wizard" } { "target" "t130" "angle" "270" "origin" "-496 -2440 104" "classname" "monster_wizard" "spawnflags" "1" } { "spawnflags" "257" "angle" "180" "origin" "-112 -2168 48" "classname" "monster_ogre" } { "targetname" "t134" "target" "t133" "origin" "-1808 -64 -176" "classname" "path_corner" } { "target" "t134" "targetname" "t133" "classname" "path_corner" "origin" "-1616 -64 -176" } { "target" "t134" "spawnflags" "1" "origin" "-1680 -64 -160" "classname" "monster_wizard" } { "targetname" "t163" "spawnflags" "1" "angle" "270" "origin" "-608 -792 192" "classname" "monster_wizard" } { "spawnflags" "1" "angle" "90" "origin" "400 -1464 -136" "classname" "monster_demon1" } { "spawnflags" "769" "classname" "monster_demon1" "origin" "168 -1464 -136" "angle" "90" } { "targetname" "t135" "spawnflags" "1" "angle" "0" "origin" "0 -1608 24" "classname" "monster_ogre" } { "target" "t135" "classname" "trigger_once" "model" "*47" } { "spawnflags" "257" "classname" "monster_wizard" "origin" "456 -1152 112" "angle" "180" } { "target" "t137" "targetname" "t136" "origin" "672 -1360 -152" "classname" "path_corner" } { "target" "t138" "targetname" "t137" "classname" "path_corner" "origin" "672 -1632 -152" } { "target" "t139" "targetname" "t138" "origin" "928 -1632 -152" "classname" "path_corner" } { "targetname" "t139" "target" "t136" "classname" "path_corner" "origin" "928 -1360 -152" } { "target" "t139" "spawnflags" "257" "origin" "968 -1424 -136" "classname" "monster_hell_knight" } { "spawnflags" "256" "angle" "270" "origin" "-608 -1144 192" "classname" "monster_wizard" } { "targetname" "t140" "angle" "90" "origin" "424 -896 24" "classname" "monster_hell_knight" } { "targetname" "t140" "classname" "monster_hell_knight" "origin" "128 -848 24" "angle" "90" "spawnflags" "256" } { "origin" "112 -616 0" "classname" "item_shells" } { "origin" "104 -1176 -160" "classname" "item_shells" } { "origin" "712 -2040 272" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "712 -2088 272" } { "origin" "1064 -2112 272" "classname" "item_shells" } { "spawnflags" "1" "origin" "1256 -2240 272" "classname" "item_health" } { "classname" "item_health" "origin" "1256 -2312 272" "spawnflags" "1" } { "origin" "824 -2592 0" "classname" "item_rockets" } { "origin" "240 -3016 0" "classname" "item_health" } { "classname" "item_health" "origin" "304 -3016 0" } { "origin" "-136 -3096 0" "classname" "item_spikes" } { "classname" "monster_shalrath" "origin" "288 -2768 152" "angle" "315" "spawnflags" "257" } { "spawnflags" "1" "origin" "-616 -2552 0" "classname" "item_spikes" } { "origin" "-528 -2064 0" "classname" "item_health" } { "classname" "item_health" "origin" "-456 -2064 0" "spawnflags" "1" } { "spawnflags" "768" "target" "t142" "targetname" "t141" "origin" "-256 -1840 80" "classname" "path_corner" } { "spawnflags" "768" "target" "t141" "targetname" "t142" "classname" "path_corner" "origin" "-256 -2168 80" } { "spawnflags" "769" "target" "t141" "angle" "90" "origin" "-256 -2112 96" "classname" "monster_wizard" } { "spawnflags" "256" "targetname" "t144" "target" "t143" "origin" "88 -1928 8" "classname" "path_corner" } { "spawnflags" "256" "target" "t144" "targetname" "t143" "classname" "path_corner" "origin" "248 -1928 8" } { "target" "t143" "spawnflags" "257" "angle" "0" "origin" "152 -1936 24" "classname" "monster_hell_knight" } { "origin" "-48 -1816 0" "classname" "item_shells" } { "target" "t145" "classname" "trigger_once" "model" "*48" } { "targetname" "t145" "angle" "270" "origin" "-96 -1496 24" "classname" "monster_shalrath" "spawnflags" "257" } { "classname" "item_shells" "origin" "648 -760 -16" } { "classname" "item_shells" "origin" "-432 -712 0" } { "classname" "item_artifact_super_damage" "origin" "32 -8 56" } { "classname" "item_armor2" "origin" "896 -280 0" } { "classname" "light" "origin" "448 -1368 -96" "light" "200" } { "classname" "item_rockets" "origin" "828 -1476 -156" } { "classname" "item_spikes" "origin" "816 -2944 0" } { "origin" "816 -2904 0" "classname" "item_spikes" } { "classname" "item_shells" "origin" "896 -3096 0" } { "spawnflags" "1" "classname" "item_health" "origin" "-240 -2784 0" } { "spawnflags" "1" "origin" "-240 -2848 0" "classname" "item_health" } { "classname" "item_shells" "origin" "-520 -2672 0" } { "classname" "monster_demon1" "origin" "-96 -720 24" "angle" "270" "spawnflags" "1" } { "classname" "item_health" "origin" "-168 -816 0" } { "origin" "-168 -944 0" "classname" "item_health" } { "classname" "item_spikes" "origin" "-64 -1200 0" "spawnflags" "1" } { "classname" "item_shells" "origin" "-56 -680 0" } { "targetname" "t83" "classname" "trigger_teleport" "spawnflags" "258" "target" "t153" "model" "*49" } { "classname" "monster_hell_knight" "origin" "-168 -3912 24" "angle" "90" "targetname" "t83" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "-96 -1064 8" "angle" "90" "targetname" "t153" "spawnflags" "256" } { "classname" "path_corner" "origin" "320 -1632 -160" "targetname" "t155" "target" "t154" } { "origin" "152 -1632 -160" "classname" "path_corner" "targetname" "t154" "target" "t155" } { "classname" "monster_wizard" "origin" "288 -1632 -144" "angle" "180" "target" "t154" } { "classname" "monster_wizard" "origin" "48 -1672 -120" "angle" "45" "spawnflags" "257" } { "classname" "monster_wizard" "origin" "8 -1856 -120" "angle" "90" "spawnflags" "1" } { "classname" "path_corner" "origin" "32 -1960 -160" "target" "t156" "targetname" "t157" } { "origin" "24 -2176 -160" "classname" "path_corner" "targetname" "t156" "target" "t157" } { "classname" "monster_wizard" "origin" "64 -2168 -144" "angle" "90" "target" "t156" "spawnflags" "1" } { "classname" "monster_wizard" "origin" "136 -2296 -176" "angle" "135" "spawnflags" "257" } { "classname" "item_health" "origin" "216 -2424 192" } { "origin" "216 -2472 192" "classname" "item_health" } { "classname" "item_spikes" "origin" "328 -2648 128" "spawnflags" "1" } { "classname" "item_shells" "origin" "136 -2640 128" } { "classname" "item_rockets" "origin" "112 -1712 0" } { "classname" "item_spikes" "origin" "-168 -680 0" "spawnflags" "1" } { "classname" "item_armorInv" "origin" "-856 -544 -224" } { "classname" "item_rockets" "origin" "-1464 -368 -224" "spawnflags" "1" } { "targetname" "t109" "classname" "trigger_teleport" "spawnflags" "258" "target" "t158" "model" "*50" } { "spawnflags" "256" "classname" "info_teleport_destination" "origin" "-1088 -584 -8" "angle" "0" "targetname" "t158" } { "classname" "item_health" "origin" "824 -2688 0" } { "targetname" "t160" "spawnflags" "2" "classname" "trigger_teleport" "target" "t159" "model" "*51" } { "angle" "90" "origin" "136 -3912 160" "classname" "monster_demon1" "targetname" "t160" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "284 -3312 140" "angle" "90" "targetname" "t159" } { "classname" "trigger_once" "target" "t160" "model" "*52" } { "spawnflags" "256" "classname" "monster_shalrath" "origin" "-1272 128 -160" "angle" "270" "targetname" "t109" } { "classname" "info_intermission" "origin" "712 -3632 368" "mangle" "15 140 0" } { "message" "These bars are opened elsewhere..." "targetname" "t161" "sounds" "4" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*53" } { "target" "t161" "targetname" "t89" "count" "3" "classname" "trigger_counter" "model" "*54" } { "spawnflags" "1" "origin" "824 -2728 0" "classname" "item_health" } { "targetname" "t98" "angle" "180" "origin" "-2008 -384 88" "classname" "monster_ogre" "spawnflags" "769" } { "spawnflags" "2816" "origin" "-2008 -328 64" "classname" "item_shells" } { "classname" "monster_ogre" "origin" "-1304 -880 152" "angle" "315" "spawnflags" "769" } { "spawnflags" "769" "angle" "270" "origin" "-448 -304 152" "classname" "monster_wizard" } { "classname" "monster_ogre" "origin" "392 -472 24" "angle" "90" "spawnflags" "769" } { "spawnflags" "769" "angle" "315" "origin" "696 -856 -24" "classname" "monster_hell_knight" } { "spawnflags" "2816" "classname" "item_shells" "origin" "112 -656 0" } { "spawnflags" "768" "angle" "270" "origin" "-96 -872 24" "classname" "monster_shalrath" } { "classname" "monster_hell_knight" "origin" "192 -600 24" "angle" "0" "spawnflags" "768" } { "classname" "monster_ogre" "origin" "984 -1400 80" "angle" "0" "targetname" "t111" "spawnflags" "768" } { "angle" "0" "origin" "984 -1592 80" "classname" "monster_ogre" "targetname" "t111" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "800 -2176 296" "angle" "90" "spawnflags" "768" "target" "t162" } { "classname" "monster_hell_knight" "origin" "1120 -2152 296" "angle" "180" "spawnflags" "769" "targetname" "t162" } { "classname" "item_armor1" "origin" "1160 -2616 0" } { "target" "t163" "classname" "trigger_once" "model" "*55" } { "spawnflags" "2816" "origin" "880 -1344 56" "classname" "item_shells" } { "target" "t164" "spawnflags" "768" "classname" "trigger_once" "model" "*56" } { "targetname" "t164" "spawnflags" "768" "angle" "270" "origin" "-240 -2928 24" "classname" "monster_demon1" } { "target" "t114" "spawnflags" "1536" "angle" "180" "origin" "816 -952 -24" "classname" "monster_hell_knight" } { "spawnflags" "1536" "angle" "315" "origin" "288 -2760 144" "classname" "monster_hell_knight" } { "spawnflags" "3584" "origin" "-656 -2552 0" "classname" "item_health" } { "targetname" "t145" "spawnflags" "1537" "angle" "270" "origin" "-96 -1432 24" "classname" "monster_ogre" } { "light" "200" "origin" "400 -1352 112" "classname" "light" } { "light" "200" "origin" "400 -1152 112" "classname" "light" } { "classname" "light" "origin" "192 -1152 112" "light" "200" } { "classname" "light" "origin" "192 -1352 112" "light" "200" } { "spawnflags" "1792" "origin" "560 -1152 -48" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "-1784 -472 64" "classname" "weapon_supershotgun" } { "angle" "270" "origin" "-1088 -360 24" "classname" "info_player_deathmatch" } { "origin" "-936 -824 152" "classname" "weapon_rocketlauncher" //Q-Man } { "spawnflags" "1792" "origin" "-616 -2392 0" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "288 -3392 128" "classname" "weapon_lightning" } { "classname" "item_cells" "origin" "248 -3088 0" "spawnflags" "1" } { "angle" "270" "origin" "888 -2592 24" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "1224 -2408 272" "classname" "weapon_rocketlauncher" } { "angle" "270" "origin" "288 -2624 152" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-312 -2624 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "328 -1944 24" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-96 -624 24" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "632 -232 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "416 -1152 -136" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-464 -696 32" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "768 -120 8" "classname" "weapon_supernailgun" //Q-Man } { "spawnflags" "1792" "origin" "288 -736 8" "classname" "weapon_supernailgun" } { "origin" "-448 -148 0" "classname" "item_armor1" } { "light" "175" "origin" "896 -1592 96" "classname" "light" } { "classname" "light" "origin" "704 -1592 96" "light" "175" } { "light" "175" "origin" "704 -1408 96" "classname" "light" } { "classname" "light" "origin" "896 -1408 96" "light" "175" } { "light" "150" "origin" "800 -1720 280" "classname" "light" } { "spawnflags" "1" "angle" "315" "origin" "-360 -1784 96" "classname" "monster_wizard" } { "targetname" "t167" "target" "t166" "classname" "trigger_teleport" "spawnflags" "2" "model" "*57" } { "classname" "monster_shalrath" "origin" "496 -3912 160" "angle" "90" } { "targetname" "t166" "classname" "info_teleport_destination" "origin" "664 -3064 16" "angle" "135" } { "target" "t167" "classname" "trigger_once" "model" "*58" } { "light" "200" "origin" "1000 -1496 -72" "classname" "light" } { "classname" "light" "origin" "800 -1312 -72" "light" "200" } { "light" "200" "origin" "608 -1496 -72" "classname" "light" } { "light" "300" "origin" "-128 -2024 -152" "classname" "light" } { "classname" "light" "origin" "-256 -2024 -152" "light" "300" } { "classname" "light" "origin" "280 -1288 -104" "light" "200" } { "classname" "light" "origin" "32 -3048 80" } { "origin" "584 -3048 80" "classname" "light" } { "classname" "light" "origin" "552 -3264 280" } { "origin" "16 -3264 280" "classname" "light" } { "classname" "monster_hell_knight" "origin" "288 -3272 144" "angle" "45" "spawnflags" "1536" } { "classname" "light_flame_large_yellow" "origin" "-1642 -474 96" } { "origin" "-600 -474 96" "classname" "light_flame_large_yellow" } { "light" "250" "origin" "280 -3576 248" "classname" "light" } //{ //"target" "t168" //"spawnflags" "4" //"origin" "284 -3432 152" //"classname" "item_sigil" //} { "map" "start" "classname" "trigger_changelevel" "model" "*59" } //{ //"targetname" "t168" //"speed" "50" //"sounds" "4" //"wait" "-1" //"angle" "-2" //"classname" "func_door" //"model" "*60" //} { "light" "125" "origin" "284 -3644 348" "classname" "light" } { "classname" "light" "origin" "284 -3496 248" "light" "200" } //{ //"speed" "50" //"wait" "-1" //"targetname" "t168" //"angle" "-2" //"classname" "func_door" //"model" "*61" //} { "origin" "296 -2856 128" "classname" "item_cells" "spawnflags" "2048" } { "origin" "304 -3088 0" "classname" "item_rockets" } { "light" "150" "origin" "872 -2624 160" "classname" "light" } { "classname" "light" "origin" "872 -2720 160" "light" "150" } { "light" "150" "origin" "872 -2848 160" "classname" "light" } { "classname" "light" "origin" "872 -2960 160" "light" "150" } { "light" "150" "origin" "872 -3064 160" "classname" "light" } { "light" "150" "origin" "984 -2624 72" "classname" "light" } { "classname" "light" "origin" "872 -2624 72" "light" "150" } { "light" "150" "origin" "872 -2720 72" "classname" "light" } { "classname" "light" "origin" "872 -2848 72" "light" "150" } { "light" "150" "origin" "872 -2960 72" "classname" "light" } { "classname" "light" "origin" "872 -3064 72" "light" "150" } { "light" "150" "origin" "-256 -3040 160" "classname" "light" } { "classname" "light" "origin" "-256 -2928 160" "light" "150" } { "light" "150" "origin" "-256 -2816 160" "classname" "light" } { "classname" "light" "origin" "-256 -2624 160" "light" "150" } { "light" "150" "origin" "-480 -2624 160" "classname" "light" } { "classname" "light" "origin" "-480 -2168 144" "light" "150" } { "light" "150" "origin" "-480 -2072 40" "classname" "light" } { "classname" "light" "origin" "-480 -2192 40" "light" "150" } { "light" "150" "origin" "-480 -2272 40" "classname" "light" } { "classname" "light" "origin" "-480 -2376 40" "light" "150" } { "light" "150" "origin" "-480 -2472 40" "classname" "light" } { "classname" "light" "origin" "-472 -2592 40" "light" "150" } { "light" "150" "origin" "-392 -2624 40" "classname" "light" } { "classname" "light" "origin" "-256 -2624 40" "light" "150" } { "light" "150" "origin" "-256 -2728 40" "classname" "light" } { "classname" "light" "origin" "-256 -2840 40" "light" "150" } { "light" "150" "origin" "-256 -2936 40" "classname" "light" } { "classname" "light" "origin" "-256 -3056 40" "light" "150" } { "classname" "func_wall" "spawnflags" "1792" "model" "*62" } { "angle" "270" "origin" "-1016 -344 32" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-1152 -352 32" "angle" "270" } { "angle" "270" "origin" "-1088 -408 32" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-1152 -560 32" "angle" "270" } { "classname" "item_spikes" "origin" "-312 -328 0" "spawnflags" "3584" } { "spawnflags" "3584" "origin" "-272 -328 0" "classname" "item_spikes" } { "target" "t137" "origin" "648 -1520 -136" "classname" "monster_hell_knight" } { "spawnflags" "2" "classname" "trigger_teleport" "targetname" "t167" "target" "t169" "model" "*63" } { "angle" "90" "origin" "336 -3912 160" "classname" "monster_shalrath" } { "classname" "info_teleport_destination" "origin" "-64 -3056 16" "angle" "45" "targetname" "t169" } { "classname" "trigger_teleport" "spawnflags" "258" "targetname" "t160" "target" "t170" "model" "*64" } { "classname" "monster_demon1" "origin" "8 -3920 160" "angle" "90" "targetname" "t160" "spawnflags" "256" } { "classname" "info_teleport_destination" "origin" "288 -2656 136" "angle" "270" "targetname" "t170" } { "classname" "trigger_teleport" "target" "t169" "model" "*65" } { "classname" "path_corner" "origin" "560 -3040 8" "spawnflags" "768" "targetname" "t171" "target" "t172" } { "spawnflags" "768" "origin" "360 -3040 8" "classname" "path_corner" "targetname" "t172" "target" "t171" } { "classname" "monster_demon1" "origin" "472 -3040 24" "angle" "0" "spawnflags" "768" "target" "t171" } //Q-Man { "classname" "item_flag_team1" "origin" "-1086 -288 28" } { "classname" "info_player_team1" "origin" "-1088 -288 32" "angle" "270" } { "classname" "info_player_team1" "origin" "-1093 -588 8" "angle" "270" } { "classname" "info_player_team1" "origin" "-929 -713 24" "angle" "90" } { "classname" "info_player_team1" "origin" "-1249 -713 24" "angle" "90" } { "classname" "info_player_team1" "origin" "-652 -652 24 " "angle" "180" } { "classname" "info_player_team1" "origin" "-1788 -350 88" "angle" "0" } { "classname" "item_flag_team2" "origin" "284 -3432 152" } { "classname" "info_player_team2" "origin" "288 -2655 152" "angle" "270" } { "classname" "info_player_team2" "origin" "286 -3202 144" "angle" "270" } { "classname" "info_player_team2" "origin" "288 -3392 152" "angle" "270" } { "classname" "info_player_team2" "origin" "-85 -3042 24" } { "classname" "info_player_team2" "origin" "289 -3047 24" } { "classname" "info_player_team2" "origin" "877 -3050 24" "angle" "90" } { "classname" "item_armorInv" "origin" "287 -3046 168" } { "origin" "288 -1572 24" "classname" "weapon_supershotgun" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e3m7.ent000066400000000000000000000771151475442401000252120ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/metal.wad" "sounds" "5" "message" "the Haunted Halls" "worldtype" "1" } { "angle" "90" "classname" "info_player_start" "origin" "-1128 -224 -496" } { "classname" "light" "origin" "-384 -816 -8" "light" "200" } { "classname" "light" "origin" "-512 -816 -8" "light" "200" } { "classname" "light" "origin" "-512 -1040 -8" "light" "200" } { "classname" "light" "origin" "-384 -1040 -8" "light" "200" } { "light" "200" "origin" "-254 -694 148" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-102 -694 148" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-246 -422 148" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-102 -422 148" "classname" "light_torch_small_walltorch" } { "light" "500" "origin" "-336 -560 288" "classname" "light" } { "light" "500" "origin" "-176 -688 288" "classname" "light" } { "light" "500" "origin" "48 -640 288" "classname" "light" } { "light" "500" "origin" "-48 -544 288" "classname" "light" } { "light" "500" "origin" "-176 -432 288" "classname" "light" } { "origin" "-496 -432 56" "classname" "light" } { "origin" "-456 -560 56" "classname" "light" } { "light" "600" "origin" "-544 -208 344" "classname" "light" } { "light" "600" "origin" "-408 -240 344" "classname" "light" } { "light" "600" "origin" "-680 -240 344" "classname" "light" } { "light" "600" "origin" "-544 -272 344" "classname" "light" } { "light" "200" "origin" "-566 -166 92" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-422 -166 92" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-566 -310 92" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "-422 -310 92" "classname" "light_torch_small_walltorch" } { "origin" "-576 -224 -264" "classname" "light" } { "classname" "light" "origin" "224 -224 360" "light" "500" } { "classname" "light_torch_small_walltorch" "origin" "154 -38 204" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "266 -38 204" "light" "180" } { "classname" "light" "origin" "48 -96 312" "light" "500" } { "classname" "light" "origin" "48 -320 312" "light" "500" } { "classname" "light" "origin" "48 -208 256" "light" "500" } { "light" "400" "origin" "368 -240 280" "classname" "light" } { "light" "200" "origin" "32 80 -64" "classname" "light" } { "light" "200" "origin" "384 32 152" "classname" "light" } { "light" "200" "origin" "56 -344 -64" "classname" "light" } { "light" "200" "origin" "216 -336 -64" "classname" "light" } { "light" "200" "origin" "208 -88 -64" "classname" "light" } { "light" "200" "origin" "96 -176 -64" "classname" "light" } { "spawnflags" "4" //Q-Man "angle" "180" "classname" "func_door_secret" "target" "t12" "model" "*1" "wait" "4" } { "light" "400" "origin" "112 64 32" "classname" "light" } { "origin" "-1048 -496 -256" "classname" "light" "light" "200" } { "origin" "-848 -312 -256" "classname" "light" } { "origin" "-864 -648 -256" "classname" "light" } { "origin" "-624 -504 -256" "classname" "light" } { "classname" "light" "origin" "-112 128 -96" } { "classname" "light" "origin" "-256 128 -96" } { "classname" "light" "origin" "-384 128 -96" } { "classname" "light" "origin" "-384 416 -96" } { "classname" "light" "origin" "-256 416 -96" } { "classname" "light" "origin" "-112 416 -96" } { "classname" "func_plat" "angle" "90" "model" "*2" } { "light" "150" "origin" "-280 264 -56" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "-470 370 132" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-470 178 132" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-366 74 132" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-182 74 132" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-78 362 132" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-78 178 132" "light" "200" } { "classname" "light" "origin" "-176 -888 64" } { "classname" "light" "origin" "200 256 64" "light" "200" } { "light" "200" "origin" "-592 272 48" "classname" "light" } { "light" "200" "origin" "-724 304 48" "classname" "light" } { "origin" "-808 -272 -528" "classname" "item_health" } { "origin" "-808 -304 -528" "classname" "item_health" } { "origin" "-624 256 16" "classname" "item_health" } { "spawnflags" "1" "origin" "200 -240 0" "classname" "item_weapon" } { "spawnflags" "2" "origin" "-8 -648 -104" "classname" "item_weapon" } { "origin" "-528 -104 -128" "classname" "item_health" } { "origin" "-488 -104 -128" "classname" "item_health" } { "angle" "0" "origin" "-352 -928 24" "classname" "info_player_deathmatch" } { "origin" "-1040 -496 -320" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-176 -232 32" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-720 528 24" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "208 56 32" "classname" "info_player_deathmatch" } { "origin" "48 272 0" "classname" "item_health" } { "spawnflags" "1" "origin" "-304 -456 -120" "classname" "item_health" } { "spawnflags" "1" "origin" "-264 -456 -120" "classname" "item_health" } { "spawnflags" "2" "origin" "-1056 -840 -360" "classname" "item_weapon" } { "light" "250" "origin" "-176 -248 32" "classname" "light" } { "origin" "-488 -96 104" "classname" "light" } { "light" "200" "origin" "-256 560 -88" "classname" "light" } { "light" "200" "origin" "-272 560 32" "classname" "light" } { "light" "200" "origin" "-232 560 128" "classname" "light" } { "light" "200" "origin" "10 -150 156" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "10 -326 156" "classname" "light_torch_small_walltorch" } { "light" "200" "origin" "344 -240 104" "classname" "light" } { "classname" "light" "origin" "384 -64 -48" "light" "250" } { "classname" "light" "origin" "384 80 48" "light" "200" } { "classname" "light" "origin" "-864 -600 -16" "light" "600" } { "classname" "light" "origin" "-864 -456 -16" "light" "600" } { "classname" "light" "origin" "-864 -312 -16" "light" "600" } { "classname" "light" "origin" "-448 264 -488" "light" "200" } { "classname" "light" "origin" "-776 256 -488" "light" "200" } { "classname" "light" "origin" "-808 136 -488" "light" "200" } { "classname" "light" "origin" "-456 136 -488" "light" "200" } { "classname" "light" "origin" "-464 16 -488" "light" "200" } { "classname" "light" "origin" "-624 0 -488" "light" "200" } { "classname" "light" "origin" "-784 0 -488" "light" "200" } { "classname" "light" "origin" "-616 280 -488" "light" "200" } { "classname" "light" "origin" "-624 128 -488" "light" "200" } { "classname" "light" "origin" "-792 384 -488" "light" "200" } { "classname" "light" "origin" "-616 368 -488" "light" "200" } { "classname" "light" "origin" "-448 376 -488" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "-490 226 -204" } { "classname" "light_torch_small_walltorch" "origin" "-758 226 -204" } { "origin" "400 48 0" "classname" "item_armor2" } { "origin" "-1056 -600 -368" "classname" "item_armor1" } { "spawnflags" "1" "origin" "-760 -16 -368" "classname" "item_spikes" } { "classname" "weapon_nailgun" "origin" "-640 -16 -368" "spawnflags" "1792" } { "classname" "monster_ogre" "origin" "-856 -496 -344" "angle" "270" } { "classname" "func_plat" "model" "*3" } { "classname" "light" "origin" "-1048 -848 -256" "light" "200" } { "light" "200" "origin" "-560 -976 76" "classname" "light" } { "classname" "light" "origin" "-880 -112 -448" "light" "200" } { "classname" "monster_demon1" "origin" "-632 -496 -344" "angle" "180" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-624 -496 -344" "angle" "180" "spawnflags" "1536" } { "classname" "trigger_monsterjump" "angle" "90" "model" "*4" } { "origin" "-856 -840 -256" "classname" "light" "light" "200" } { "classname" "func_door" "angle" "0" "targetname" "t6" "wait" "-1" "sounds" "4" "message" "This door is opened elsewhere..." "model" "*5" } { "light" "200" "origin" "-1072 -704 -256" "classname" "light" } { "classname" "trigger_teleport" "target" "t5" "model" "*6" } { "classname" "info_teleport_destination" "origin" "-320 -240 -112" "angle" "180" "targetname" "t5" } { "classname" "func_button" "angle" "0" "target" "t6" "wait" "-1" "model" "*7" } { "classname" "info_null" "origin" "-356 -240 -304" "targetname" "t7" } { "classname" "light" "origin" "-392 -240 -268" "target" "t7" "style" "2" } { "classname" "light" "origin" "-640 -40 -304" "light" "200" } { "light" "200" "origin" "-512 16 -304" "classname" "light" } { "classname" "light" "origin" "-736 48 -304" "light" "200" } { "classname" "monster_zombie" "origin" "-816 -584 -504" "angle" "225" } { "classname" "monster_zombie" "origin" "-896 -584 -504" "angle" "315" } { "classname" "item_rockets" "origin" "-872 -648 -528" } { "classname" "monster_wizard" "origin" "-608 -208 -152" "angle" "90" "targetname" "t8" "spawnflags" "257" } { "classname" "trigger_once" "target" "t8" "model" "*8" } { "classname" "monster_zombie" "origin" "-472 -224 -344" "angle" "45" "targetname" "t8" "spawnflags" "2" } { "origin" "-472 -280 -344" "classname" "monster_zombie" "angle" "0" "targetname" "t8" "spawnflags" "2" } { "classname" "monster_zombie" "origin" "-416 -248 -344" "angle" "0" "spawnflags" "258" "targetname" "t8" } { "classname" "item_rockets" "origin" "-672 -224 -368" "spawnflags" "1024" } { "classname" "monster_ogre" "origin" "-488 -240 -104" "angle" "0" "targetname" "t8" "spawnflags" "1" } { "classname" "trigger_monsterjump" "angle" "180" "model" "*9" } { "classname" "monster_ogre" "origin" "-496 -544 -104" "angle" "90" } { "classname" "func_door" "angle" "-2" "spawnflags" "2049" "targetname" "t9" "wait" "-1" "sounds" "4" "model" "*10" } { "classname" "monster_demon1" "origin" "-120 -568 -104" "angle" "180" } { "classname" "trigger_once" "target" "t9" "spawnflags" "2048" "model" "*11" } { "classname" "light" "origin" "-184 -496 -64" "light" "150" } { "light" "150" "origin" "-128 -568 -64" "classname" "light" } { "classname" "light" "origin" "-184 -624 -64" "light" "150" } { "light" "150" "origin" "-272 -560 -64" "classname" "light" } { "classname" "light" "origin" "-112 -568 -288" "light" "200" } { "classname" "light" "origin" "-32 -728 -56" "light" "150" } { "classname" "light" "origin" "-424 -560 -24" "light" "150" } { "light" "150" "origin" "-512 -456 -24" "classname" "light" } { "classname" "func_door" "spawnflags" "2049" "angle" "270" "targetname" "t9" "wait" "5" "speed" "300" "model" "*12" } { "classname" "func_wall" "spawnflags" "1792" "model" "*13" } { "classname" "func_door" "angle" "270" "wait" "-1" "targetname" "t10" "sounds" "4" "model" "*14" } { "classname" "trigger_once" "target" "t10" "model" "*15" } { "classname" "func_plat" "model" "*16" } { "classname" "func_button" "angle" "180" "target" "t11" "wait" "-1" "model" "*17" } { "classname" "func_door" "angle" "-1" "wait" "-1" "message" "This door is opened elsewhere..." "targetname" "t11" "spawnflags" "2048" "model" "*18" } { "classname" "misc_fireball" "origin" "-488 -808 -8" "speed" "300" } { "speed" "300" "origin" "-400 -816 -8" "classname" "misc_fireball" } { "classname" "misc_fireball" "origin" "-488 -1040 -8" "speed" "300" } { "speed" "300" "origin" "-408 -1048 -8" "classname" "misc_fireball" } { "classname" "light" "origin" "-176 -384 64" "light" "200" } { "light" "200" "origin" "-176 -704 64" "classname" "light" } { "classname" "func_door" "angle" "270" "lip" "-8" "wait" "-1" "targetname" "t11" "model" "*19" } { "classname" "light" "origin" "-208 -936 -104" "light" "200" } { "classname" "func_door" "spawnflags" "1" "angle" "-2" "targetname" "t11" "speed" "150" "wait" "-1" "model" "*20" } { "classname" "monster_zombie" "origin" "-240 -904 -152" "angle" "180" } { "angle" "180" "origin" "-240 -952 -152" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "-184 -952 -152" "angle" "180" } { "angle" "180" "origin" "-176 -904 -152" "classname" "monster_zombie" } { "classname" "monster_ogre" "origin" "392 -248 168" "angle" "180" } { "classname" "light" "origin" "512 -192 192" "light" "180" } { "light" "180" "origin" "512 -320 192" "classname" "light" } { "classname" "monster_ogre" "origin" "376 -240 24" "angle" "180" } { "classname" "monster_ogre" "origin" "208 56 24" "angle" "270" } { "classname" "light" "origin" "384 -152 40" "light" "150" } { "classname" "func_door" "spawnflags" "1" "angle" "-2" "targetname" "t12" "wait" "4" //Q-Man "model" "*21" } { "classname" "monster_ogre" "origin" "-496 -976 24" "angle" "0" "spawnflags" "256" } { "angle" "0" "origin" "-496 -872 24" "classname" "monster_ogre" } { "classname" "monster_ogre" "origin" "-24 -840 24" "angle" "90" "spawnflags" "1" } { "classname" "trigger_teleport" "target" "t13" "targetname" "t17" "model" "*22" } { "classname" "trigger_teleport" "target" "t15" "targetname" "t17" "model" "*23" } { "classname" "trigger_teleport" "target" "t16" "targetname" "t17" "model" "*24" } { "classname" "trigger_teleport" "target" "t14" "targetname" "t17" "model" "*25" } { "classname" "monster_wizard" "origin" "280 -672 56" "spawnflags" "256" } { "origin" "368 -672 56" "classname" "monster_wizard" "spawnflags" "768" } { "classname" "monster_wizard" "origin" "368 -800 56" } { "origin" "280 -800 56" "classname" "monster_wizard" } { "classname" "info_teleport_destination" "origin" "-288 -480 80" "angle" "315" "targetname" "t16" } { "classname" "info_teleport_destination" "origin" "-288 -656 80" "angle" "0" "targetname" "t15" } { "classname" "info_teleport_destination" "origin" "-88 -480 80" "angle" "225" "targetname" "t14" } { "classname" "info_teleport_destination" "origin" "-40 -632 80" "angle" "180" "targetname" "t13" } { "classname" "trigger_once" "delay" "2" "target" "t17" "targetname" "t11" "model" "*26" } { "classname" "monster_ogre" "origin" "-48 -248 24" "angle" "180" "spawnflags" "257" } { "classname" "light_torch_small_walltorch" "origin" "266 194 212" "light" "200" } { "classname" "func_plat" "model" "*27" } { "classname" "light" "origin" "424 240 192" "light" "150" } { "classname" "light" "origin" "296 224 40" "light" "150" } { "classname" "light" "origin" "-392 1352 184" } { "classname" "light" "origin" "-392 1224 184" } { "classname" "func_plat" "model" "*28" } { "classname" "light" "origin" "-912 1152 -112" } { "classname" "light" "origin" "-904 1296 -112" } { "classname" "light" "origin" "-912 1480 -112" } { "classname" "light" "origin" "-904 1608 -112" } { "classname" "light" "origin" "-920 1408 368" "light" "500" } { "angle" "-2" "classname" "func_plat" "targetname" "t44" "model" "*29" } { "light" "350" "origin" "-1208 1520 124" "classname" "light" } { "light" "350" "origin" "-616 1120 124" "classname" "light" } { "light" "350" "origin" "-704 1624 312" "classname" "light" } { "light" "350" "origin" "-728 1600 312" "classname" "light" } { "light" "350" "origin" "-704 1576 312" "classname" "light" } { "light" "350" "origin" "-680 1600 312" "classname" "light" } { "classname" "light" "origin" "-1120 1176 312" "light" "350" } { "classname" "light" "origin" "-1144 1152 312" "light" "350" } { "classname" "light" "origin" "-1120 1128 312" "light" "350" } { "classname" "light" "origin" "-1096 1152 312" "light" "350" } { "light" "350" "origin" "-520 1224 184" "classname" "light" } { "angle" "0" "classname" "func_door" "model" "*30" } { "angle" "180" "classname" "func_door" "model" "*31" } { "origin" "-928 1008 248" "classname" "light" } { "origin" "-1056 1008 248" "classname" "light" } { "origin" "-1176 1008 248" "classname" "light" } { "light" "350" "origin" "-1344 1016 248" "classname" "light" } { "origin" "-1248 1392 184" "classname" "light" } { "origin" "-1384 1392 184" "classname" "light" } { "origin" "-1384 1256 184" "classname" "light" } { "origin" "-1392 1128 184" "classname" "light" } { "origin" "-1384 920 184" "classname" "light" } { "classname" "light" "origin" "-1056 816 248" "light" "500" } { "classname" "light" "origin" "-1056 656 248" "light" "500" } { "classname" "light" "origin" "-904 736 248" "light" "500" } { "classname" "light" "origin" "-1208 736 248" "light" "500" } { "classname" "light" "origin" "-1136 736 88" "light" "200" } { "classname" "light" "origin" "-976 736 88" "light" "200" } { "classname" "light" "origin" "-720 624 200" } { "classname" "item_artifact_super_damage" "origin" "224 -456 24" } { "classname" "light" "origin" "216 -488 24" "light" "150" } { "classname" "func_button" "angle" "0" "wait" "-1" "target" "t29" "spawnflags" "2048" "model" "*32" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t18" "message" "This door is opened elsewhere..." "spawnflags" "2080" "sounds" "4" "model" "*33" } { "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t18" "spawnflags" "2048" "model" "*34" } { "classname" "info_null" "origin" "572 -260 212" "targetname" "t19" "style" "2" } { "style" "2" "classname" "light" "origin" "480 -256 216" "target" "t19" } { "light" "200" "origin" "16 272 64" "classname" "light" } { "classname" "func_button" "wait" "-1" "target" "t22" "health" "1" "angle" "90" "model" "*35" } { "classname" "func_door" "wait" "-1" "message" "This door is opened elsewhere..." "angle" "-1" "targetname" "t21" "spawnflags" "2048" "model" "*36" } { "classname" "info_null" "origin" "-260 636 92" "targetname" "t20" } { "classname" "light" "origin" "-256 544 96" "target" "t20" "style" "2" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t30" "model" "*37" } { "classname" "func_door" "angle" "180" "lip" "1" "wait" "-1" "targetname" "t22" "model" "*38" } { "classname" "trigger_once" "target" "t29" "spawnflags" "2048" "model" "*39" } { "classname" "func_button" "health" "1" "angle" "0" "target" "t23" "model" "*40" } { "classname" "trigger_teleport" "targetname" "t23" "target" "t24" "model" "*41" } { "classname" "info_teleport_destination" "origin" "64 272 8" "angle" "180" "targetname" "t24" } { "classname" "light" "origin" "-296 272 -160" "light" "200" } { "classname" "light" "origin" "-272 280 48" "light" "200" } { "classname" "monster_ogre" "origin" "32 768 24" } { "origin" "184 768 24" "classname" "monster_ogre" "spawnflags" "256" } { "classname" "monster_shambler" "origin" "32 672 24" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "184 672 24" "spawnflags" "1536" } { "classname" "trigger_teleport" "targetname" "t25" "target" "t27" "model" "*42" } { "classname" "trigger_teleport" "targetname" "t25" "target" "t28" "model" "*43" } { "classname" "trigger_teleport" "targetname" "t25" "target" "t26" "model" "*44" } { "classname" "trigger_teleport" "targetname" "t25" "target" "t26" "model" "*45" } { "classname" "trigger_relay" "origin" "104 720 32" "target" "t25" "targetname" "t31" } { "classname" "info_teleport_destination" "origin" "-424 272 8" "targetname" "t26" "angle" "0" } { "classname" "info_teleport_destination" "origin" "-272 104 8" "angle" "90" "targetname" "t27" } { "classname" "info_teleport_destination" "origin" "-256 512 -104" "angle" "270" "targetname" "t28" } { "classname" "trigger_relay" "origin" "552 -152 152" "targetname" "t29" "target" "t18" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "232 264 64" "targetname" "t30" "target" "t29" "spawnflags" "2048" } { "classname" "trigger_relay" "origin" "-240 608 8" "target" "t31" "targetname" "t22" } { "classname" "trigger_once" "target" "t21" "model" "*46" } { "classname" "info_null" "origin" "-600 -928 48" "targetname" "t32" } { "classname" "light" "origin" "-532 -928 52" "target" "t32" "style" "2" } { "classname" "light" "origin" "-716 444 48" "light" "200" } { "classname" "item_health" "origin" "-760 232 16" } { "classname" "light" "origin" "-1328 808 112" "light" "150" } { "light" "150" "origin" "-1328 960 112" "classname" "light" } { "classname" "light" "origin" "-1328 1088 112" "light" "150" } { "light" "150" "origin" "-1328 1216 112" "classname" "light" } { "classname" "light" "origin" "-1328 1336 112" "light" "150" } { "light" "150" "origin" "-1216 1328 112" "classname" "light" } { "classname" "monster_ogre" "origin" "-1104 1008 88" "angle" "180" "targetname" "t33" } { "classname" "trigger_monsterjump" "angle" "180" "model" "*47" } { "classname" "trigger_once" "target" "t33" "model" "*48" } { "classname" "func_button" "angle" "90" "target" "t18" "health" "1" "model" "*49" } { "classname" "func_door" "angle" "90" "wait" "-1" "targetname" "t25" "model" "*50" } //{ //"classname" "trap_spikeshooter" //"origin" "-1408 892 -16" //"angle" "0" //"targetname" "t35" //} { "classname" "trigger_multiple" "target" "t36" "wait" "1.5" "model" "*51" } { "classname" "light" "origin" "-1376 872 -16" "light" "125" } { "light" "125" "origin" "-1376 960 -16" "classname" "light" } { "classname" "light" "origin" "-1376 1048 -16" "light" "125" } { "light" "125" "origin" "-1376 1152 -16" "classname" "light" } { "classname" "light" "origin" "-1376 1248 -16" "light" "125" } { "light" "125" "origin" "-1376 1336 -16" "classname" "light" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t35" "model" "*52" } //{ //"angle" "0" //"origin" "-1408 1340 -16" //"classname" "trap_spikeshooter" //"targetname" "t43" //} //{ //"classname" "trap_spikeshooter" //"origin" "-1408 1276 -16" //"angle" "0" //"targetname" "t42" //} //{ //"angle" "0" //"origin" "-1408 1212 -16" //"classname" "trap_spikeshooter" //"targetname" "t41" //} //{ //"classname" "trap_spikeshooter" //"origin" "-1408 1148 -16" //"angle" "0" //"targetname" "t40" //} //{ //"angle" "0" //"origin" "-1408 1084 -16" //"classname" "trap_spikeshooter" //"targetname" "t39" //} //{ //"classname" "trap_spikeshooter" //"origin" "-1408 1020 -16" //"angle" "0" //"targetname" "t38" //} //{ //"angle" "0" //"origin" "-1408 956 -16" //"classname" "trap_spikeshooter" //"targetname" "t37" //} { "classname" "trigger_multiple" "targetname" "t36" "target" "t43" "delay" "1" "model" "*53" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t42" "model" "*54" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t41" "delay" "1" "model" "*55" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t40" "model" "*56" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t39" "delay" "1" "model" "*57" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t38" "model" "*58" } { "classname" "trigger_multiple" "targetname" "t36" "target" "t37" "delay" "1" "model" "*59" } { "spawnflags" "1" "classname" "monster_hell_knight" "origin" "-864 768 -40" "angle" "180" } { "classname" "monster_hell_knight" "origin" "-1368 800 -40" "angle" "0" } { "classname" "item_spikes" "origin" "-880 624 16" "spawnflags" "1" } { "classname" "func_button" "target" "t44" "wait" "-1" "angle" "90" "model" "*60" } { "classname" "light" "origin" "-1120 1576 -8" "style" "2" "target" "t45" } { "classname" "info_null" "origin" "-1124 1652 -4" "targetname" "t45" } { "classname" "light" "origin" "-1128 1608 -32" "light" "150" } { "light" "150" "origin" "-1120 1472 -32" "classname" "light" } { "classname" "light" "origin" "-1120 1352 -32" "light" "150" } { "light" "150" "origin" "-1120 1216 -32" "classname" "light" } { "classname" "light" "origin" "-1128 1104 -32" "light" "150" } { "classname" "light" "origin" "-1152 1280 184" "light" "150" } { "light" "150" "origin" "-1152 1440 184" "classname" "light" } { "classname" "light" "origin" "-1152 1600 112" "light" "150" } { "classname" "func_door" "angle" "90" "targetname" "t46" "sounds" "4" "wait" "-1" "spawnflags" "4" "model" "*61" } { "classname" "func_door" "angle" "-2" "lip" "48" "wait" "-1" "sounds" "1" "targetname" "t46" "model" "*62" } { "classname" "func_door" "angle" "-2" "lip" "32" "wait" "-1" "sounds" "1" "targetname" "t46" "model" "*63" } { "classname" "func_door" "angle" "-2" "lip" "16" "wait" "-1" "sounds" "1" "targetname" "t46" "model" "*64" } { "classname" "trigger_relay" "origin" "-1168 1648 8" "target" "t46" "targetname" "t47" } { "classname" "func_button" "angle" "-1" "health" "1" "target" "t47" "wait" "-1" "model" "*65" } { "classname" "light" "origin" "-1232 1464 -56" "light" "150" } { "light" "150" "origin" "-1240 1600 -56" "classname" "light" } { "classname" "trigger_secret" "model" "*66" } { //Q-Man "classname" "item_health" "origin" "-1400 1464 -120" "spawnflags" "1" "targetname" "t48" } { "classname" "item_health" "origin" "-1400 1539 -120" "targetname" "t49" "spawnflags" "1" } { "classname" "item_health" "origin" "-1400 1614 -120" "targetname" "t50" "spawnflags" "1" } { "classname" "monster_zombie" "origin" "-1312 1472 -104" "angle" "90" } { "angle" "90" "origin" "-1256 1472 -104" "classname" "monster_zombie" } { "classname" "light" "origin" "-1384 1480 0" "target" "t48" } { "origin" "-1384 1552 0" "classname" "light" "target" "t49" } { "classname" "light" "origin" "-1384 1624 0" "target" "t50" } { "classname" "light" "origin" "-1168 1648 144" "style" "2" "light" "150" "target" "t51" } { "classname" "info_null" "origin" "-1172 1652 196" "targetname" "t51" } { "classname" "monster_ogre" "origin" "-1112 1296 136" "spawnflags" "768" } { "classname" "monster_shalrath" "origin" "-704 1408 -40" "angle" "180" } { "classname" "monster_ogre" "origin" "-1120 1504 -40" "angle" "270" "spawnflags" "256" } { "classname" "monster_ogre" "origin" "-800 1408 136" "angle" "180" } { "classname" "monster_ogre" "origin" "-904 1024 -40" "angle" "90" "target" "t52" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "4" "targetname" "t52" "spawnflags" "2048" "model" "*67" } { "classname" "func_door" "angle" "-1" "wait" "-1" "sounds" "1" "model" "*68" } { "classname" "monster_ogre" "origin" "-472 1280 -40" "angle" "180" } { "light" "150" "origin" "-704 1152 -32" "classname" "light" } { "classname" "light" "origin" "-680 1264 -32" "light" "150" } { "light" "150" "origin" "-704 1344 -32" "classname" "light" } { "classname" "light" "origin" "-688 1464 -32" "light" "150" } { "light" "150" "origin" "-728 1576 -32" "classname" "light" } { "classname" "light" "origin" "-728 624 104" "light" "150" } { "light" "150" "origin" "-808 632 104" "classname" "light" } { "classname" "light" "origin" "-912 664 104" "light" "150" } { "classname" "light" "origin" "-928 1008 144" "light" "150" } { "light" "150" "origin" "-1040 1024 144" "classname" "light" } { "classname" "light" "origin" "-1176 976 144" "light" "150" } { "classname" "trigger_secret" "model" "*69" } { "classname" "item_spikes" "origin" "-992 992 64" "spawnflags" "1" } //{ //"classname" "item_artifact_invulnerability" //"origin" "-1032 1008 88" //} { "classname" "trigger_once" "health" "1" "target" "t9" "model" "*70" } { "classname" "trigger_secret" "model" "*71" } { "classname" "monster_shalrath" "origin" "-272 272 -168" "spawnflags" "256" } { "classname" "trigger_monsterjump" "angle" "360" "speed" "300" "height" "300" "model" "*72" } { "classname" "light" "origin" "-896 832 40" "light" "200" } { "classname" "item_health" "origin" "-880 808 -64" } { "classname" "item_health" "origin" "-8 232 0" } { "classname" "item_spikes" "origin" "456 -184 144" "spawnflags" "1" } { "classname" "item_rockets" "origin" "456 -368 144" "spawnflags" "1" } { "classname" "item_shells" "origin" "496 -272 144" "spawnflags" "1" } { "classname" "monster_ogre" "origin" "536 -312 168" "angle" "180" } { "classname" "item_health" "origin" "280 168 0" "spawnflags" "1" } { "classname" "light" "origin" "576 192 -192" "light" "200" "style" "11" } { "classname" "item_health" "origin" "528 176 -256" "spawnflags" "2" } { "classname" "trigger_secret" "model" "*73" } { "classname" "light" "origin" "392 184 -184" "light" "200" } { "classname" "item_health" "origin" "-144 288 -104" "spawnflags" "1" } { "origin" "-144 224 -104" "classname" "item_health" } { "classname" "item_spikes" "origin" "-464 256 -104" "spawnflags" "1" } { "classname" "item_health" "origin" "-688 1120 -64" } { "origin" "-688 1184 -64" "classname" "item_health" "spawnflags" "1" } { "light" "200" "origin" "-456 1760 0" "classname" "light" } { "origin" "-392 1480 184" "classname" "light" } { "classname" "light" "origin" "-392 1560 184" } { "light" "150" "origin" "-536 1312 -32" "classname" "light" } { "classname" "light" "origin" "-488 1408 -32" "light" "150" } { "light" "150" "origin" "-488 1536 -32" "classname" "light" } { "classname" "light" "origin" "-512 1664 -32" "light" "150" } { "light" "150" "origin" "-336 1808 -32" "classname" "light" } { "classname" "light" "origin" "-560 1808 -32" "light" "150" } { "spawnflags" "1792" "classname" "func_wall" "model" "*74" } { "map" "e3m5" "classname" "trigger_changelevel" "model" "*75" } { "mangle" "20 45 0" "origin" "112 -304 176" "classname" "info_intermission" } { "classname" "light" "origin" "-680 1128 96" "light" "150" } { "light" "150" "origin" "-672 1248 96" "classname" "light" } { "classname" "trigger_teleport" "target" "t53" "model" "*76" } { "angle" "270" "origin" "208 200 16" "classname" "info_teleport_destination" "targetname" "t53" } { "classname" "info_player_coop" "origin" "-1064 -176 -496" "angle" "90" } { "angle" "90" "origin" "-1128 -152 -496" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-1032 -112 -496" "angle" "0" } { "angle" "90" "origin" "-1200 -176 -496" "classname" "info_player_coop" } { "angle" "270" "origin" "-1120 1432 -40" "classname" "info_player_deathmatch" } //{ //"spawnflags" "1792" //"origin" "-920 1360 112" //"classname" "weapon_rocketlauncher" //} { "spawnflags" "1792" "origin" "-464 1616 -40" "classname" "item_artifact_invisibility" } { "origin" "-960 848 -64" //Q-Man "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "-1072 -752 -368" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "-416 -928 0" "classname" "weapon_grenadelauncher" } { //"spawnflags" "1793" "origin" "-192 -808 0" "classname" "item_rockets" } { "spawnflags" "1792" "origin" "448 -256 144" "classname" "weapon_rocketlauncher" } { "light" "200" "origin" "-1128 -144 -272" "classname" "light" } { "classname" "light" "origin" "-1128 -288 -272" "light" "200" } { "target" "t54" "classname" "trigger_teleport" "model" "*77" } { "targetname" "t54" "origin" "-1128 -120 -464" "classname" "info_teleport_destination" } { "light" "125" "origin" "-1032 -112 -448" "classname" "light" } { "classname" "light" "origin" "-1128 -344 -448" "light" "250" } { "light" "200" "origin" "-1192 -120 -448" "classname" "light" } { "light" "125" "origin" "-1128 -272 -448" "classname" "light" } { "light" "125" "origin" "-1072 -200 -312" "classname" "light" } { "classname" "light" "origin" "-1184 -200 -312" "light" "125" } { "classname" "trigger_teleport" "target" "t55" "model" "*78" } { "classname" "info_teleport_destination" "origin" "-456 1656 16" "targetname" "t55" } { "spawnflags" "1280" "angle" "270" "origin" "-1120 1264 136" "classname" "monster_hell_knight" } //Q-Man { "classname" "item_flag_team1" "origin" "-1129 -240 -504" } { "classname" "info_player_team1" "origin" "-967 -114 -504" } { "classname" "info_player_team1" "origin" "-863 -280 -504" "angle" "270" } { "classname" "info_player_team1" "origin" "-846 -603 -504" "angle" "270" } { "classname" "info_player_team1" "origin" "-916 -824 -344" "angle" "180" } { "classname" "info_player_team1" "origin" "-1022 -497 -344" } { "classname" "info_player_team1" "origin" "-797 -497 -344" } { "classname" "item_flag_team2" "origin" "-920 1360 112" } { "classname" "info_player_team2" "origin" "-773 1411 136" "angle" "235" } { "classname" "info_player_team2" "origin" "-1012 1346 136" "angle" "235" } { "classname" "info_player_team2" "origin" "-706 1415 -40" "angle" "270" } { "classname" "info_player_team2" "origin" "-713 1185 -40" "angle" "270" } { "classname" "info_player_team2" "origin" "-1116 1334 -40" "angle" "90" } { "classname" "info_player_team2" "origin" "-1112 1524 -40" "angle" "90" } { "classname" "item_armorInv" "origin" "-287 274 -180" } { "origin" "-420 -310 -344" "classname" "item_health" "spawnflags" "1" } { "origin" "-722 1410 -40" "classname" "weapon_supershotgun" } { "origin" "-1092 1327 -40" "classname" "weapon_supershotgun" } { "origin" "-850 -496 -344" "classname" "weapon_supershotgun" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m1.ent000066400000000000000000001164101475442401000251750ustar00rootroot00000000000000{ "worldtype" "2" "classname" "worldspawn" "wad" "gfx/base.wad" "sounds" "6" "message" "the Sewage System" } { "classname" "info_player_start" "origin" "1312 568 688" "angle" "90" } { "classname" "light" "origin" "1656 744 -128" "light" "200" } { "classname" "light" "origin" "1656 1000 -64" "light" "200" } { "classname" "light" "origin" "968 904 -240" "light" "200" } { "classname" "light" "origin" "1312 1072 -40" "light" "200" } { "classname" "light" "origin" "960 1328 40" "light" "200" } { "light" "150" "origin" "924 860 96" "classname" "light" } { "classname" "light" "origin" "1312 1216 -16" "light" "200" } { "light" "250" "classname" "light" "origin" "1240 1376 -8" } { "classname" "light" "origin" "1408 432 120" "light" "200" } { "classname" "light" "origin" "1664 432 128" "light" "200" } { "classname" "light" "origin" "1104 1296 -16" } { "classname" "light" "origin" "1672 1128 128" } { "classname" "light" "origin" "1664 600 56" } { "classname" "light" "origin" "1664 376 -96" } { "light" "275" "origin" "1376 738 824" "classname" "light_fluoro" "style" "5" } { "light" "275" "origin" "1248 738 824" "classname" "light_fluoro" "style" "5" } { "classname" "light" "origin" "1100 832 180" "light" "150" } { "classname" "light_fluoro" "origin" "1100 832 116" "light" "150" } { "light" "150" "origin" "1100 688 172" "classname" "light" } { "classname" "light_fluoro" "origin" "1100 688 108" "light" "150" } { "classname" "light" "origin" "1312 584 164" "light" "250" } { "classname" "light" "origin" "1520 744 164" "light" "250" } { "classname" "light" "origin" "1316 744 164" } { "classname" "light" "origin" "1312 964 164" "light" "250" } { "classname" "light" "origin" "1208 568 24" "light" "200" } { "classname" "light" "origin" "1208 568 -120" "light" "200" } { "classname" "light" "origin" "1208 568 -312" "light" "200" } { "classname" "light" "origin" "1448 568 -312" "light" "200" } { "classname" "light" "origin" "1448 568 -120" "light" "200" } { "classname" "light" "origin" "1448 568 24" "light" "200" } { "classname" "light" "origin" "1208 960 24" "light" "200" } { "classname" "light" "origin" "1208 960 -120" "light" "200" } { "classname" "light" "origin" "1208 960 -312" "light" "200" } { "classname" "light" "origin" "1448 960 -312" "light" "200" } { "classname" "light" "origin" "1448 960 -120" "light" "200" } { "classname" "light" "origin" "1448 960 24" "light" "200" } { "classname" "light" "origin" "1392 1408 248" "light" "200" } { "classname" "light" "origin" "1392 1344 248" "light" "200" } { "classname" "light" "origin" "1584 1408 248" "light" "200" } { "classname" "light" "origin" "1584 1344 248" "light" "200" } { "classname" "light" "origin" "1312 1216 168" "light" "200" } { "light" "200" "origin" "1864 440 -112" "classname" "light" } { "origin" "2008 488 -72" "classname" "light" } { "light" "250" "origin" "2128 480 232" "classname" "light_fluoro" } { "origin" "2080 64 136" "classname" "light" } { "light" "150" "origin" "2416 384 160" "classname" "light_fluoro" } { "origin" "2368 112 144" "classname" "light" } { "light" "150" "origin" "2416 384 216" "classname" "light" } { "classname" "light" "origin" "1776 1224 24" "light" "150" } { "classname" "light" "origin" "1776 1032 24" "light" "150" } { "classname" "light" "origin" "1776 824 24" "light" "150" } { "light" "200" "origin" "1688 1368 -8" "classname" "light" } { "classname" "light" "origin" "2072 424 -256" "light" "200" } { "classname" "light" "origin" "960 1168 136" } { "origin" "764 1332 264" "classname" "light" } { "light" "150" "origin" "924 924 96" "classname" "light" } { "light" "150" "origin" "924 988 96" "classname" "light" } { "light" "150" "origin" "988 988 96" "classname" "light" } { "light" "150" "origin" "988 924 96" "classname" "light" } { "light" "150" "origin" "988 860 96" "classname" "light" } { "light" "200" "origin" "960 1088 -24" "classname" "light" } { "origin" "768 896 264" "classname" "light" } { "origin" "2296 280 80" "classname" "item_health" } { "origin" "2296 240 80" "classname" "item_health" } { "origin" "1880 -24 80" "classname" "item_spikes" } { "origin" "1192 800 80" "classname" "item_health" } { "spawnflags" "1794" "origin" "1304 736 -128" "classname" "item_health" } { "angle" "90" "origin" "1312 560 688" "classname" "info_player_deathmatch" } { "origin" "1296 408 88" "classname" "item_shells" } { "spawnflags" "1" "origin" "1512 1184 88" "classname" "item_health" } { "spawnflags" "1" "origin" "720 1488 152" "classname" "item_shells" } { "classname" "light" "origin" "960 904 -116" "light" "200" } { "light" "150" "origin" "1312 856 744" "classname" "light" } { "light" "200" "origin" "2072 -72 176" "classname" "light" } { "light" "200" "origin" "1952 -304 240" "classname" "light" } { "light" "200" "origin" "2200 -312 240" "classname" "light" } { "light" "125" "origin" "2072 -192 216" "classname" "light" } { "classname" "light" "origin" "2076 -568 264" } { "classname" "light" "origin" "2168 -788 244" "light" "200" } { "classname" "light" "origin" "1976 -792 244" "light" "200" } { "classname" "light" "origin" "2076 -532 128" "light" "200" } { "origin" "2064 200 -312" "classname" "light" } { "light" "200" "origin" "2076 -568 -152" "classname" "light" } { "light" "250" "origin" "2064 -8 -328" "classname" "light" } { "style" "32" "light" "200" "origin" "2312 -448 -136" "classname" "light" "spawnflags" "1" "targetname" "t99" } { "style" "32" "light" "200" "origin" "2312 -8 -136" "classname" "light" "spawnflags" "1" "targetname" "t99" } { "style" "32" "light" "200" "origin" "1832 -448 -136" "classname" "light" "spawnflags" "1" "targetname" "t99" } { "style" "32" "light" "200" "origin" "1832 -8 -136" "classname" "light" "spawnflags" "1" "targetname" "t99" } { "light" "150" "origin" "2416 -72 -376" "classname" "light" } { "light" "150" "origin" "2416 -248 -376" "classname" "light" } { "light" "150" "origin" "2416 -408 -376" "classname" "light" } { "light" "150" "origin" "1728 -72 -376" "classname" "light" } { "light" "150" "origin" "1728 -232 -376" "classname" "light" } { "light" "150" "origin" "1728 -408 -376" "classname" "light" } { "light" "250" "origin" "2072 -352 -344" "classname" "light" } { "light" "150" "origin" "2072 -416 -104" "classname" "light" } { "light" "200" "origin" "2072 -8 -136" "classname" "light" } { "light" "200" "origin" "2532 128 100" "classname" "light" } { "light" "200" "origin" "1096 1560 192" "classname" "light" } { "light" "150" "origin" "1104 1208 192" "classname" "light" } { "light" "200" "origin" "1560 1504 200" "classname" "light" } { "light" "200" "origin" "1664 744 160" "classname" "light" } { "classname" "info_player_deathmatch" "origin" "2376 384 104" "angle" "180" } { "classname" "item_health" "origin" "2184 -448 176" } { "sounds" "4" "speed" "50" "classname" "func_door" "angle" "90" "wait" "-1" "targetname" "t24" "model" "*1" } { "spawnflags" "1792" "classname" "trigger_once" "target" "t24" "model" "*2" } { "classname" "light" "origin" "1440 528 712" "light" "150" } { "light" "150" "origin" "1208 528 712" "classname" "light" } { "light" "200" "origin" "1312 744 640" "classname" "light" } { "classname" "light" "origin" "960 712 -16" } { "classname" "light" "origin" "960 552 -16" "light" "200" } { "classname" "light" "origin" "960 552 384" "light" "200" } { "classname" "light" "origin" "960 552 152" "light" "150" } { "classname" "light" "origin" "948 432 472" "light" "200" } { "sounds" "1" "targetname" "t31" "speed" "150" "target" "t25" "classname" "func_train" "model" "*3" } { "target" "t26" "targetname" "t25" "origin" "880 522 -168" "classname" "path_corner" } { "target" "t27" "targetname" "t26" "origin" "880 522 392" "classname" "path_corner" } { "target" "t28" "targetname" "t27" "origin" "880 400 392" "classname" "path_corner" } { "target" "t25" "targetname" "t28" "origin" "880 400 -168" "classname" "path_corner" } { "light" "200" "origin" "740 400 468" "classname" "light" } { "classname" "light" "origin" "748 640 468" "light" "200" } { "light" "200" "origin" "1768 1568 232" "classname" "light" } { "light" "250" "origin" "1312 964 364" "classname" "light" } { "light" "150" "origin" "1100 832 428" "classname" "light" } { "classname" "light_fluoro" "origin" "1100 832 364" "light" "150" } { "classname" "light" "origin" "1100 688 428" "light" "150" } { "light" "150" "origin" "1100 688 364" "classname" "light_fluoro" } { "classname" "light" "origin" "1312 580 364" "light" "250" } { "classname" "light" "origin" "1496 744 364" } { "light" "250" "origin" "1664 752 364" "classname" "light" } { "target" "t30" "classname" "func_button" "angle" "270" "wait" "-1" "model" "*4" } { "targetname" "t29" "origin" "1316 860 340" "classname" "info_null" } { "sounds" "4" "targetname" "t30" "lip" "40" "angle" "90" "classname" "func_door" "wait" "-1" "model" "*5" } { "lip" "40" "classname" "func_door" "angle" "270" "wait" "-1" "message" "This flood gate is closed..." "model" "*6" } { "light" "200" "origin" "1512 752 -144" "classname" "light" } { "classname" "func_door" "angle" "90" "lip" "40" "targetname" "t30" "wait" "-1" "model" "*7" } { "sounds" "4" "lip" "40" "angle" "270" "classname" "func_door" "wait" "-1" "message" "This flood gate is closed..." "model" "*8" } { "light" "200" "origin" "1528 440 120" "classname" "light" } { "lip" "40" "angle" "180" "classname" "func_door" "targetname" "t30" "wait" "-1" "spawnflags" "2048" "model" "*9" } { "sounds" "4" "classname" "func_door" "angle" "0" "lip" "40" "wait" "-1" "spawnflags" "2048" "message" "This flood gate is closed..." "model" "*10" } { "classname" "light" "origin" "1664 1000 20" "light" "200" } { "light" "100" "origin" "1312 528 696" "classname" "light" } { "style" "2" "light" "200" "origin" "1188 468 368" "classname" "light" } { "style" "2" "classname" "light" "origin" "1412 496 368" "light" "200" } { "classname" "light" "origin" "2072 -856 160" "light" "200" } { "classname" "light" "origin" "2152 -992 232" "light" "200" } { "light" "200" "origin" "2152 -928 232" "classname" "light" } { "classname" "light" "origin" "1992 -920 232" "light" "200" } { "light" "200" "origin" "1992 -992 232" "classname" "light" } { "spawnflags" "2056" "wait" "-1" "speed" "400" "classname" "func_door" "angle" "180" "sounds" "2" "model" "*11" } { "spawnflags" "2056" "wait" "-1" "speed" "400" "classname" "func_door" "angle" "0" "model" "*12" } { "light" "250" "origin" "768 1392 584" "classname" "light_fluoro" } { "classname" "light" "origin" "768 1232 584" "light" "250" } { "light" "200" "origin" "984 1472 514" "classname" "light" } { "style" "10" "origin" "844 1764 528" "classname" "light_fluorospark" } { "light" "250" "classname" "light" "origin" "1536 1560 440" } { "light" "250" "origin" "1520 1232 440" "classname" "light" } { "light" "250" "classname" "light" "origin" "1728 1232 440" } { "light" "250" "origin" "1728 1560 440" "classname" "light" } { "light" "150" "origin" "1096 1480 168" "classname" "light_fluoro" } { "classname" "light_fluoro" "origin" "1096 1312 168" "light" "150" } { "light" "150" "origin" "1096 1312 224" "classname" "light" } { "classname" "light" "origin" "1096 1480 224" "light" "150" } { "light" "400" "origin" "1256 1456 608" "classname" "light" } { "classname" "light" "origin" "1352 1344 608" "light" "400" } { "light" "150" "origin" "1416 1552 408" "classname" "light" } { "light" "150" "classname" "light" "origin" "1408 1256 408" } { "light" "150" "origin" "1192 1256 408" "classname" "light" } { "light" "150" "classname" "light" "origin" "1184 1552 408" } { "light" "100" "origin" "1344 1456 488" "classname" "light" } { "classname" "light" "origin" "1344 1352 488" "light" "100" } { "light" "100" "origin" "1256 1352 488" "classname" "light" } { "classname" "light" "origin" "1256 1456 488" "light" "100" } { "light" "150" "origin" "1112 1528 408" "classname" "light" } { "classname" "light" "origin" "1104 1208 408" "light" "75" } { "light" "200" "origin" "1280 1520 400" "classname" "light" } { "classname" "light" "origin" "1280 1304 400" "light" "200" } { "light" "75" "origin" "1456 1200 408" "classname" "light" } { "classname" "light" "origin" "1456 1608 408" "light" "75" } { "light" "75" "origin" "1144 1608 408" "classname" "light" } { "classname" "light" "origin" "1392 1560 232" "light" "200" } { "origin" "1664 960 432" "classname" "light" } { "light" "150" "origin" "1560 1232 200" "classname" "light" } { "origin" "1488 1368 -72" "classname" "light" } { "light" "200" "origin" "1680 1160 -72" "classname" "light" } { "light" "150" "origin" "1592 752 32" "classname" "light" } { "light" "150" "origin" "1616 904 32" "classname" "light" } { "classname" "light_fluorospark" "origin" "1116 1908 528" "style" "10" } { "style" "10" "origin" "1348 1764 528" "classname" "light_fluorospark" } { "light" "250" "origin" "768 1008 584" "classname" "light_fluoro" } { "classname" "light_fluoro" "origin" "768 816 584" "light" "250" } { "light" "250" "origin" "1048 1328 352" "classname" "light" } { "classname" "light" "origin" "1048 1136 352" "light" "250" } { "classname" "light" "origin" "1048 752 350" "light" "250" } { "light" "250" "origin" "1048 944 352" "classname" "light" } { "light" "175" "origin" "1000 832 176" "classname" "light" } { "light" "175" "origin" "744 736 172" "classname" "light" } { "classname" "light" "origin" "808 672 172" "light" "175" } { "light" "125" "origin" "1664 1624 256" "classname" "light" } { "classname" "light" "origin" "1664 1720 256" "light" "125" } { "light" "200" "origin" "1880 1696 148" "classname" "light" } { "classname" "light" "origin" "1880 1528 148" "light" "200" } { "light" "200" "origin" "1880 1352 148" "classname" "light" } { "classname" "light" "origin" "1880 1152 148" "light" "200" } { "light" "200" "origin" "1880 936 148" "classname" "light" } { "classname" "light" "origin" "2064 1832 148" "light" "200" } { "light" "200" "origin" "2064 1688 148" "classname" "light" } { "classname" "light" "origin" "2064 1528 148" "light" "200" } { "light" "200" "origin" "2064 1352 148" "classname" "light" } { "classname" "light" "origin" "2064 1160 148" "light" "200" } { "light" "200" "origin" "2064 952 148" "classname" "light" } { "classname" "light" "origin" "2064 824 148" "light" "200" } { "light" "200" "origin" "2064 688 148" "classname" "light" } { "light" "250" "origin" "1552 1792 288" "classname" "light_fluoro" } { "light" "200" "origin" "1976 1680 352" "classname" "light" } { "classname" "light_fluoro" "origin" "1976 1616 352" "light" "200" } { "light" "200" "origin" "1976 1344 352" "classname" "light" } { "classname" "light_fluoro" "origin" "1976 1280 352" "light" "200" } { "style" "10" "light" "150" "origin" "1976 1040 368" "classname" "light_fluorospark" } { "style" "10" "classname" "light" "origin" "1976 968 368" "light" "150" } { "light" "200" "origin" "1976 1648 232" "classname" "light" } { "light" "200" "origin" "1976 1312 264" "classname" "light" } { "light" "200" "origin" "1976 1000 344" "classname" "light" } { "light" "175" "origin" "1880 1752 272" "classname" "light" } { "classname" "light" "origin" "1976 688 352" "light" "250" } { "light" "175" "origin" "1952 1824 208" "classname" "light" } { "light" "200" "origin" "1976 1472 472" "classname" "light" } { "classname" "light" "origin" "1976 1768 472" "light" "200" } { "light" "200" "origin" "1976 1152 472" "classname" "light" } { "classname" "light" "origin" "1976 776 472" "light" "150" } { "lip" "12" "speed" "50" "wait" "-1" "angle" "270" "classname" "func_door" "targetname" "t24" "model" "*13" } { "target" "t24" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*14" } { "classname" "light_fluoro" "origin" "2000 480 232" "light" "250" } { "light" "200" "origin" "2312 384 160" "classname" "light" } { "light" "200" "origin" "2168 304 160" "classname" "light" } { "classname" "light" "origin" "1960 304 160" "light" "200" } { "light" "250" "origin" "2072 -144 336" "classname" "light" } { "light" "200" "origin" "2072 432 -400" "classname" "light" } { "spawnflags" "2048" "sounds" "3" "origin" "1408 1408 376" "classname" "item_key2" } { "light" "100" "origin" "1760 1616 200" "classname" "light" } { "classname" "light" "origin" "1568 1616 200" "light" "100" } { "target" "t31" "classname" "trigger_once" "model" "*15" } { "light" "250" "origin" "1144 736 -184" "classname" "light" } { "light" "175" "origin" "1312 744 -96" "classname" "light" } { "origin" "1160 912 648" "classname" "item_shells" } { "target" "t33" "targetname" "t32" "origin" "1240 456 280" "classname" "path_corner" } { "target" "t32" "targetname" "t33" "classname" "path_corner" "origin" "1376 456 280" } { "target" "t32" "angle" "180" "origin" "1320 456 296" "classname" "monster_enforcer" "spawnflags" "257" } { "classname" "path_corner" "origin" "1312 904 88" "targetname" "t34" "target" "t35" } { "origin" "1488 752 88" "classname" "path_corner" "target" "t34" "targetname" "t38" } { "origin" "1312 1224 88" "classname" "path_corner" "targetname" "t35" "target" "t36" } { "classname" "path_corner" "origin" "1664 1224 88" "targetname" "t36" "target" "t37" } { "origin" "1664 752 88" "classname" "path_corner" "targetname" "t37" "target" "t38" } { "classname" "monster_army" "origin" "1576 1224 104" "angle" "0" "target" "t36" "spawnflags" "1" } { "classname" "monster_army" "origin" "1664 752 296" "angle" "90" "spawnflags" "1281" } { "classname" "monster_army" "origin" "1664 1792 184" "angle" "270" "spawnflags" "1" } { "classname" "path_corner" "origin" "1928 1784 168" "targetname" "t41" "target" "t42" } { "origin" "2016 1784 168" "classname" "path_corner" "target" "t41" "targetname" "t45" } { "classname" "path_corner" "origin" "1928 1408 168" "targetname" "t42" "target" "t43" } { "origin" "2016 1408 168" "classname" "path_corner" "targetname" "t46" "target" "t45" } { "classname" "path_corner" "origin" "2016 896 280" "targetname" "t44" "target" "t46" } { "origin" "1928 896 280" "classname" "path_corner" "targetname" "t43" "target" "t44" } { "spawnflags" "769" "classname" "monster_army" "origin" "1928 1472 184" "angle" "270" "target" "t42" } { "target" "t59" "classname" "monster_enforcer" "origin" "760 552 448" "angle" "90" "spawnflags" "257" } { "classname" "func_door" "angle" "-2" "speed" "300" "wait" "-1" "targetname" "t48" "sounds" "2" "model" "*16" } { "classname" "light" "origin" "1968 1960 216" "light" "150" } { "classname" "trigger_once" "target" "t48" "model" "*17" } { "classname" "monster_army" "origin" "2016 1480 184" "target" "t46" "spawnflags" "1" } { "classname" "monster_army" "origin" "1936 944 296" "angle" "270" "target" "t43" "spawnflags" "257" } { "classname" "monster_army" "origin" "1968 1776 184" "target" "t41" "spawnflags" "1" } { "classname" "monster_dog" "origin" "2008 1928 184" "angle" "270" "targetname" "t48" } { "angle" "270" "origin" "1928 1928 184" "classname" "monster_dog" "targetname" "t48" "spawnflags" "256" } { "classname" "monster_dog" "origin" "1840 1928 184" "angle" "270" "targetname" "t48" } { "light" "150" "origin" "1880 1960 216" "classname" "light" } { "classname" "func_door" "angle" "0" "speed" "800" "lip" "-4" "wait" "-1" "targetname" "t49" "sounds" "2" "model" "*18" } { "classname" "monster_enforcer" "origin" "1184 1856 584" "angle" "180" "targetname" "t49" } { "classname" "trigger_once" "target" "t50" "model" "*19" } { "classname" "monster_dog" "origin" "1096 1856 416" "angle" "180" "targetname" "t50" "spawnflags" "1" } { "target" "t49" "classname" "monster_army" "origin" "1232 1856 416" "angle" "180" "targetname" "t50" "spawnflags" "1" } { "classname" "func_door_secret" "angle" "90" "spawnflags" "1" "targetname" "t51" "model" "*20" } { "wait" "-1" "classname" "func_button" "angle" "-1" "target" "t51" "lip" "96" "model" "*21" } { "light" "125" "origin" "2160 1024 352" "classname" "light" } { "targetname" "t30" "message" "You have opened the flood gates...." "classname" "trigger_once" "model" "*22" } { "light" "250" "origin" "1976 1744 112" "classname" "light" } { "light" "250" "classname" "light" "origin" "1976 1544 112" } { "origin" "1976 1360 112" "classname" "light" } { "light" "250" "classname" "light" "origin" "1984 1368 112" } { "target" "t34" "angle" "90" "origin" "1312 860 104" "classname" "monster_army" "spawnflags" "1" } { "targetname" "t52" "sounds" "2" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*23" } //{ //"target" "t52" //"health" "1" //"sounds" "2" //"wait" "-1" //"angle" "90" //"classname" "func_button" //"model" "*24" //} { "light" "100" "origin" "1120 1224 104" "classname" "light" } { "target" "t53" "classname" "trigger_teleport" "model" "*25" } { "targetname" "t53" "angle" "0" "origin" "1120 1224 96" "classname" "info_teleport_destination" } { "light" "150" "origin" "928 528 -156" "classname" "light" } { "classname" "light" "origin" "992 528 -156" "light" "150" } { "origin" "1008 1464 422" "classname" "item_health" } { "targetname" "t57" "target" "t54" "origin" "1016 1160 120" "classname" "path_corner" } { "target" "t55" "targetname" "t54" "classname" "path_corner" "origin" "768 1160 120" } { "target" "t57" "targetname" "t56" "origin" "768 1160 120" "classname" "path_corner" } { "target" "t56" "targetname" "t55" "classname" "path_corner" "origin" "768 776 120" } { "target" "t57" "origin" "1000 1080 136" "classname" "monster_army" "spawnflags" "1" } { "targetname" "t59" "target" "t58" "origin" "768 608 432" "classname" "path_corner" } { "target" "t59" "targetname" "t58" "classname" "path_corner" "origin" "768 1088 432" } { "angle" "0" "origin" "744 416 448" "classname" "monster_army" "spawnflags" "257" } { "targetname" "t74" "target" "t61" "angle" "270" "origin" "864 1800 416" "classname" "monster_enforcer" "spawnflags" "257" } { "target" "t60" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t61" "model" "*26" } { "targetname" "t61" "angle" "90" "origin" "744 144 452" "classname" "monster_enforcer" "spawnflags" "256" } { "targetname" "t60" "angle" "90" "origin" "752 424 428" "classname" "info_teleport_destination" } { "targetname" "t69" "target" "t62" "origin" "1344 1552 360" "classname" "path_corner" } { "target" "t63" "targetname" "t62" "classname" "path_corner" "origin" "1176 1520 360" } { "target" "t64" "targetname" "t63" "origin" "1120 1408 360" "classname" "path_corner" } { "target" "t65" "targetname" "t64" "classname" "path_corner" "origin" "1184 1296 360" } { "target" "t66" "targetname" "t65" "origin" "1352 1272 360" "classname" "path_corner" } { "target" "t67" "targetname" "t66" "classname" "path_corner" "origin" "1184 1272 360" } { "target" "t68" "targetname" "t67" "origin" "1120 1408 360" "classname" "path_corner" } { "target" "t69" "targetname" "t68" "classname" "path_corner" "origin" "1176 1536 360" } { "target" "t69" "angle" "225" "origin" "1312 1576 376" "classname" "monster_enforcer" "spawnflags" "769" } { "target" "t37" "angle" "270" "origin" "1664 912 104" "classname" "monster_army" "spawnflags" "1" } { "target" "t72" "targetname" "t71" "origin" "1536 1560 168" "classname" "path_corner" } { "target" "t73" "targetname" "t72" "classname" "path_corner" "origin" "1128 1560 96" } { "target" "t71" "targetname" "t70" "origin" "1128 1560 96" "classname" "path_corner" } { "targetname" "t73" "target" "t70" "classname" "path_corner" "origin" "1128 1304 96" } { "target" "t71" "angle" "0" "origin" "1536 1560 192" "classname" "monster_army" "spawnflags" "1" } { "light" "250" "origin" "1472 744 -296" "classname" "light" } { "target" "t74" "classname" "trigger_once" "model" "*27" } { "targetname" "t78" "target" "t75" "origin" "2368 384 88" "classname" "path_corner" } { "target" "t78" "targetname" "t76" "classname" "path_corner" "origin" "2368 40 88" } { "target" "t77" "targetname" "t75" "origin" "2368 64 88" "classname" "path_corner" } { "target" "t76" "targetname" "t77" "classname" "path_corner" "origin" "1984 48 88" } { "target" "t75" "angle" "270" "origin" "2352 280 104" "classname" "monster_army" "spawnflags" "1" } { "target" "t79" "classname" "trigger_once" "model" "*28" } { "targetname" "t79" "angle" "135" "origin" "1976 -360 200" "classname" "monster_army" "spawnflags" "257" } { "targetname" "t79" "classname" "monster_army" "origin" "2144 -360 200" "angle" "45" "spawnflags" "1" } { "angle" "270" "origin" "2072 -756 104" "classname" "monster_enforcer" "spawnflags" "257" } { "target" "t53" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t48" "model" "*29" } { "target" "t103" "targetname" "t48" "angle" "270" "origin" "1560 2032 184" "classname" "monster_enforcer" "spawnflags" "256" } { "spawnflags" "2050" "origin" "2152 1560 272" "classname" "item_health" } { "target" "t53" "classname" "trigger_teleport" "spawnflags" "2" "model" "*30" } { "targetname" "t81" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*31" } { "target" "t80" "angle" "270" "origin" "1416 2080 184" "classname" "monster_army" } { "target" "t35" "targetname" "t80" "origin" "1416 2040 168" "classname" "path_corner" } { "target" "t81" "classname" "trigger_once" "model" "*32" } { "spawnflags" "1" "origin" "1568 1816 160" "classname" "item_health" } { "classname" "item_health" "origin" "1616 1816 160" "spawnflags" "1" } { "angle" "180" "origin" "1480 432 104" "classname" "monster_army" "spawnflags" "257" } { "spawnflags" "2048" "origin" "1184 1400 352" "classname" "weapon_nailgun" } { "origin" "1200 1192 352" "classname" "item_health" } { "classname" "item_health" "origin" "1248 1192 352" } { "origin" "1392 1288 352" "classname" "item_spikes" "spawnflags" "1" } { "spawnflags" "1" "origin" "1800 1992 160" "classname" "item_spikes" } { "classname" "light" "origin" "2144 1552 352" "light" "175" } { "light" "150" "origin" "2144 1400 352" "classname" "light" } { "spawnflags" "257" "target" "t83" "angle" "225" "origin" "2128 1576 280" "classname" "monster_army" } { "angle" "270" "origin" "776 1488 176" "classname" "monster_army" "spawnflags" "257" } { "spawnflags" "769" "classname" "monster_army" "origin" "1008 1040 136" "angle" "270" } { "angle" "270" "origin" "768 1432 176" "classname" "monster_dog" "spawnflags" "1" } { "angle" "180" "origin" "1456 428 296" "classname" "monster_army" "spawnflags" "257" } { "origin" "1008 1464 192" "classname" "item_health" } { "spawnflags" "256" "angle" "225" "origin" "2304 416 104" "classname" "monster_enforcer" } { "classname" "trigger_secret" "model" "*33" } { "origin" "792 640 112" "classname" "item_health" } { "origin" "792 680 112" "classname" "item_spikes" "spawnflags" "1" } { "angle" "270" "classname" "func_door_secret" "model" "*34" } { "light" "150" "origin" "632 424 528" "classname" "light" } { "classname" "trigger_secret" "model" "*35" } { "origin" "600 424 424" "classname" "item_armor2" } { "target" "t84" "classname" "monster_army" "origin" "1736 1520 184" "angle" "270" "spawnflags" "1" } { "spawnflags" "257" "targetname" "t91" "angle" "90" "origin" "1104 1208 376" "classname" "monster_army" } { "target" "t86" "targetname" "t84" "spawnflags" "1" "classname" "trigger_counter" "model" "*36" } { "target" "t85" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t86" "model" "*37" } { "targetname" "t85" "angle" "90" "origin" "1664 824 88" "classname" "info_teleport_destination" } { "targetname" "t86" "angle" "90" "origin" "1664 216 120" "classname" "monster_army" } { "target" "t84" "classname" "trigger_once" "model" "*38" } { "targetname" "t88" "target" "t89" "origin" "2312 216 88" "classname" "path_corner" "spawnflags" "256" } { "target" "t88" "targetname" "t87" "classname" "path_corner" "origin" "2312 96 88" "spawnflags" "256" } { "target" "t90" "targetname" "t89" "origin" "2336 112 88" "classname" "path_corner" "spawnflags" "256" } { "targetname" "t90" "classname" "path_corner" "origin" "2184 88 88" "spawnflags" "256" } { "target" "t88" "origin" "2320 176 104" "classname" "monster_enforcer" "spawnflags" "257" } { "spawnflags" "1" "origin" "816 432 424" "classname" "item_health" } { "target" "t91" "spawnflags" "256" "classname" "trigger_once" "model" "*39" } { "targetname" "t83" "spawnflags" "257" "angle" "270" "origin" "2120 1168 304" "classname" "monster_enforcer" } { "spawnflags" "768" "angle" "0" "origin" "1560 1784 440" "classname" "monster_enforcer" } { "spawnflags" "768" "classname" "func_wall" "model" "*40" } { "targetname" "t93" "target" "t92" "origin" "1976 1224 240" "classname" "path_corner" } { "target" "t93" "targetname" "t92" "origin" "1976 984 288" "classname" "path_corner" } { "target" "t93" "spawnflags" "769" "angle" "270" "origin" "1968 1264 240" "classname" "monster_army" } { "angle" "270" "origin" "1384 936 296" "classname" "monster_army" "spawnflags" "769" "target" "t94" } { "classname" "item_spikes" "origin" "1224 512 272" "spawnflags" "1" } { "classname" "item_health" "origin" "1240 1752 352" "spawnflags" "3584" } { "spawnflags" "3585" "origin" "1240 1704 352" "classname" "item_health" } { "classname" "item_spikes" "origin" "2456 112 88" "spawnflags" "1" } { "classname" "monster_enforcer" "origin" "1832 808 296" "angle" "0" "spawnflags" "1" } { "classname" "monster_enforcer" "origin" "1112 1224 112" "angle" "0" "spawnflags" "768" } { "spawnflags" "769" "classname" "monster_enforcer" "origin" "1336 1704 376" "angle" "90" } { "classname" "monster_enforcer" "origin" "1664 736 296" "spawnflags" "769" } { "classname" "item_health" "origin" "1736 1584 160" } { "classname" "path_corner" "origin" "1208 936 280" "targetname" "t95" "target" "t94" } { "origin" "1416 936 280" "classname" "path_corner" "targetname" "t94" "target" "t95" } { "classname" "path_corner" "origin" "768 1200 432" "target" "t96" "targetname" "t97" "spawnflags" "768" } { "origin" "768 1432 432" "classname" "path_corner" "targetname" "t96" "target" "t97" "spawnflags" "768" } { "classname" "monster_enforcer" "origin" "760 1264 448" "spawnflags" "769" "target" "t97" } { "classname" "monster_army" "origin" "2120 1424 280" "angle" "180" "spawnflags" "1" } { "spawnflags" "1281" "classname" "monster_enforcer" "origin" "2072 -160 152" "angle" "90" } { "classname" "monster_army" "origin" "2160 -960 104" "angle" "270" "targetname" "t98" "spawnflags" "256" } { "angle" "270" "origin" "1984 -960 104" "classname" "monster_army" "targetname" "t98" "spawnflags" "256" } { "classname" "trigger_once" "spawnflags" "2304" "target" "t98" "model" "*41" } { "classname" "monster_army" "origin" "2072 -768 104" "angle" "270" "spawnflags" "1537" } { "classname" "item_armor2" "origin" "1672 1560 160" "spawnflags" "3584" } { "classname" "item_health" "origin" "1176 736 80" "spawnflags" "3584" } { "spawnflags" "3584" "origin" "1176 680 80" "classname" "item_health" } { "classname" "item_health" "origin" "728 912 424" } { "classname" "item_spikes" "origin" "728 720 112" "spawnflags" "3584" } { "classname" "item_health" "origin" "1824 680 272" "spawnflags" "3584" } { "classname" "monster_army" "origin" "792 552 448" "angle" "90" "spawnflags" "1537" "target" "t59" } { "classname" "trigger_secret" "model" "*42" } { "spawnflags" "2048" "classname" "func_wall" "model" "*43" } { "spawnflags" "1792" "origin" "2072 -704 80" "classname" "item_armorInv" } { "spawnflags" "1792" "origin" "2312 96 80" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "1184 1400 352" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "904 1480 424" "classname" "weapon_supernailgun" } { "angle" "180" "origin" "984 1480 448" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "1968 1824 184" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "1296 592 80" "classname" "item_rockets" } //{ //"spawnflags" "1792" //"origin" "1312 552 272" //"classname" "weapon_lightning" //} { "spawnflags" "1792" "origin" "1864 2008 160" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "1648 768 272" "classname" "item_rockets" } { "target" "t35" "angle" "180" "origin" "1376 1224 104" "classname" "monster_army" "spawnflags" "1" } { "angle" "270" "origin" "2072 -344 200" "classname" "monster_enforcer" "spawnflags" "1" } { "classname" "item_armor2" "origin" "2168 1576 256" //Q-Man "spawnflags" "1792" } { "angle" "0" "origin" "1104 752 296" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "2192 -360 200" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "1112 1608 104" "classname" "info_player_deathmatch" } { "classname" "item_artifact_super_damage" "origin" "2168 1528 280" } { "origin" "640 424 448" "classname" "item_artifact_super_damage" } { "classname" "misc_explobox2" "origin" "880 1056 112" } { "classname" "misc_explobox" "origin" "832 1080 112" } { "classname" "item_health" "origin" "2008 1992 160" } { "origin" "1960 1992 164" "classname" "item_health" } { "origin" "1256 552 272" "classname" "item_health" } { "classname" "item_health" "origin" "1328 552 272" } { "spawnflags" "2048" "origin" "1272 736 -128" "classname" "item_health" } { "spawnflags" "2048" "classname" "item_health" "origin" "1336 736 -128" } { "map" "e4m2" "classname" "trigger_changelevel" "model" "*44" } { "origin" "1488 1592 160" "classname" "item_health" } { "classname" "light" "origin" "1664 352 -136" "light" "150" } { "classname" "light" "origin" "2320 -144 16" "light" "200" } { "light" "200" "origin" "2320 -336 16" "classname" "light" } { "classname" "light" "origin" "1664 1024 -184" "light" "125" } { "spawnflags" "768" "angle" "180" "origin" "2400 -304 -40" "classname" "monster_enforcer" "targetname" "t99" } { "style" "32" "classname" "trigger_once" "target" "t99" "sounds" "3" "model" "*45" } { "style" "32" "spawnflags" "1" "light" "250" "origin" "2320 -232 -56" "classname" "light" "targetname" "t99" } { "spawnflags" "256" "targetname" "t99" "angle" "180" "origin" "2400 -160 -40" "classname" "monster_army" } { "angle" "180" "classname" "trigger_monsterjump" "model" "*46" } { "targetname" "t99" "classname" "monster_army" "origin" "2400 -296 -40" "angle" "180" "spawnflags" "1024" } { "spawnflags" "1" "origin" "2384 -216 -64" "classname" "item_health" } { "origin" "2384 -256 -64" "classname" "item_shells" } { "origin" "2056 -248 -432" "classname" "item_health" } { "classname" "item_health" "origin" "2056 -296 -432" } { "spawnflags" "1792" "classname" "func_wall" "model" "*47" } { "style" "1" "light" "150" "origin" "1448 904 728" "classname" "light" } { "classname" "light" "origin" "1432 392 80" "light" "150" } { "light" "150" "origin" "1288 392 80" "classname" "light" } { "spawnflags" "2048" "origin" "2072 -392 200" "classname" "item_artifact_envirosuit" } { "classname" "misc_explobox" "origin" "1584 1480 168" } { "classname" "func_door" "angle" "-1" "wait" "-1" "speed" "300" "sounds" "2" "targetname" "t100" "model" "*48" } { "classname" "trigger_once" "target" "t100" "model" "*49" } { "classname" "func_wall" "spawnflags" "3072" "model" "*50" } { "classname" "item_health" "origin" "1648 1376 -152" } { "origin" "1648 1336 -152" "classname" "item_health" } { "classname" "item_health" "origin" "2096 456 -432" "spawnflags" "1" } { "spawnflags" "1" "origin" "2000 456 -432" "classname" "item_health" } { "classname" "light" "origin" "1032 920 472" "light" "100" } { "light" "100" "origin" "1032 872 472" "classname" "light" } { "classname" "light" "origin" "1032 1176 472" "light" "100" } { "light" "100" "origin" "1032 1128 472" "classname" "light" } { "classname" "trap_spikeshooter" "origin" "1048 898 454" "spawnflags" "2" "angle" "180" "targetname" "t101" } { "angle" "180" "spawnflags" "2" "origin" "1048 1154 454" "classname" "trap_spikeshooter" "targetname" "t102" } { "classname" "trigger_multiple" "wait" ".8" "target" "t101" "model" "*51" } { "classname" "trigger_multiple" "delay" ".4" "targetname" "t101" "target" "t102" "model" "*52" } { "style" "32" "classname" "light" "origin" "1824 -112 -408" "light" "250" "spawnflags" "1" "targetname" "t99" } { "style" "32" "spawnflags" "1" "light" "250" "origin" "1824 -304 -408" "classname" "light" "targetname" "t99" } { "style" "32" "classname" "light" "origin" "2320 -312 -408" "light" "250" "spawnflags" "1" "targetname" "t99" } { "style" "32" "spawnflags" "1" "light" "250" "origin" "2320 -120 -408" "classname" "light" "targetname" "t99" } { "classname" "item_artifact_envirosuit" "origin" "1248 640 104" "spawnflags" "3584" } { "mangle" "20 225 0" "origin" "1760 1608 424" "classname" "info_intermission" } { "classname" "info_intermission" "origin" "1024 640 560" "mangle" "20 120 0" } { "classname" "info_intermission" "origin" "1184 896 440" "mangle" "20 315 0" } { "classname" "info_intermission" "origin" "2000 -792 288" "mangle" "20 80 0" } { "classname" "item_health" "origin" "1600 528 -216" "spawnflags" "3072" } { "origin" "1696 528 -216" "classname" "item_health" } { "classname" "item_spikes" "origin" "1900 -608 176" "spawnflags" "1" //Q-Man } //{ //"spawnflags" "1792" //"origin" "2072 -392 200" //"classname" "item_artifact_invulnerability" //} { "spawnflags" "1792" "classname" "weapon_lightning" //Q-Man "origin" "952 1048 112" } { "classname" "item_spikes" "origin" "1880 16 80" } { "classname" "item_shells" "origin" "1648 768 272" "spawnflags" "2048" } { "classname" "item_shells" "origin" "1320 1880 352" } { "classname" "item_health" "origin" "888 1464 168" } { "classname" "item_spikes" "origin" "1296 912 272" "spawnflags" "1" } { "classname" "info_player_coop" "origin" "1200 576 672" "angle" "90" } { "angle" "90" "origin" "1408 568 672" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1376 880 672" "angle" "270" } { "style" "10" "light" "150" "origin" "2072 -464 -162" "classname" "light" } { "spawnflags" "1792" "classname" "func_wall" "model" "*53" } { "spawnflags" "1792" "classname" "func_wall" "model" "*54" } { "spawnflags" "1792" "origin" "1308 860 680" "classname" "item_artifact_invisibility" } { "classname" "trigger_secret" "model" "*55" } { "spawnflags" "2" "classname" "trigger_teleport" "targetname" "t103" "target" "t53" "model" "*56" } { "spawnflags" "256" "angle" "270" "origin" "1664 2032 184" "classname" "monster_enforcer" "targetname" "t103" } { "origin" "1426 882 728" "classname" "ambient_comp_hum" } { "classname" "ambient_comp_hum" "origin" "1370 490 392" } { "origin" "1226 490 392" "classname" "ambient_comp_hum" } { "classname" "ambient_comp_hum" "origin" "1778 1778 320" } { "classname" "ambient_comp_hum" "origin" "986 1474 528" } { "classname" "ambient_comp_hum" "origin" "794 722 232" } { "classname" "ambient_comp_hum" "origin" "2074 -182 232" } { "classname" "ambient_comp_hum" "origin" "2066 -726 232" } { "classname" "ambient_drone" "origin" "2074 -862 184" } { "spawnflags" "3584" "origin" "1312 920 656" "classname" "item_armor1" } //Q-Man { "classname" "item_flag_team1" "origin" "1312 449 296" } { "classname" "info_player_team1" "origin" "1470 910 296" "angle" "225" } { "classname" "info_player_team1" "origin" "1150 910 296" "angle" "315" } { "classname" "info_player_team1" "origin" "1470 623 296" "angle" "135" } { "classname" "info_player_team1" "origin" "1150 623 296" "angle" "45" } { "classname" "info_player_team1" "origin" "1312 552 296" "angle" "270" } { "classname" "info_player_team1" "origin" "1312 568 688" "angle" "90" } { "classname" "item_flag_team2" "origin" "2071 -767 104" } { "classname" "info_player_team2" "origin" "2000 -515 100" "angle" "315" } { "classname" "info_player_team2" "origin" "2150 -515 100" "angle" "225" } { "classname" "info_player_team2" "origin" "1950 -430 200" "angle" "315" } { "classname" "info_player_team2" "origin" "2190 -430 200" "angle" "225" } { "classname" "info_player_team2" "origin" "2071 -23 104" "angle" "90" } { "classname" "info_player_team2" "origin" "2317 357 104" "angle" "180" } { "classname" "weapon_supershotgun" "origin" "2000 -515 100" } { "classname" "weapon_supernailgun" "origin" "2150 -515 100" } { "classname" "weapon_supershotgun" "origin" "1110 768 296" } { "classname" "weapon_supernailgun" "origin" "1507 768 296" } { "origin" "2113 -738 104" "classname" "item_health" } { "origin" "1985 -738 104" "classname" "item_health" } { "classname" "item_shells" "spawnflags" "1" "origin" "2072 -392 200" } { "origin" "2392 -128 -40" "classname" "weapon_nailgun" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m2.ent000066400000000000000000000671421475442401000252050ustar00rootroot00000000000000{ "message" "The Tower of Despair" "worldtype" "0" "classname" "worldspawn" "wad" "gfx/medieval.wad" "sounds" "8" } { "classname" "light" "origin" "0 0 1032" "light" "350" } { "light" "400" "classname" "light_flame_large_yellow" "origin" "-406 930 860" } { "origin" "-406 -406 860" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "402 -406 860" "light" "300" } { "light" "400" "origin" "402 402 860" "classname" "light_flame_large_yellow" } { "speed" "150" "wait" "1.5" "classname" "func_door_secret" "angle" "270" "health" "1" "dmg" "1000" "sounds" "1" "model" "*1" } { "classname" "light" "origin" "-648 8 824" } { "classname" "func_plat" "model" "*2" } { "classname" "weapon_rocketlauncher" "origin" "-824 -752 496" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "24 -416 768" "spawnflags" "1" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t3" "model" "*3" } { "classname" "info_teleport_destination" "origin" "128 -176 1208" "angle" "90" "targetname" "t3" } { "classname" "func_door_secret" "spawnflags" "4" "angle" "270" "health" "1" "targetname" "t16" "wait" "6" "sounds" "1" "model" "*4" } { "classname" "light" "origin" "168 -480 856" "light" "200" } { "classname" "light" "origin" "112 -192 1160" "light" "150" } { "classname" "light" "origin" "352 -72 704" "light" "200" } { "classname" "path_corner" "origin" "384 -384 792" "targetname" "t6" "target" "t11" } { "classname" "path_corner" "origin" "-384 448 792" "targetname" "t13" "target" "t12" } { "classname" "path_corner" "origin" "-320 448 792" "targetname" "t15" "target" "t14" } { "spawnflags" "768" "targetname" "t79" "classname" "monster_knight" "origin" "-192 352 792" "angle" "315" } { "spawnflags" "768" "targetname" "t79" "classname" "monster_knight" "origin" "192 352 792" "angle" "180" } { "classname" "path_corner" "origin" "-384 832 792" "targetname" "t12" "target" "t13" } { "classname" "path_corner" "origin" "-320 832 792" "targetname" "t14" "target" "t15" } { "classname" "path_corner" "origin" "320 312 792" "targetname" "t9" "target" "t10" } { "classname" "path_corner" "origin" "384 312 792" "targetname" "t11" "target" "t6" } { "classname" "path_corner" "origin" "320 -384 792" "targetname" "t10" "target" "t9" } { "classname" "monster_knight" "origin" "384 -336 792" "angle" "90" "target" "t11" } { "classname" "monster_knight" "origin" "-320 496 792" "target" "t14" "spawnflags" "256" } { "classname" "monster_knight" "origin" "-384 496 792" "angle" "90" "target" "t12" } { "classname" "monster_knight" "origin" "320 -336 792" "angle" "90" "target" "t9" "spawnflags" "256" } { "classname" "func_button" "angle" "270" "wait" "6" "target" "t16" "sounds" "1" "model" "*5" } { "classname" "light_torch_small_walltorch" "origin" "-740 -568 672" "light" "400" } { "classname" "light" "origin" "-632 -8 696" } { "classname" "monster_ogre" "origin" "-120 -352 792" "angle" "180" "spawnflags" "256" } { "spawnflags" "1" "classname" "item_shells" "origin" "-240 208 768" } { "light" "400" "classname" "light" "origin" "-1104 -2200 384" } { "classname" "info_teleport_destination" "origin" "-656 280 1096" "angle" "270" "targetname" "t17" } { "classname" "info_teleport_destination" "origin" "-944 0 1096" "angle" "0" "targetname" "t18" } { "classname" "info_teleport_destination" "origin" "-656 -288 1096" "angle" "90" "targetname" "t19" } { "classname" "trigger_teleport" "target" "t17" "model" "*6" } { "classname" "trigger_teleport" "target" "t18" "model" "*7" } { "classname" "trigger_teleport" "target" "t19" "model" "*8" } { "classname" "light" "origin" "-952 24 840" "light" "180" } { "targetname" "t77" "classname" "monster_shambler" "origin" "-664 -480 376" "angle" "90" } { "light" "600" "classname" "light" "origin" "-70 -2500 672" } { "classname" "func_door" "angle" "-1" "model" "*9" } { "classname" "func_door" "angle" "0" "model" "*10" } { "message" "You opened the cages! " "wait" "-1" "target" "t21" "angle" "-2" "classname" "func_button" "sounds" "1" "model" "*11" } { "targetname" "t21" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "3" "model" "*12" } { "targetname" "t21" "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "model" "*13" } { "origin" "-16 -160 768" "classname" "item_shells" } { "origin" "0 -216 960" "classname" "light" } { "targetname" "t21" "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "model" "*14" } { "targetname" "t21" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "3" "model" "*15" } { "light" "400" "classname" "light" "origin" "260 -2368 680" } { "classname" "func_door" "angle" "0" "health" "1" "model" "*16" } { "classname" "func_door" "angle" "-2" "health" "1" "model" "*17" } { "classname" "func_door" "angle" "180" "health" "1" "model" "*18" } { "classname" "func_door" "angle" "-1" "health" "1" "model" "*19" } { "spawnflags" "256" "classname" "monster_ogre" "origin" "216 -2296 648" "angle" "225" } { "classname" "monster_ogre" "origin" "216 -2432 648" "angle" "135" } { "classname" "func_plat" "model" "*20" } { "angle" "90" "classname" "func_button" "wait" "-1" "target" "t22" "sounds" "0" "model" "*21" } { "classname" "func_door" "angle" "90" "speed" "200" "wait" "-1" "targetname" "t22" "sounds" "1" "lip" "0" "model" "*22" } { "origin" "-50 -2754 876" "classname" "light_flame_large_yellow" } { "wait" "-1" "angle" "270" "classname" "func_door" "targetname" "t22" "sounds" "3" "model" "*23" } { "origin" "-206 -2642 668" "classname" "light_flame_large_yellow" } { "classname" "func_plat" "height" "128" "targetname" "t24" "sounds" "2" "model" "*24" } { "targetname" "t24" "classname" "func_door_secret" "angle" "0" "wait" "-1" "sounds" "1" "model" "*25" } { "classname" "light_flame_large_yellow" "origin" "-564 -878 500" "light" "450" } { "classname" "light" "origin" "-928 120 832" } { "target" "t30" "classname" "trigger_teleport" "model" "*26" } { "classname" "func_button" "angle" "180" "wait" "-1" "target" "t24" "sounds" "0" "model" "*27" } { "classname" "light" "origin" "352 -2800 632" "light" "400" } { "classname" "func_door" "angle" "-2" "lip" "24" "dmg" "100" "speed" "200" "targetname" "t25" "wait" "2" "sounds" "1" "model" "*28" } { "classname" "trigger_multiple" "target" "t25" "wait" "2" "model" "*29" } { "classname" "trigger_multiple" "target" "t25" "wait" "2" "model" "*30" } { "classname" "func_button" "angle" "270" "wait" "-1" "target" "t26" "sounds" "0" "model" "*31" } { "classname" "func_door" "wait" "-1" "lip" "16" "angle" "-2" "targetname" "t26" "sounds" "3" "model" "*32" } { "origin" "-1504 -192 520" "classname" "light" } { "angle" "90" "targetname" "t27" "origin" "-1504 -224 456" "classname" "info_teleport_destination" } { "light" "400" "origin" "-1504 -280 224" "classname" "light" } { "target" "t30" "classname" "trigger_teleport" "model" "*33" } { "classname" "light" "origin" "-352 -2736 576" } { "classname" "trigger_teleport" "target" "t27" "model" "*34" } { "classname" "info_teleport_destination" "origin" "-128 -2288 616" "angle" "270" "targetname" "t30" } { "classname" "item_health" "origin" "-64 -416 768" "spawnflags" "1" } { "classname" "monster_knight" "origin" "168 -1744 376" "angle" "90" "target" "t31" } { "classname" "path_corner" "origin" "168 -1480 376" "targetname" "t31" "target" "t32" } { "classname" "path_corner" "origin" "168 -1768 376" "targetname" "t32" "target" "t31" } { "classname" "path_corner" "origin" "-680 -2072 392" "targetname" "t37" "target" "t38" } { "classname" "path_corner" "origin" "-680 -2264 392" "targetname" "t38" "target" "t37" } { "classname" "monster_knight" "origin" "-680 -2192 392" "angle" "90" "target" "t37" "spawnflags" "256" } { "classname" "item_health" "origin" "64 -2512 816" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-320 -2464 816" } { "classname" "light_torch_small_walltorch" "origin" "-228 -2700 616" "light" "400" } { "spawnflags" "1" "classname" "item_spikes" "origin" "-40 -2280 512" } { "classname" "item_shells" "origin" "16 -1928 528" "spawnflags" "1" } { "targetname" "t81" "classname" "monster_ogre" "origin" "800 -2432 536" "angle" "135" } { "spawnflags" "256" "targetname" "t78" "classname" "monster_ogre" "origin" "-128 -2336 640" "angle" "45" } { "classname" "monster_ogre" "origin" "-344 -2296 536" "angle" "0" "spawnflags" "768" } { "angle" "90" "origin" "264 -1680 376" "classname" "monster_knight" "target" "t45" } { "origin" "264 -1768 376" "classname" "path_corner" "targetname" "t46" "target" "t45" } { "classname" "path_corner" "origin" "264 -1480 376" "targetname" "t45" "target" "t46" } { "origin" "216 -1480 376" "classname" "path_corner" "targetname" "t47" "target" "t48" } { "classname" "path_corner" "origin" "216 -1768 376" "targetname" "t48" "target" "t47" } { "classname" "monster_knight" "origin" "216 -1712 376" "angle" "90" "target" "t47" } { "classname" "path_corner" "origin" "-528 -1888 392" "targetname" "t50" "target" "t49" } { "classname" "path_corner" "origin" "-528 -1528 376" "targetname" "t49" "target" "t50" } { "origin" "-720 -2264 392" "classname" "path_corner" "target" "t55" "targetname" "t56" } { "classname" "path_corner" "origin" "-632 -2264 392" "target" "t57" "targetname" "t58" } { "classname" "path_corner" "origin" "-720 -2072 392" "targetname" "t55" "target" "t56" } { "origin" "-632 -2072 392" "classname" "path_corner" "targetname" "t57" "target" "t58" } { "classname" "monster_knight" "origin" "-720 -2224 392" "angle" "90" "target" "t55" "spawnflags" "256" } { "angle" "90" "origin" "-632 -2144 392" "classname" "monster_knight" "target" "t57" "spawnflags" "256" } { "classname" "item_health" "origin" "496 -2640 368" } { "classname" "item_shells" "origin" "536 -2728 368" "spawnflags" "1" } { "classname" "item_health" "origin" "-544 -2784 368" } { "classname" "item_shells" "origin" "-992 -208 512" } { "classname" "item_spikes" "origin" "-488 -440 512" } { "classname" "item_spikes" "origin" "-48 -1584 352" "spawnflags" "1" } { "spawnflags" "1" "classname" "item_shells" "origin" "-840 -672 496" } { "classname" "item_health" "origin" "-496 -1936 368" "spawnflags" "1" } { "classname" "item_health" "origin" "-536 -2076 488" "spawnflags" "2" } { "origin" "-544 408 416" "classname" "light" } { "classname" "trigger_teleport" "target" "t69" "model" "*35" } { "classname" "info_teleport_destination" "origin" "0 -16 1064" "angle" "270" "targetname" "t69" } { "classname" "func_door" "angle" "180" "targetname" "t85" "sounds" "1" "model" "*36" } { "classname" "light" "origin" "-392 0 864" } { "classname" "light" "origin" "-936 -2176 432" } { "classname" "monster_knight" "origin" "-16 688 792" "angle" "180" "targetname" "t79" } { "angle" "180" "origin" "-16 624 792" "classname" "monster_knight" "targetname" "t79" "spawnflags" "256" } { "light" "400" "origin" "164 604 860" "classname" "light_flame_large_yellow" } { "classname" "monster_ogre" "origin" "-208 896 792" "angle" "0" "target" "t74" } { "origin" "-376 896 792" "classname" "path_corner" "targetname" "t74" "target" "t75" } { "classname" "path_corner" "origin" "8 896 792" "targetname" "t75" "target" "t74" } { "classname" "item_health" "origin" "-112 -1136 368" "spawnflags" "1" } { "targetname" "t21" "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "model" "*37" } { "targetname" "t21" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "3" "model" "*38" } { "target" "t77" "classname" "trigger_once" "model" "*39" } { "angle" "270" "origin" "64 224 1192" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "-192 -352 792" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "-1024 400 376" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "-760 -656 376" "classname" "info_player_deathmatch" } { "angle" "270" "origin" "-1504 -152 344" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "-416 -1920 392" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "-288 -2712 536" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "32 -2432 840" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-128 -2592 632" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "816 -2320 536" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "-352 -2288 536" "classname" "info_player_deathmatch" } { "target" "t78" "classname" "trigger_once" "model" "*40" } { "message" "The window is key to a secret. " "target" "t79" "classname" "trigger_once" "model" "*41" } { "angle" "0" "origin" "-344 -2496 840" "classname" "monster_knight" } { "spawnflags" "1536" "classname" "func_wall" "model" "*42" } { "target" "t81" "classname" "trigger_once" "model" "*43" } { "wait" "-1" "target" "t82" "angle" "90" "classname" "func_button" "sounds" "0" "model" "*44" } { "targetname" "t82" "wait" "-1" "angle" "180" "classname" "func_door_secret" "sounds" "1" "spawnflags" "2" "model" "*45" } { "spawnflags" "1" "origin" "-944 -2400 368" "classname" "item_health" } { "spawnflags" "1" "origin" "-944 -2352 368" "classname" "item_spikes" } { "spawnflags" "2048" "classname" "func_wall" "model" "*46" } { "angle" "90" "origin" "200 -2008 408" "classname" "monster_ogre" "spawnflags" "256" } { "angle" "45" "origin" "-136 -2160 520" "classname" "monster_ogre" } { "classname" "item_health" "origin" "-144 -1928 624" "spawnflags" "1" } { "classname" "item_armor2" "origin" "-704 -192 768" } { "wait" "0.5" "target" "t83" "classname" "trigger_multiple" "model" "*47" } { "targetname" "t83" "origin" "408 -2532 560" "classname" "trap_spikeshooter" "angle" "0" } { "classname" "item_health" "origin" "-896 -16 512" "spawnflags" "2048" } { "targetname" "t89" "classname" "item_health" "origin" "-1136 -2088 368" "spawnflags" "2050" } { "targetname" "t96" "origin" "352 -32 672" "classname" "item_armor1" } { "classname" "trigger_multiple" "health" "1" "target" "t85" "model" "*48" } { "wait" "-1" "classname" "func_door" "angle" "180" "lip" "-16" "targetname" "t26" "sounds" "0" "model" "*49" } { "origin" "0 224 864" "classname" "light" } { "light" "200" "origin" "0 376 864" "classname" "light" } { "light" "150" "origin" "232 128 816" "classname" "light" } { "classname" "light" "origin" "-232 128 816" "light" "150" } { "light" "200" "origin" "-160 512 872" "classname" "light" } { "light" "200" "origin" "64 -352 856" "classname" "light" } { "light" "200" "origin" "352 128 872" "classname" "light" } { "light" "200" "origin" "-32 896 872" "classname" "light" } { "light" "200" "origin" "-352 640 872" "classname" "light" } { "classname" "light" "origin" "-352 320 872" "light" "200" } { "light" "200" "origin" "-992 368 512" "classname" "light" } { "classname" "light" "origin" "-512 -352 512" "light" "200" } { "light" "200" "origin" "-848 -696 448" "classname" "light" } { "light" "200" "origin" "-704 -2752 416" "classname" "light" } { "classname" "light" "origin" "-704 -2616 416" "light" "200" } { "light" "180" "origin" "8 -240 808" "classname" "light" } { "light" "200" "origin" "-88 -312 864" "classname" "light" } { "target" "t86" "classname" "trigger_once" "model" "*50" } { "targetname" "t86" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*51" } { "light" "200" "origin" "-688 -192 832" "classname" "light" } { "classname" "light" "origin" "-848 32 832" "light" "200" } { "light" "200" "origin" "-624 192 832" "classname" "light" } { "classname" "light" "origin" "-856 -616 552" "light" "150" "style" "2" } { "classname" "light" "origin" "56 -2456 872" "light" "150" } { "classname" "light" "origin" "376 -376 800" "light" "150" } { "classname" "light" "origin" "128 896 872" "light" "150" } { "spawnflags" "768" "angle" "225" "origin" "-576 -640 376" "classname" "monster_hell_knight" } { "origin" "48 -304 792" "classname" "item_artifact_invisibility" } { "origin" "64 -800 376" "classname" "item_artifact_super_damage" } { "classname" "item_health" "origin" "-16 80 768" "spawnflags" "2050" } { "killtarget" "t90" "classname" "trigger_once" "target" "t90" "model" "*52" } { "classname" "trigger_once" "killtarget" "t89" "target" "t89" "model" "*53" } { "spawnflags" "1792" "origin" "-1088 -2072 368" "classname" "weapon_lightning" } { "origin" "-128 -80 880" "classname" "item_armor1" } { "spawnflags" "1792" "origin" "-240 -1904 624" "classname" "weapon_supershotgun" } { "spawnflags" "1793" "origin" "-144 -2296 616" "classname" "item_cells" } { "classname" "monster_shalrath" "origin" "-920 0 792" "angle" "0" "spawnflags" "256" } { "classname" "monster_shalrath" "origin" "176 -1832 376" "angle" "90" "spawnflags" "768" } { "classname" "monster_shalrath" "origin" "240 -2896 392" "angle" "45" "targetname" "t83" } { "classname" "monster_knight" "origin" "-384 -1104 376" "angle" "90" "spawnflags" "768" } { "spawnflags" "768" "angle" "90" "origin" "-320 -1104 376" "classname" "monster_knight" } { "classname" "monster_hell_knight" "origin" "-656 -2960 392" "angle" "0" "spawnflags" "256" } { "mangle" "35 50 0" "origin" "-552 -2176 608" "classname" "info_intermission" } { "classname" "weapon_supershotgun" "origin" "224 224 768" } { "spawnflags" "1792" "classname" "weapon_grenadelauncher" "origin" "-128 -32 880" } { "classname" "trigger_secret" "model" "*54" } { "killtarget" "t96" "target" "t96" "classname" "trigger_secret" "model" "*55" } { "killtarget" "t94" "target" "t94" "classname" "trigger_secret" "model" "*56" } { "classname" "monster_ogre" "origin" "-736 -272 792" "angle" "45" } { "classname" "monster_ogre" "origin" "-736 272 792" "angle" "315" } { "classname" "item_armor2" "origin" "-1104 -2280 368" "targetname" "t90" } { "classname" "item_health" "origin" "-720 176 768" "spawnflags" "2" } { "classname" "item_health" "origin" "-512 352 352" "spawnflags" "1" } { "classname" "item_health" "origin" "-1024 -352 352" "spawnflags" "1" } { "classname" "monster_shalrath" "origin" "-112 -816 376" "angle" "270" "spawnflags" "256" } { "origin" "-448 -1528 376" "classname" "path_corner" "targetname" "t92" "target" "t91" } { "classname" "path_corner" "origin" "-448 -1888 392" "targetname" "t91" "target" "t92" } { "classname" "monster_hell_knight" "origin" "288 -2368 536" "angle" "180" } { "classname" "weapon_rocketlauncher" "origin" "-240 -2416 816" "spawnflags" "1792" } { "classname" "monster_hell_knight" "origin" "-528 -1584 376" "target" "t49" } { "classname" "monster_hell_knight" "origin" "-448 -1832 376" "target" "t91" "spawnflags" "256" } { "classname" "monster_knight" "origin" "-480 -2624 392" "angle" "180" "spawnflags" "256" } { "angle" "180" "origin" "-432 -2592 392" "classname" "monster_knight" "spawnflags" "768" } { "classname" "weapon_supernailgun" "origin" "-264 -2768 512" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "472 -2656 368" "spawnflags" "1792" } { "classname" "weapon_lightning" "origin" "-608 192 768" "spawnflags" "1792" } { "classname" "item_cells" "origin" "-944 -120 768" "spawnflags" "1793" } { "classname" "trigger_secret" "model" "*57" } { "classname" "trigger_changelevel" "map" "e4m3" "model" "*58" } { "classname" "light" "origin" "-1632 -56 216" "light" "250" } { "origin" "-1376 -56 216" "classname" "light" "light" "250" } { "classname" "item_cells" "origin" "-368 -1248 352" "spawnflags" "1793" } { "classname" "weapon_nailgun" "origin" "-656 -208 512" } { "classname" "weapon_grenadelauncher" "origin" "-128 -2096 624" "spawnflags" "1792" } { "spawnflags" "1793" "origin" "-912 -712 352" "classname" "item_rockets" } { "classname" "info_intermission" "origin" "-64 224 800" "mangle" "-45 300 0" } { "classname" "info_intermission" "origin" "288 -1936 752" "mangle" "0 215 0" } { "classname" "info_intermission" "origin" "192 -2960 640" "mangle" "20 25 0" } { "spawnflags" "2048" "classname" "trigger_multiple" "targetname" "t94" "message" "Are you sure you want to exit? \n You left something important behind" "model" "*59" } { "origin" "-512 -784 352" "classname" "item_health" } { "origin" "-848 -432 536" "classname" "item_artifact_invulnerability" } { "spawnflags" "1" "origin" "-616 -2512 368" "classname" "item_spikes" } { "origin" "-480 -2336 392" "classname" "item_artifact_super_damage" } { "spawnflags" "1" "origin" "208 -2384 512" "classname" "item_shells" } { "spawnflags" "1793" "origin" "408 -2608 368" "classname" "item_cells" } { "classname" "item_shells" "origin" "-64 -352 768" } { "classname" "item_health" "origin" "272 -2232 416" "spawnflags" "1" } { "classname" "light" "origin" "-1080 -2264 416" "light" "200" } { "classname" "monster_ogre" "origin" "-864 -2336 392" "angle" "90" } { "angle" "135" "classname" "monster_ogre" "origin" "-368 -2152 392" } { "classname" "weapon_supershotgun" "origin" "-656 208 512" } { "classname" "item_spikes" "origin" "-144 80 880" "spawnflags" "1" } { "spawnflags" "768" "origin" "-624 -2832 392" "classname" "monster_hell_knight" } { "origin" "-864 384 512" "classname" "item_shells" } { "classname" "func_door" "angle" "180" "wait" "-1" "sounds" "3" "model" "*60" } { "sounds" "3" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*61" } { "classname" "light" "origin" "-1504 104 200" "light" "200" } { "angle" "270" "origin" "0 384 1208" "classname" "info_player_start" } { "angle" "270" "origin" "-32 328 1192" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "32 328 1192" "angle" "270" } { "angle" "270" "origin" "0 272 1192" "classname" "info_player_coop" } { "classname" "func_wall" "spawnflags" "1792" "model" "*62" } { "classname" "func_wall" "spawnflags" "1792" "model" "*63" } { "light" "200" "origin" "-56 344 1192" "classname" "light" } { "classname" "light" "origin" "56 344 1192" "light" "200" } { "light" "200" "origin" "56 424 1192" "classname" "light" } { "classname" "light" "origin" "-56 424 1192" "light" "200" } { "light" "200" "origin" "-72 72 1192" "classname" "light" } { "light" "200" "classname" "light" "origin" "72 72 1192" } { "light" "200" "origin" "72 -72 1192" "classname" "light" } { "light" "200" "classname" "light" "origin" "-72 -72 1192" } { "light" "200" "origin" "-40 184 1272" "classname" "light" } { "classname" "light" "origin" "128 352 1272" "light" "200" } { "classname" "trigger_once" "target" "t94" "killtarget" "t94" "model" "*64" } { "light" "150" "origin" "376 376 800" "classname" "light" } { "classname" "light" "origin" "136 632 800" "light" "150" } { "light" "150" "origin" "-376 904 800" "classname" "light" } { "classname" "light" "origin" "-376 -376 800" "light" "150" } { "origin" "-462 -2 568" "classname" "light_flame_large_yellow" } { "origin" "-1062 -434 652" "classname" "light_flame_large_yellow" } { "origin" "-1062 -2 652" "classname" "light_flame_large_yellow" } { "origin" "-770 434 652" "classname" "light_flame_large_yellow" } { "light" "150" "origin" "-580 -856 504" "classname" "light" } { "origin" "-286 -514 508" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-286 -834 508" } { "origin" "-420 -1154 508" "classname" "light_flame_large_yellow" } { "origin" "-34 -782 476" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-550 -1500 444" } { "light" "150" "origin" "-520 -1528 384" "classname" "light" } { "origin" "292 -1500 444" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "264 -1528 384" "light" "150" } { "light" "200" "origin" "-32 -1600 456" "classname" "light" } { "origin" "94 -1894 612" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "306 -2082 612" } { "origin" "-222 -1994 732" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-218 -2130 604" } { "origin" "-562 -2022 480" "classname" "light_flame_large_yellow" } { "origin" "-620 -1884 460" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "-648 -1912 400" "light" "150" } { "classname" "light_flame_large_yellow" "origin" "-804 -2390 460" } { "light" "150" "origin" "-832 -2360 400" "classname" "light" } { "classname" "light_flame_large_yellow" "origin" "-428 -2390 460" } { "light" "150" "origin" "-456 -2360 400" "classname" "light" } { "origin" "-750 -2914 524" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-418 -2998 524" } { "origin" "-62 -2998 612" "classname" "light_flame_large_yellow" } { "origin" "-370 -2446 900" "classname" "light_flame_large_yellow" } { "origin" "286 -2998 612" "classname" "light_flame_large_yellow" } { "origin" "154 -2262 524" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "154 -2478 524" } { "origin" "542 -2262 588" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "882 -2402 588" } { "origin" "542 -2478 588" "classname" "light_flame_large_yellow" } { "origin" "558 -2578 380" "classname" "light_flame_large_yellow" } { "spawnflags" "3584" "origin" "-764 0 376" "classname" "item_artifact_invulnerability" } { "classname" "light_flame_large_yellow" "origin" "-514 -2442 524" } { "origin" "-848 0 792" "classname" "item_key1" } { "targetname" "t97" "origin" "-1208 -2176 392" "classname" "item_key1" } { "killtarget" "t97" "target" "t97" "classname" "trigger_once" "model" "*65" } { "angle" "-2" "spawnflags" "2064" "classname" "func_door" "model" "*66" } { "classname" "light" "origin" "-640 -2472 424" "light" "150" } { "classname" "func_door_secret" "angle" "270" "spawnflags" "3" "model" "*67" } { "classname" "item_health" "origin" "264 -2296 624" } { "classname" "item_health" "origin" "320 -2288 624" "spawnflags" "1" } { "classname" "trigger_secret" "model" "*68" } { "origin" "-574 -6 784" "classname" "ambient_drip" } { "origin" "-638 130 512" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-638 -134 512" } { "origin" "-790 2 512" "classname" "ambient_drip" } { "light" "150" "origin" "-680 -2240 432" "classname" "light" } // ================================ // stas-sc begin extra BSP entity list for e4m2 // ================================ { "classname" "item_shells" "origin" "-64 -2334 512" "spawnflags" "1" } { "classname" "weapon_supernailgun" "origin" "-64 -2392 512" } { "classname" "item_shells" "origin" "-64 -2450 512" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-180 -2334 512" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "-180 -2392 512" } { "classname" "item_spikes" "origin" "-180 -2450 512" "spawnflags" "1" } { "classname" "item_shells" "origin" "55 33 768" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-61 149 768" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-61 33 768" "spawnflags" "1" } { "classname" "item_health" "origin" "-3 149 768" } { "classname" "item_flag_team2" "origin" "-128 -2467 512" } { "classname" "item_health" "origin" "-122 -2334 512" } { "classname" "item_armor2" "origin" "-122 -2392 512" } { "classname" "item_health" "origin" "-3 33 768" } { "classname" "item_flag_team1" "origin" "8 -109 768" } { "classname" "item_health" "origin" "-122 -2450 512" } { "classname" "info_player_team1" "origin" "68 -169 792" } { "classname" "info_player_team1" "origin" "68 -109 792" } { "classname" "info_player_team1" "origin" "68 -49 792" } { "classname" "info_player_team1" "origin" "8 -169 792" } { "classname" "info_player_team1" "origin" "8 -109 792" } { "classname" "info_player_team1" "origin" "8 -49 792" } { "classname" "info_player_team1" "origin" "-52 -169 792" } { "classname" "info_player_team1" "origin" "-52 -109 792" } { "classname" "info_player_team1" "origin" "-52 -49 792" } { "classname" "info_player_team2" "origin" "-68 -2527 536" } { "classname" "info_player_team2" "origin" "-68 -2467 536" } { "classname" "info_player_team2" "origin" "-68 -2407 536" } { "classname" "info_player_team2" "origin" "-128 -2527 536" } { "classname" "info_player_team2" "origin" "-128 -2467 536" } { "classname" "info_player_team2" "origin" "-128 -2407 536" } { "classname" "info_player_team2" "origin" "-188 -2527 536" } { "classname" "info_player_team2" "origin" "-188 -2467 536" } { "classname" "info_player_team2" "origin" "-188 -2407 536" } // ================================ // stas-sc end extra BSP entity list for e4m2 // ================================ QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m3.ent000066400000000000000000001232601475442401000252000ustar00rootroot00000000000000{ "message" "The Elder God Shrine" "classname" "worldspawn" "wad" "gfx/medieval.wad" "worldtype" "0" "sounds" "9" } { "classname" "info_player_start" "origin" "192 256 24" "angle" "180" } { "classname" "light" "origin" "608 -576 224" "angle" "0" "light" "300" } { "classname" "light" "origin" "1256 48 224" } { "classname" "light" "origin" "1728 64 -32" } { "classname" "light" "origin" "736 -320 224" "angle" "0" "light" "300" } { "classname" "light" "origin" "472 -320 224" "angle" "0" "light" "300" } { "classname" "light" "origin" "-32 552 192" "light" "200" } { "classname" "light" "origin" "-32 -40 192" "light" "200" } { "classname" "light" "origin" "864 1144 240" "angle" "0" } { "classname" "light" "origin" "672 1144 240" "angle" "0" } { "classname" "light" "light" "150" "origin" "1048 1056 200" } { "classname" "light" "light" "200" "origin" "576 960 -16" } { "classname" "light" "light" "200" "origin" "960 960 -16" } { "classname" "light" "light" "200" "origin" "768 800 -16" } { "classname" "info_player_deathmatch" "origin" "400 -752 24" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "-272 -24 152" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1056 1152 152" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "1104 176 8" "angle" "315" } { "classname" "info_teleport_destination" "targetname" "balcony" "origin" "768 544 8" "angle" "90" } { "model" "*1" "sounds" "2" "classname" "func_plat" } { "classname" "path_corner" "origin" "376 -280 24" "targetname" "t5" "target" "t6" } { "classname" "path_corner" "origin" "376 -704 24" "targetname" "t6" "target" "t5" } { "classname" "path_corner" "origin" "840 -200 24" "targetname" "t4" "target" "t3" } { "classname" "path_corner" "origin" "840 -704 24" "targetname" "t3" "target" "t4" } { "angle" "90" "classname" "monster_ogre" "origin" "606 -754 152" } { "classname" "item_health" "origin" "808 -528 0" } { "classname" "item_health" "origin" "376 -528 0" } { "spawnflags" "1" "classname" "item_shells" "origin" "376 -336 0" } { "classname" "item_health" "origin" "472 1136 128" } { "spawnflags" "1" "classname" "item_spikes" "origin" "896 800 -96" } { "model" "*2" "spawnflags" "2048" "sounds" "3" "classname" "func_door" "angle" "90" "wait" "-1" } { "model" "*3" "spawnflags" "2048" "sounds" "3" "classname" "func_door" "angle" "270" "targetname" "t147" "wait" "-1" "message" "This door is opened elsewhere." } { "model" "*4" "spawnflags" "2048" "wait" "-1" "targetname" "t93" "classname" "func_door" "angle" "90" } { "model" "*5" "spawnflags" "2048" "sounds" "3" "wait" "-1" "classname" "func_door" "angle" "270" } { "model" "*6" "spawnflags" "2048" "sounds" "3" "classname" "func_door" "angle" "180" "wait" "6" } { "model" "*7" "spawnflags" "2048" "sounds" "3" "wait" "-1" "targetname" "t138" "classname" "func_door" "angle" "0" "message" "This door is opened elsewhere." } { "model" "*8" "spawnflags" "2048" "sounds" "3" "wait" "-1" "classname" "func_door" "angle" "180" } { "angle" "225" "origin" "-208 320 40" "classname" "monster_demon1" } { "spawnflags" "1" "origin" "80 -80 64" "classname" "item_health" } { "targetname" "t215" "origin" "1776 64 24" "classname" "monster_wizard" "angle" "0" } { "targetname" "t215" "origin" "1776 -64 24" "classname" "monster_wizard" "angle" "0" } { "origin" "1184 224 -144" "classname" "item_health" } { "origin" "496 -272 0" "classname" "item_health" "spawnflags" "1" } { "origin" "400 -752 128" "classname" "item_shells" } { "targetname" "t85" "angle" "180" "origin" "768 256 136" "classname" "info_teleport_destination" } { "model" "*9" "spawnflags" "2" "target" "t85" "classname" "trigger_teleport" } { "target" "t5" "origin" "376 -368 24" "classname" "monster_knight" } { "target" "t3" "origin" "840 -632 24" "classname" "monster_knight" } { "classname" "light" "origin" "-488 256 160" "light" "400" } { "origin" "224 552 192" "classname" "light" "light" "200" } { "classname" "light" "origin" "224 -40 192" "light" "200" } { "spawnflags" "768" "classname" "monster_demon1" "origin" "-208 192 40" "angle" "135" } { "classname" "item_health" "origin" "80 560 64" "spawnflags" "1" } { "spawnflags" "1" "origin" "752 112 16" "classname" "item_shells" } { "light" "200" "origin" "296 288 64" "classname" "light" } { "classname" "light" "origin" "296 256 256" "light" "150" } { "light" "200" "origin" "-32 176 224" "classname" "light" } { "light" "200" "classname" "light" "origin" "-32 336 224" } { "light" "200" "origin" "192 336 192" "classname" "light" } { "light" "200" "classname" "light" "origin" "192 176 192" } { "classname" "light" "origin" "-88 256 96" "light" "150" } { "classname" "light" "origin" "-432 344 256" "light" "150" } { "light" "150" "origin" "-432 168 256" "classname" "light" } { "classname" "light" "origin" "-288 168 256" "light" "150" } { "light" "150" "origin" "-288 344 256" "classname" "light" } { "light" "150" "origin" "-416 344 80" "classname" "light" } { "classname" "light" "origin" "-416 168 80" "light" "150" } { "model" "*10" "classname" "func_illusionary" } { "model" "*11" "classname" "func_illusionary" } { "origin" "1728 -64 -32" "classname" "light" } { "classname" "light" "origin" "2016 0 -104" } { "model" "*12" "sounds" "1" "classname" "func_button" "angle" "270" "wait" "-1" "target" "t147" "lip" "4" } { "model" "*13" "sounds" "3" "targetname" "t177" "classname" "func_door" "angle" "270" "lip" "-8" "speed" "75" } { "classname" "light" "origin" "640 -1344 88" } { "classname" "light" "origin" "1024 -1344 184" } { "origin" "832 -1344 88" "classname" "light" } { "model" "*14" "sounds" "1" "targetname" "t198" "wait" "-1" "angle" "-1" "classname" "func_door" } { "model" "*15" "target" "t198" "classname" "trigger_once" } { "origin" "1256 -48 224" "classname" "light" } { "classname" "light" "origin" "-1272 256 192" "light" "400" } { "classname" "light" "origin" "-1080 408 192" } { "origin" "-1080 112 192" "classname" "light" } { "classname" "light" "origin" "568 128 64" "light" "200" } { "origin" "640 200 64" "classname" "light" "light" "200" } { "classname" "light" "origin" "712 128 64" "light" "200" } { "origin" "640 56 64" "classname" "light" "light" "200" } { "light" "200" "origin" "1856 0 -160" "classname" "light" } { "origin" "2440 440 32" "classname" "light" } { "classname" "light" "origin" "2152 -40 32" } { "origin" "2264 -352 32" "classname" "light" } { "classname" "light" "origin" "2696 -200 32" } { "light" "200" "origin" "2008 744 32" "classname" "light" } { "origin" "514 -1254 204" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "514 -1430 212" } { "classname" "light" "origin" "-1376 1696 184" } { "origin" "-1536 1504 184" "classname" "light" } { "classname" "light" "origin" "-1696 1696 184" } { "origin" "-1536 1888 184" "classname" "light" } { "targetname" "t173" "classname" "light" "origin" "-1312 -808 192" "light" "250" "style" "32" } { "targetname" "t173" "light" "250" "origin" "-928 -808 192" "classname" "light" "style" "32" } { "targetname" "t173" "classname" "light" "origin" "-544 -808 192" "light" "250" "style" "32" } { "origin" "96 -1416 192" "classname" "light" } { "classname" "light" "origin" "1184 -1640 192" } { "light" "250" "origin" "1440 -440 192" "classname" "light" } { "classname" "light" "origin" "1856 -584 192" "light" "250" } { "light" "250" "origin" "1568 984 192" "classname" "light" } { "classname" "light" "origin" "32 984 192" "light" "250" } { "light" "250" "origin" "-608 984 192" "classname" "light" } { "classname" "light" "origin" "-256 1128 192" "light" "250" } { "light" "250" "origin" "288 1128 192" "classname" "light" } { "classname" "light" "origin" "1248 1128 192" "light" "250" } { "light" "250" "origin" "1664 680 192" "classname" "light" } { "classname" "light" "origin" "1856 1128 192" "light" "250" } { "light" "250" "origin" "1928 608 192" "classname" "light" } { "classname" "light" "origin" "1928 352 192" "light" "250" } { "light" "250" "origin" "1384 -1344 192" "classname" "light" } { "classname" "light" "origin" "1184 -1048 192" } { "light" "250" "origin" "-224 -664 192" "classname" "light" } { "classname" "light" "origin" "168 -736 192" } { "targetname" "t173" "light" "250" "origin" "-472 -544 192" "classname" "light" "style" "32" } { "classname" "light" "origin" "-544 -280 192" "light" "250" } { "targetname" "t173" "classname" "light" "origin" "-1384 -544 192" "light" "250" "style" "32" } { "light" "250" "origin" "-1184 -280 192" "classname" "light" } { "classname" "light" "origin" "-856 256 192" "light" "400" } { "light" "250" "origin" "-1000 800 192" "classname" "light" } { "classname" "light" "origin" "1928 0 264" "light" "350" } { "angle" "180" "origin" "1088 384 32" "classname" "monster_demon1" "targetname" "t147" "target" "t121" "spawnflags" "257" } { "classname" "monster_demon1" "origin" "1088 472 32" "angle" "180" "targetname" "t97" "target" "t122" "spawnflags" "257" } { "angle" "180" "origin" "1088 560 32" "classname" "monster_demon1" "targetname" "t98" "target" "t123" "spawnflags" "257" } { "classname" "monster_demon1" "origin" "1088 648 32" "angle" "180" "targetname" "t99" "spawnflags" "257" "target" "t216" } { "classname" "light" "origin" "1152 -192 -96" "light" "200" } { "light" "200" "origin" "1152 192 -96" "classname" "light" } { "light" "150" "origin" "-256 576 176" "classname" "light" } { "classname" "light" "origin" "-256 -64 176" "light" "150" } { "light" "150" "origin" "-256 -152 176" "classname" "light" } { "classname" "light" "origin" "-256 672 176" "light" "150" } { "light" "250" "origin" "1184 -584 192" "classname" "light" } { "light" "150" "origin" "768 400 64" "classname" "light" } { "classname" "light" "origin" "904 0 64" "light" "150" } { "light" "200" "origin" "512 -136 64" "classname" "light" "style" "5" } { "classname" "light" "origin" "376 256 64" "light" "150" } { "light" "200" "origin" "752 -544 56" "classname" "light" } { "classname" "light" "origin" "744 -216 56" "light" "200" } { "light" "200" "origin" "472 -544 56" "classname" "light" } { "spawnflags" "768" "classname" "monster_ogre" "origin" "382 -450 152" "angle" "45" } { "classname" "monster_ogre" "origin" "830 -242 152" "spawnflags" "768" "angle" "180" } { "target" "t138" "angle" "270" "origin" "672 1236 280" "classname" "monster_wizard" "message" "The door has opened." } { "spawnflags" "256" "targetname" "t138" "target" "t128" "classname" "monster_wizard" "origin" "872 1236 280" "angle" "45" } { "spawnflags" "769" "classname" "monster_wizard" "origin" "664 1064 48" "angle" "270" "targetname" "t232" } { "spawnflags" "769" "classname" "monster_wizard" "origin" "872 1064 48" "angle" "270" "targetname" "t232" } { "model" "*16" "spawnflags" "2" "target" "t108" "classname" "trigger_teleport" } { "model" "*17" "spawnflags" "2" "target" "t109" "classname" "trigger_teleport" } { "targetname" "t108" "angle" "270" "origin" "672 1264 264" "classname" "info_teleport_destination" } { "targetname" "t109" "classname" "info_teleport_destination" "origin" "864 1264 264" "angle" "270" } { "origin" "512 880 -96" "classname" "item_rockets" "spawnflags" "1" } { "origin" "608 800 -96" "classname" "item_health" } { "model" "*18" "target" "t97" "targetname" "t121" "classname" "trigger_once" "delay" "30" } { "model" "*19" "target" "t98" "targetname" "t122" "delay" "30" "classname" "trigger_once" } { "model" "*20" "target" "t99" "targetname" "t123" "classname" "trigger_once" "delay" "30" } { "model" "*21" "target" "t224" "targetname" "t128" "delay" "10" "classname" "trigger_once" } { "light" "200" "origin" "1016 0 56" "classname" "light" } { "spawnflags" "1" "origin" "1016 -16 0" "classname" "item_spikes" } { "angle" "135" "origin" "2672 -256 -96" "classname" "monster_zombie" } { "angle" "135" "classname" "monster_zombie" "origin" "2672 -352 -96" } { "angle" "135" "origin" "2800 -256 -96" "classname" "monster_zombie" } { "angle" "135" "classname" "monster_zombie" "origin" "2800 -352 -96" } { "model" "*22" "classname" "trigger_once" "targetname" "t156" "delay" "1" "target" "t157" } { "angle" "90" "origin" "2568 168 -96" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "2056 624 -200" "angle" "315" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "2056 520 -200" "angle" "0" } { "spawnflags" "768" "angle" "225" "origin" "2544 400 -104" "classname" "monster_zombie" } { "light" "150" "origin" "2024 488 -64" "classname" "light" } { "classname" "light" "origin" "2248 728 -64" "light" "150" } { "origin" "2880 448 -64" "classname" "light" } { "targetname" "t145" "classname" "monster_zombie" "origin" "2768 624 -96" "angle" "270" } { "targetname" "t145" "classname" "monster_zombie" "origin" "2856 624 -96" "angle" "270" } { "targetname" "t145" "classname" "monster_zombie" "origin" "2856 736 -96" "angle" "270" "spawnflags" "256" } { "targetname" "t145" "classname" "monster_zombie" "origin" "2768 736 -96" "angle" "270" "spawnflags" "256" } { "model" "*23" "target" "t145" "classname" "trigger_once" } { "model" "*24" "classname" "trigger_teleport" "target" "balcony" } { "style" "2" "light" "200" "origin" "2792 776 -64" "classname" "light" } { "classname" "light" "origin" "608 -792 48" "style" "5" } { "targetname" "t147" "spawnflags" "512" "classname" "monster_knight" "origin" "536 -1000 24" "angle" "90" } { "targetname" "t147" "origin" "584 -1000 24" "classname" "monster_knight" "angle" "90" } { "targetname" "t147" "classname" "monster_knight" "origin" "632 -1000 24" "angle" "90" } { "targetname" "t147" "spawnflags" "512" "angle" "90" "origin" "680 -1000 24" "classname" "monster_knight" } { "model" "*25" "spawnflags" "2" "classname" "trigger_teleport" "target" "t148" } { "model" "*26" "spawnflags" "2" "classname" "trigger_teleport" "target" "t149" } { "model" "*27" "spawnflags" "2" "classname" "trigger_teleport" "target" "t150" } { "model" "*28" "spawnflags" "2" "classname" "trigger_teleport" "target" "t151" } { "classname" "info_teleport_destination" "origin" "392 -680 8" "angle" "315" "targetname" "t148" } { "classname" "info_teleport_destination" "origin" "824 -680 8" "angle" "225" "targetname" "t151" } { "classname" "info_teleport_destination" "origin" "496 -480 8" "angle" "225" "targetname" "t149" } { "angle" "315" "origin" "720 -480 8" "classname" "info_teleport_destination" "targetname" "t150" } { "classname" "light" "origin" "2392 -144 -56" "light" "200" } { "classname" "light" "origin" "960 -320 190" } { "classname" "light" "origin" "256 -512 190" } { "spawnflags" "1" "classname" "item_spikes" "origin" "624 -16 0" } { "classname" "item_spikes" "origin" "808 -336 0" "spawnflags" "1" } { "spawnflags" "1" "classname" "item_spikes" "origin" "784 -752 128" } { "classname" "item_armor1" "origin" "672 -800 128" } { "classname" "item_spikes" "origin" "592 -688 0" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "1152 -128 -120" "angle" "0" } { "model" "*29" "classname" "func_illusionary" } { "angle" "270" "origin" "2272 -328 -224" "classname" "monster_zombie" } { "model" "*30" "lip" "0" "targetname" "t156" "wait" "-1" "speed" "1000" "angle" "180" "classname" "func_door" } { "model" "*31" "speed" "300" "lip" "-116" "wait" "-1" "angle" "-1" "targetname" "t157" "classname" "func_door" } { "light" "200" "origin" "2288 -288 -240" "classname" "light" } { "classname" "light" "origin" "2256 -344 -240" "light" "200" } { "light" "200" "origin" "2272 -312 -216" "classname" "light" } { "model" "*32" "classname" "func_illusionary" } { "origin" "2416 -328 -224" "classname" "monster_zombie" "angle" "225" } { "model" "*33" "speed" "300" "targetname" "t157" "classname" "func_door" "angle" "-1" "wait" "-1" "lip" "-116" } { "classname" "light" "origin" "2432 -288 -240" "light" "200" } { "light" "200" "origin" "2400 -344 -240" "classname" "light" } { "classname" "light" "origin" "2416 -312 -216" "light" "200" } { "light" "200" "origin" "2360 -576 -56" "classname" "light" } { "model" "*34" "classname" "func_illusionary" } { "angle" "90" "classname" "monster_zombie" "origin" "2416 -584 -216" } { "model" "*35" "lip" "0" "targetname" "t156" "wait" "-1" "speed" "1000" "angle" "270" "classname" "func_door" } { "model" "*36" "speed" "300" "targetname" "t157" "lip" "-116" "wait" "-1" "angle" "-1" "classname" "func_door" } { "light" "200" "origin" "2432 -544 -240" "classname" "light" } { "classname" "light" "origin" "2400 -600 -240" "light" "200" } { "light" "200" "origin" "2416 -568 -216" "classname" "light" } { "model" "*37" "classname" "func_illusionary" } { "classname" "monster_zombie" "origin" "2320 -584 -216" "angle" "90" } { "model" "*38" "lip" "0" "targetname" "t156" "classname" "func_door" "angle" "270" "speed" "1000" "wait" "-1" } { "model" "*39" "speed" "300" "targetname" "t157" "classname" "func_door" "angle" "-1" "wait" "-1" "lip" "-116" } { "classname" "light" "origin" "2336 -544 -240" "light" "200" } { "light" "200" "origin" "2304 -600 -240" "classname" "light" } { "classname" "light" "origin" "2320 -568 -216" "light" "200" } { "model" "*40" "classname" "func_illusionary" } { "angle" "315" "classname" "monster_zombie" "origin" "2152 -424 -200" } { "model" "*41" "lip" "0" "targetname" "t156" "wait" "-1" "speed" "1000" "angle" "270" "classname" "func_door" } { "model" "*42" "targetname" "t157" "lip" "-116" "wait" "-1" "angle" "-1" "classname" "func_door" } { "light" "200" "origin" "2192 -440 -240" "classname" "light" } { "classname" "light" "origin" "2136 -408 -240" "light" "200" } { "light" "200" "origin" "2168 -424 -216" "classname" "light" } { "model" "*43" "classname" "func_illusionary" } { "origin" "2224 -584 -224" "classname" "monster_zombie" "angle" "45" } { "model" "*44" "lip" "0" "targetname" "t156" "classname" "func_door" "angle" "270" "speed" "1000" "wait" "-1" } { "model" "*45" "speed" "300" "targetname" "t157" "classname" "func_door" "angle" "-1" "wait" "-1" "lip" "-116" } { "classname" "light" "origin" "2144 -544 -240" "light" "200" } { "light" "200" "origin" "2112 -600 -240" "classname" "light" } { "classname" "light" "origin" "2128 -568 -216" "light" "200" } { "classname" "light" "origin" "2224 -512 -8" } { "origin" "2128 -584 -152" "classname" "weapon_grenadelauncher" } { "model" "*46" "targetname" "t156" "lip" "0" "classname" "func_door" "angle" "0" "speed" "1000" "wait" "-1" } { "light" "150" "origin" "2600 -8 -56" "classname" "light" } { "angle" "315" "origin" "2128 696 -200" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "2200 696 -200" "angle" "315" "spawnflags" "256" } { "model" "*47" "targetname" "t158" "lip" "-96" "angle" "-1" "wait" "-1" "classname" "func_door" } { "classname" "monster_zombie" "origin" "2344 696 -200" "angle" "315" } { "model" "*48" "classname" "func_illusionary" } { "model" "*49" "target" "t158" "classname" "trigger_once" } { "spawnflags" "2" "origin" "2200 544 -80" "classname" "item_health" } { "origin" "2856 392 -128" "classname" "item_rockets" } { "origin" "2560 0 -120" "classname" "item_rockets" } { "model" "*50" "sounds" "2" "wait" "-1" "lip" "-8" "angle" "-2" "classname" "func_door" } { "model" "*51" "sounds" "2" "spawnflags" "2064" "wait" "-1" "classname" "func_door" "angle" "-2" "lip" "-8" } { "model" "*52" "spawnflags" "2048" "sounds" "2" "lip" "-8" "angle" "-2" "classname" "func_door" "wait" "-1" } { "model" "*53" "spawnflags" "2048" "sounds" "2" "wait" "-1" "classname" "func_door" "angle" "-2" "lip" "-8" } { "angle" "90" "origin" "-920 800 152" "classname" "monster_knight" "spawnflags" "768" } { "classname" "monster_knight" "origin" "-864 864 152" "angle" "90" "spawnflags" "256" } { "angle" "270" "origin" "-928 1312 152" "classname" "monster_knight" "spawnflags" "768" } { "classname" "monster_knight" "origin" "-992 1240 152" "angle" "270" } { "origin" "768 592 120" "classname" "light" } { "light" "200" "origin" "680 680 248" "classname" "light" } { "model" "*54" "spawnflags" "2048" "sounds" "2" "targetname" "t168" "wait" "-1" "classname" "func_door" "angle" "-2" "lip" "-8" } { "spawnflags" "1" "origin" "1040 144 -144" "classname" "item_spikes" } { "model" "*55" "target" "t156" "classname" "trigger_once" } { "angle" "90" "origin" "1792 -336 152" "classname" "monster_knight" "spawnflags" "256" } { "classname" "monster_knight" "origin" "1856 -288 152" "angle" "90" } { "spawnflags" "256" "angle" "90" "origin" "1920 -336 152" "classname" "monster_knight" } { "targetname" "t164" "angle" "90" "origin" "1792 416 152" "classname" "monster_knight" } { "targetname" "t164" "classname" "monster_knight" "origin" "1856 352 152" "angle" "90" "spawnflags" "256" } { "targetname" "t164" "angle" "90" "origin" "1920 416 152" "classname" "monster_knight" } { "model" "*56" "target" "t164" "classname" "trigger_once" } { "model" "*57" "sounds" "3" "dmg" "1000" "targetname" "t167" "classname" "func_door" "spawnflags" "36" "angle" "-2" "lip" "-120" } { "model" "*58" "sounds" "2" "height" "104" "classname" "func_plat" "wait" "9" "speed" "75" } { "model" "*59" "spawnflags" "2" "target" "t178" "classname" "trigger_teleport" } { "light" "500" "origin" "-1536 1696 216" "classname" "light" } { "model" "*60" "target" "t167" "angle" "90" "classname" "func_button" } { "model" "*61" "spawnflags" "2048" "sounds" "2" "targetname" "t169" "lip" "-8" "angle" "-2" "classname" "func_door" "wait" "-1" } { "model" "*62" "target" "t168" "classname" "trigger_once" } { "model" "*63" "target" "t169" "classname" "trigger_once" } { "sounds" "2" "origin" "1344 -1344 160" "classname" "item_key1" "spawnflags" "2048" } { "angle" "180" "origin" "-1280 1872 16" "classname" "monster_zombie" } { "angle" "180" "origin" "-1272 1536 16" "classname" "monster_zombie" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "-1344 1408 16" "angle" "135" "spawnflags" "256" } { "spawnflags" "768" "angle" "135" "origin" "-1304 1760 48" "classname" "monster_wizard" } { "model" "*64" "target" "t179" "classname" "func_button" "angle" "90" "wait" "3" } { "model" "*65" "targetname" "t179" "wait" "6" "angle" "0" "classname" "func_door" } { "targetname" "t171" "angle" "0" "origin" "-1120 96 152" "classname" "monster_ogre" } { "targetname" "t171" "classname" "monster_ogre" "origin" "-1120 416 152" "angle" "0" "spawnflags" "256" } { "model" "*66" "target" "t171" "classname" "trigger_once" } { "spawnflags" "1" "origin" "-560 -560 128" "classname" "item_spikes" } { "spawnflags" "1" "origin" "-944 -368 128" "classname" "item_spikes" } { "spawnflags" "2" "origin" "-272 48 128" "classname" "item_health" } { "origin" "-272 432 128" "classname" "item_rockets" } { "targetname" "t172" "angle" "45" "origin" "-1312 -672 152" "classname" "monster_demon1" } { "targetname" "t172" "angle" "135" "origin" "-544 -672 152" "classname" "monster_demon1" "spawnflags" "256" } { "model" "*67" "target" "t172" "classname" "trigger_once" } { "origin" "-928 -736 128" "classname" "item_armor2" } { "model" "*68" "spawnflags" "2048" "target" "t173" "classname" "trigger_once" "style" "32" } { "model" "*69" "spawnflags" "2048" "sounds" "1" "targetname" "t173" "wait" "-1" "speed" "300" "angle" "-1" "classname" "func_door" } { "classname" "monster_zombie" "origin" "-1120 -512 152" "angle" "315" "target" "t199" } { "angle" "225" "origin" "-704 -576 152" "classname" "monster_zombie" "target" "t199" } { "classname" "monster_zombie" "origin" "-752 -496 152" "angle" "225" "target" "t199" } { "angle" "315" "origin" "-992 -496 152" "classname" "monster_zombie" "target" "t199" } { "light" "150" "origin" "-1152 -512 192" "classname" "light" } { "classname" "light" "origin" "-704 -512 192" "light" "150" } { "light" "150" "origin" "-928 -512 192" "classname" "light" } { "angle" "90" "origin" "1120 -1616 152" "classname" "monster_knight" "spawnflags" "512" } { "angle" "270" "origin" "1120 -1072 152" "classname" "monster_knight" "spawnflags" "512" } { "origin" "1240 -1072 128" "classname" "item_health" } { "model" "*70" "wait" "10" "target" "t177" "classname" "trigger_multiple" } { "classname" "light" "origin" "448 -1344 88" } { "origin" "256 -1344 88" "classname" "light" } { "sounds" "2" "origin" "1856 -40 248" "classname" "item_key2" "spawnflags" "2048" } { "targetname" "t178" "angle" "90" "origin" "768 504 208" "classname" "info_teleport_destination" } { "origin" "768 672 200" "classname" "item_armorInv" } { "classname" "item_rockets" "origin" "816 496 200" } { "origin" "688 608 200" "classname" "item_health" } { "classname" "item_health" "origin" "816 608 200" } { "light" "150" "origin" "368 -512 232" "classname" "light" } { "light" "200" "origin" "680 -736 232" "classname" "light" } { "classname" "light" "origin" "2624 192 -56" "light" "150" } { "light" "150" "origin" "-1760 2008 168" "classname" "light" } { "light" "200" "origin" "-1824 1376 64" "classname" "light" } { "classname" "light" "origin" "-1248 1376 64" "light" "200" } { "light" "200" "origin" "-1248 2016 64" "classname" "light" } { "classname" "light" "origin" "-1824 2016 64" "light" "200" } { "light" "150" "origin" "-928 -304 192" "classname" "light" } { "origin" "-1072 -560 128" "classname" "item_health" } { "spawnflags" "1" "classname" "item_health" "origin" "-816 -560 128" } { "origin" "-224 240 16" "classname" "item_spikes" "spawnflags" "1" } { "model" "*71" "target" "t196" "classname" "trigger_once" } { "classname" "monster_wizard" "origin" "-624 736 56" "angle" "90" "target" "t201" "spawnflags" "257" } { "angle" "90" "origin" "-624 672 56" "classname" "monster_wizard" "target" "t203" "spawnflags" "1" } { "classname" "monster_wizard" "origin" "-624 608 56" "angle" "90" "target" "t205" "spawnflags" "257" } { "model" "*72" "spawnflags" "2" "target" "t181" "classname" "trigger_teleport" } { "model" "*73" "spawnflags" "2" "target" "t182" "classname" "trigger_teleport" } { "model" "*74" "spawnflags" "2" "target" "t183" "classname" "trigger_teleport" } { "model" "*75" "spawnflags" "2" "target" "t186" "classname" "trigger_teleport" } { "angle" "225" "origin" "2448 400 -104" "classname" "monster_zombie" "spawnflags" "256" } { "angle" "90" "origin" "2632 8 -96" "classname" "monster_zombie" "spawnflags" "256" } { "model" "*76" "target" "t187" "classname" "trigger_once" } { "targetname" "t181" "angle" "315" "origin" "2144 216 -120" "classname" "info_teleport_destination" } { "targetname" "t182" "classname" "info_teleport_destination" "origin" "2208 160 -120" "angle" "315" } { "targetname" "t183" "classname" "info_teleport_destination" "origin" "2184 32 -120" "angle" "315" } { "targetname" "t186" "angle" "315" "origin" "2296 64 -120" "classname" "info_teleport_destination" } { "targetname" "t187" "angle" "90" "origin" "-760 736 24" "classname" "monster_zombie" "spawnflags" "2" } { "targetname" "t187" "classname" "monster_zombie" "origin" "-760 664 24" "angle" "90" "spawnflags" "2" } { "targetname" "t187" "angle" "90" "origin" "-760 600 24" "classname" "monster_zombie" "spawnflags" "2" } { "targetname" "t187" "classname" "monster_zombie" "origin" "-760 536 24" "angle" "90" "spawnflags" "2" } { "model" "*77" "targetname" "t196" "spawnflags" "2" "target" "t191" "classname" "trigger_teleport" } { "model" "*78" "targetname" "t196" "spawnflags" "2" "target" "t192" "classname" "trigger_teleport" } { "model" "*79" "targetname" "t196" "spawnflags" "2" "target" "t193" "classname" "trigger_teleport" } { "targetname" "t189" "angle" "270" "origin" "2792 704 -112" "classname" "info_teleport_destination" } { "targetname" "t190" "origin" "-544 504 24" "classname" "monster_demon1" "spawnflags" "1" } { "model" "*80" "target" "t189" "classname" "trigger_teleport" "spawnflags" "258" } { "model" "*81" "target" "t190" "classname" "trigger_once" } { "targetname" "t192" "origin" "-992 664 168" "classname" "info_teleport_destination" } { "targetname" "t193" "classname" "info_teleport_destination" "origin" "-928 608 168" } { "targetname" "t191" "origin" "-928 736 168" "classname" "info_teleport_destination" } { "classname" "light" "origin" "-1248 1792 64" "light" "200" } { "light" "200" "origin" "-1248 1576 64" "classname" "light" } { "classname" "light" "origin" "-856 1408 192" "light" "250" } { "origin" "-1272 1408 80" "classname" "light" } { "light" "200" "origin" "1344 -128 -64" "classname" "light" } { "classname" "light" "origin" "1344 128 -64" "light" "200" } { "light" "200" "origin" "1568 192 -64" "classname" "light" } { "classname" "light" "origin" "1568 -192 -64" "light" "200" } { "model" "*82" "spawnflags" "1" "classname" "trigger_counter" "targetname" "t199" "count" "4" "target" "t173" "style" "32" } { "classname" "monster_demon1" "origin" "-1120 -576 152" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "1344 -1288 152" "angle" "180" "spawnflags" "256" } { "classname" "item_shells" "origin" "272 1040 128" "spawnflags" "1" } { "classname" "item_rockets" "origin" "816 656 0" } { "origin" "704 656 0" "classname" "item_shells" } { "model" "*83" "targetname" "t179" "target" "t167" "classname" "trigger_multiple" } { "classname" "item_health" "origin" "1232 -1648 128" } { "model" "*84" "classname" "func_door" "targetname" "t196" "angle" "-2" "wait" "-1" "lip" "0" } { "classname" "monster_ogre" "origin" "-544 616 24" "targetname" "t196" "spawnflags" "1" } { "origin" "-544 720 24" "classname" "monster_ogre" "targetname" "t196" "spawnflags" "257" } { "classname" "path_corner" "origin" "-992 736 200" "targetname" "t201" "target" "t202" } { "origin" "-992 1016 200" "classname" "path_corner" "targetname" "t202" "target" "t201" } { "classname" "path_corner" "origin" "-928 680 200" "targetname" "t203" "target" "t204" } { "origin" "-928 920 200" "classname" "path_corner" "targetname" "t204" "target" "t203" } { "classname" "path_corner" "origin" "-864 608 200" "targetname" "t205" "target" "t206" } { "origin" "-864 960 200" "classname" "path_corner" "targetname" "t206" "target" "t205" } { "classname" "info_teleport_destination" "origin" "-1216 352 136" "targetname" "t211" } { "origin" "-1216 128 136" "classname" "info_teleport_destination" "targetname" "t212" } { "model" "*85" "spawnflags" "2" "classname" "trigger_teleport" "target" "t211" } { "model" "*86" "spawnflags" "2" "classname" "trigger_teleport" "target" "t212" } { "classname" "monster_zombie" "origin" "-1312 1632 16" "angle" "135" } { "classname" "item_shells" "origin" "-1320 1944 -8" "spawnflags" "1" } { "classname" "light" "origin" "-928 1024 184" "light" "150" } { "spawnflags" "1" "origin" "1040 -176 -144" "classname" "item_shells" } { "classname" "weapon_grenadelauncher" "origin" "1184 -1344 128" } { "model" "*87" "classname" "func_button" "angle" "-2" "spawnflags" "1792" "target" "t177" "wait" "2" } { "classname" "item_rockets" "origin" "1168 -1072 128" "spawnflags" "1" } { "classname" "item_health" "origin" "992 880 -96" } { "origin" "624 240 0" "classname" "item_spikes" "spawnflags" "1" } { "classname" "item_health" "origin" "2336 -336 -128" "spawnflags" "1" } { "model" "*88" "classname" "func_illusionary" } { "model" "*89" "classname" "func_illusionary" } { "model" "*90" "classname" "func_illusionary" } { "model" "*91" "classname" "func_illusionary" } { "model" "*92" "classname" "trigger_changelevel" "map" "e4m4" } { "origin" "1184 -240 -144" "classname" "item_health" } { "spawnflags" "513" "angle" "0" "origin" "1152 -8 -120" "classname" "monster_ogre" } { "spawnflags" "257" "classname" "monster_ogre" "origin" "1152 128 -120" "angle" "0" } { "light" "200" "origin" "1008 -56 -96" "classname" "light" } { "classname" "light" "origin" "1368 608 192" "light" "250" } { "angle" "0" "origin" "1504 608 152" "classname" "monster_tarbaby" } { "angle" "180" "origin" "-352 -304 152" "classname" "monster_tarbaby" "spawnflags" "768" } { "angle" "270" "origin" "48 -464 152" "classname" "monster_tarbaby" } { "angle" "90" "origin" "48 -1392 152" "classname" "monster_tarbaby" "spawnflags" "256" } { "model" "*93" "target" "t215" "classname" "trigger_once" } { "angle" "90" "origin" "-256 800 152" "classname" "monster_tarbaby" "spawnflags" "256" } { "spawnflags" "2048" "origin" "512 128 24" "classname" "item_artifact_super_damage" } { "origin" "1008 1152 152" "classname" "item_artifact_super_damage" } { "spawnflags" "2050" "origin" "-456 240 64" "classname" "item_health" } { "spawnflags" "769" "angle" "180" "origin" "1184 648 32" "classname" "monster_demon1" "targetname" "t223" } { "classname" "monster_demon1" "origin" "1184 560 32" "angle" "180" "spawnflags" "769" "targetname" "t221" "target" "t222" } { "spawnflags" "769" "angle" "180" "origin" "1184 472 32" "classname" "monster_demon1" "targetname" "t219" "target" "t220" } { "classname" "monster_demon1" "origin" "1184 384 32" "angle" "180" "spawnflags" "769" "targetname" "t217" "target" "t218" } { "model" "*94" "delay" "30" "classname" "trigger_once" "targetname" "t216" "target" "t217" } { "model" "*95" "classname" "trigger_once" "delay" "30" "targetname" "t218" "target" "t219" } { "model" "*96" "delay" "30" "classname" "trigger_once" "targetname" "t220" "target" "t221" } { "model" "*97" "classname" "trigger_once" "delay" "30" "targetname" "t222" "target" "t223" } { "model" "*98" "classname" "func_illusionary" } { "model" "*99" "classname" "func_illusionary" } { "origin" "488 1056 200" "light" "150" "classname" "light" } { "classname" "item_health" "origin" "656 1256 144" } { "origin" "848 1256 144" "classname" "item_health" } { "model" "*100" "classname" "trigger_secret" } { "angle" "270" "origin" "664 1112 48" "classname" "monster_wizard" "spawnflags" "769" "targetname" "t230" "target" "t231" } { "spawnflags" "769" "classname" "monster_wizard" "origin" "664 1160 48" "angle" "270" "targetname" "t228" "target" "t229" } { "angle" "270" "origin" "872 1160 48" "classname" "monster_wizard" "spawnflags" "769" "targetname" "t228" "target" "t229" } { "spawnflags" "769" "classname" "monster_wizard" "origin" "872 1112 48" "angle" "270" "targetname" "t230" "target" "t231" } { "angle" "270" "origin" "832 1144 48" "classname" "monster_wizard" "spawnflags" "257" "targetname" "t226" "target" "t227" } { "spawnflags" "257" "classname" "monster_wizard" "origin" "832 1096 48" "angle" "270" "targetname" "t224" "target" "t225" } { "angle" "270" "origin" "712 1144 48" "classname" "monster_wizard" "spawnflags" "257" "targetname" "t226" "target" "t227" } { "spawnflags" "257" "classname" "monster_wizard" "origin" "712 1096 48" "angle" "270" "targetname" "t224" "target" "t225" } { "model" "*101" "classname" "trigger_counter" "spawnflags" "1" "targetname" "t225" "count" "2" "target" "t226" } { "model" "*102" "classname" "trigger_counter" "spawnflags" "1" "count" "2" "targetname" "t227" "target" "t228" } { "model" "*103" "classname" "trigger_counter" "spawnflags" "1" "count" "2" "targetname" "t229" "target" "t230" } { "model" "*104" "count" "2" "spawnflags" "1" "classname" "trigger_counter" "targetname" "t231" "target" "t232" } { "model" "*105" "sounds" "3" "classname" "trigger_once" "health" "1" "target" "t93" } { "classname" "monster_zombie" "origin" "-36 -92 176" "spawnflags" "257" "angle" "90" } { "angle" "90" "spawnflags" "257" "origin" "224 -92 176" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "224 604 176" "spawnflags" "257" "angle" "270" } { "angle" "270" "spawnflags" "257" "origin" "-32 604 176" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1724 160 24" "angle" "180" "spawnflags" "257" } { "spawnflags" "257" "angle" "180" "origin" "1724 -160 24" "classname" "monster_zombie" } { "spawnflags" "257" "angle" "90" "origin" "1440 -324 24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1440 324 24" "angle" "270" "spawnflags" "257" } { "classname" "monster_zombie" "origin" "-1060 -828 208" "angle" "90" "spawnflags" "1" } { "spawnflags" "1" "angle" "90" "origin" "-800 -828 208" "classname" "monster_zombie" } { "classname" "light" "origin" "160 216 40" "light" "150" } { "light" "150" "origin" "224 216 40" "classname" "light" } { "classname" "light" "origin" "224 296 40" "light" "150" } { "light" "150" "origin" "160 296 40" "classname" "light" } { "model" "*106" "spawnflags" "2048" "angle" "180" "targetname" "t233" "message" "Are you sure you want to leave now? \n You left something important behind." "wait" "2" "classname" "trigger_multiple" } { "classname" "info_intermission" "origin" "2464 -128 32" "mangle" "20 225 0" } { "model" "*107" "classname" "trigger_secret" } { "model" "*108" "classname" "trigger_once" "target" "t233" "killtarget" "t233" "targetname" "t234" } { "mangle" "20 220 0" "origin" "256 320 240" "classname" "info_intermission" } { "mangle" "0 300 0" "origin" "416 -240 192" "classname" "info_intermission" } { "mangle" "-10 45 0" "origin" "-624 -720 208" "classname" "info_intermission" } { "model" "*109" "spawnflags" "1792" "classname" "func_wall" } { "spawnflags" "1792" "origin" "2640 80 -120" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "64 256 0" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "608 -784 0" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "768 584 200" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "768 1072 128" "classname" "weapon_grenadelauncher" } { "spawnflags" "1793" "origin" "-1328 1808 -8" "classname" "item_cells" } { "spawnflags" "1792" "origin" "-1280 1408 -8" "classname" "item_cells" } { "origin" "-1328 1456 16" "classname" "item_artifact_super_damage" } { "origin" "-1376 1960 -8" "classname" "item_armor1" } { "origin" "-1312 1696 -8" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "-1184 256 128" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "1344 -1392 128" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "1184 -1120 152" "classname" "item_artifact_super_damage" } { "spawnflags" "1792" "origin" "1184 -1568 152" "classname" "item_artifact_invisibility" } { "spawnflags" "1792" "origin" "1856 32 224" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "-872 -672 128" "classname" "weapon_supernailgun" } { "model" "*110" "targetname" "t236" "message" "You must shoot the window \n to open this door." "classname" "trigger_multiple" } { "model" "*111" "targetname" "t93" "killtarget" "t236" "target" "t236" "spawnflags" "1" "classname" "trigger_once" } { "model" "*112" "classname" "func_door" "angle" "-1" "spawnflags" "2056" "sounds" "3" } { "spawnflags" "1" "origin" "-944 1040 128" "classname" "item_shells" } { "model" "*113" "wait" "-1" "sounds" "3" "angle" "270" "classname" "func_door" } { "model" "*114" "wait" "-1" "classname" "func_door" "angle" "90" "sounds" "3" } { "angle" "180" "origin" "232 176 24" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "264 264 24" "angle" "180" } { "angle" "180" "origin" "152 336 24" "classname" "info_player_coop" } { "classname" "item_spikes" "origin" "688 496 200" "spawnflags" "1" } { "angle" "90" "origin" "-760 472 24" "classname" "monster_zombie" "targetname" "t157" "spawnflags" "770" } { "angle" "90" "origin" "-672 536 24" "classname" "monster_zombie" "targetname" "t157" "spawnflags" "770" } { "classname" "monster_zombie" "origin" "-672 480 24" "angle" "90" "targetname" "t157" "spawnflags" "770" } { "model" "*115" "classname" "trigger_teleport" "spawnflags" "2" "target" "t183" } { "model" "*116" "spawnflags" "2" "classname" "trigger_teleport" "target" "t182" } { "model" "*117" "classname" "trigger_teleport" "spawnflags" "2" "target" "t186" } { "classname" "item_artifact_super_damage" "origin" "2732 -304 -104" } { "classname" "monster_zombie" "origin" "2320 -208 -104" "spawnflags" "768" "angle" "135" } { "classname" "item_spikes" "origin" "1168 -1632 128" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-1328 1560 -8" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-944 240 128" } { "classname" "item_spikes" "origin" "752 176 0" "spawnflags" "2817" } { "classname" "item_artifact_invisibility" "origin" "1328 0 8" "spawnflags" "1792" } { "model" "*118" "classname" "func_wall" "spawnflags" "1792" } { "model" "*119" "classname" "trigger_secret" } { "model" "*120" "target" "t234" "classname" "trigger_once" } { "model" "*121" "targetname" "t156" "target" "t234" "classname" "trigger_once" } { "classname" "ambient_drip" "origin" "1666 2 -96" } { "classname" "ambient_swamp1" "origin" "2242 2 -64" } { "origin" "2338 -422 -64" "classname" "ambient_swamp1" } { "classname" "ambient_swamp1" "origin" "2730 -182 -64" } { "classname" "ambient_swamp2" "origin" "2594 218 -64" } { "origin" "2754 442 -64" "classname" "ambient_swamp2" } { "classname" "ambient_swamp2" "origin" "2258 530 -64" } { "classname" "ambient_drip" "origin" "642 834 0" } { "origin" "890 842 0" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "770 1034 160" } { "origin" "-272 -360 128" "classname" "item_spikes" } { "origin" "-1328 -560 128" "classname" "item_shells" } { "origin" "-912 -544 152" "classname" "item_artifact_invisibility" } { "spawnflags" "1" "origin" "80 -1136 128" "classname" "item_health" } { "origin" "1416 608 152" "classname" "item_artifact_invisibility" "spawnflags" "1792" } { "spawnflags" "769" "origin" "-560 -368 128" "classname" "item_shells" } { "spawnflags" "769" "origin" "536 1040 128" "classname" "item_shells" } { "classname" "light" "origin" "2112 -552 -64" "light" "200" } { "classname" "item_artifact_super_damage" "origin" "1424 560 152" "spawnflags" "768" } { "classname" "item_health" "origin" "1408 656 128" "spawnflags" "1" } //////////////////////////////////////////////////////////////////////// // Capture the flag map mods // // capture spawns // team1 { "origin" "1182 -1647 172" "classname" "item_flag_team1" } { "angle" "90" "origin" "1132 -1547 152" "classname" "info_player_team1" } { "angle" "90" "origin" "1132 -1447 152" "classname" "info_player_team1" } { "angle" "90" "origin" "1132 -1347 152" "classname" "info_player_team1" } { "angle" "90" "origin" "1232 -1547 152" "classname" "info_player_team1" } { "angle" "90" "origin" "1232 -1447 152" "classname" "info_player_team1" } { "angle" "90" "origin" "1232 -1347 152" "classname" "info_player_team1" } // team2 { "classname" "item_flag_team2" "origin" "2200 544 -60" } { "classname" "info_player_team2" "origin" "2447 439 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "2630 430 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "2599 269 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "2370 273 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "2244 110 -104" "angle" "180" } { "classname" "info_player_team2" "origin" "2240 -64 -104" "angle" "180" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m4.ent000066400000000000000000001323661475442401000252100ustar00rootroot00000000000000{ "message" "the Palace of Hate" "classname" "worldspawn" "wad" "gfx/medieval.wad" "worldtype" "0" "sounds" "5" } { "origin" "1456 528 -224" "angle" "270" "classname" "info_player_start" } { "angle" "0" "origin" "-112 -328 96" "light" "400" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "400 -952 272" "light" "400" "classname" "light" } { "angle" "0" "origin" "-624 80 272" "light" "400" "classname" "light" } { "angle" "0" "origin" "-1232 104 224" "light" "400" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-1232 -1416 180" "light" "250" "classname" "light_torch_small_walltorch" } { "origin" "-1232 -760 80" "classname" "light_torch_small_walltorch" } { "origin" "-1232 -832 80" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-56 -280 -72" "light" "400" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-864 -1484 172" "light" "250" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "264 -1488 216" "light" "250" "classname" "light_torch_small_walltorch" } { "origin" "420 -1488 60" "light" "250" "classname" "light_torch_small_walltorch" } { "origin" "1208 -1488 196" "light" "350" "classname" "light" } { "angle" "0" "origin" "-136 -1488 60" "light" "150" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-88 -1488 64" "light" "150" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-132 688 52" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-92 688 52" "classname" "light_torch_small_walltorch" } { "targetname" "t11" "target" "t5" "angle" "0" "origin" "-1616 -656 184" "classname" "path_corner" } { "target" "t7" "targetname" "t5" "angle" "0" "origin" "-1640 1112 184" "classname" "path_corner" } { "target" "t10" "targetname" "t7" "angle" "0" "origin" "-760 1112 184" "classname" "path_corner" } { "targetname" "t15" "target" "t12" "angle" "0" "origin" "-960 320 248" "classname" "path_corner" } { "target" "t13" "targetname" "t12" "angle" "0" "origin" "704 320 248" "classname" "path_corner" } { "target" "t20" "targetname" "t13" "angle" "0" "origin" "704 -1168 248" "classname" "path_corner" } { "light" "400" "angle" "0" "origin" "268 1280 128" "classname" "light_torch_small_walltorch" } { "light" "400" "angle" "0" "origin" "532 1280 128" "classname" "light_torch_small_walltorch" } { "target" "t22" "targetname" "t18" "angle" "0" "origin" "-560 -824 232" "classname" "path_corner" } { "target" "t18" "targetname" "t17" "angle" "0" "origin" "336 -824 232" "classname" "path_corner" } { "target" "t17" "targetname" "t16" "angle" "0" "origin" "336 216 40" "classname" "path_corner" } { "origin" "-402 1486 0" "classname" "light" "light" "200" } { "target" "t11" "targetname" "t10" "angle" "0" "origin" "-1584 1088 176" "classname" "path_corner" } { "angle" "0" "origin" "-16 -716 104" "classname" "light_torch_small_walltorch" } { "angle" "0" "origin" "-208 -716 104" "classname" "light_torch_small_walltorch" } { "origin" "-112 -976 96" "light" "400" "classname" "light" } { "style" "5" "angle" "0" "origin" "-112 -400 -16" "light" "300" "classname" "light" } { "angle" "0" "origin" "64 1664 0" "classname" "light" } { "wait" "4" "height" "96" "classname" "func_plat" "sounds" "2" "model" "*1" } { "angle" "-1" "classname" "func_door" "spawnflags" "2064" "wait" "-1" "sounds" "3" "model" "*2" } { "target" "t15" "targetname" "t20" "origin" "-960 -1168 248" "classname" "path_corner" } { "target" "t33" "angle" "180" "origin" "264 1056 40" "classname" "monster_shambler" "spawnflags" "768" } { "targetname" "t22" "target" "t27" "origin" "-560 216 104" "classname" "path_corner" } { "target" "t23" "angle" "45" "origin" "488 -1352 24" "classname" "monster_shambler" "targetname" "t181" } { "target" "t43" "angle" "45" "origin" "-432 1120 128" "classname" "monster_wizard" } { "target" "t25" "targetname" "t24" "origin" "312 -1336 24" "classname" "path_corner" } { "target" "t26" "targetname" "t25" "origin" "368 -1696 24" "classname" "path_corner" } { "target" "t24" "targetname" "t23" "origin" "536 -1288 24" "classname" "path_corner" } { "target" "t23" "targetname" "t26" "origin" "576 -1664 24" "classname" "path_corner" } { "target" "t16" "targetname" "t28" "origin" "456 -904 224" "classname" "path_corner" } { "target" "t28" "targetname" "t27" "origin" "-680 -904 224" "classname" "path_corner" } { "target" "t90" "targetname" "t39" "origin" "184 1976 320" "classname" "path_corner" } { "target" "t33" "targetname" "t29" "origin" "504 912 40" "classname" "path_corner" } { "target" "t109" "targetname" "t32" "origin" "704 1152 40" "classname" "path_corner" } { "target" "t32" "targetname" "t33" "origin" "104 1152 40" "classname" "path_corner" } { "target" "t34" "targetname" "t37" "origin" "512 624 28" "classname" "path_corner" } { "target" "t37" "targetname" "t34" "origin" "-576 624 28" "classname" "path_corner" } { "target" "t36" "targetname" "t35" "origin" "-576 752 28" "classname" "path_corner" } { "target" "t35" "targetname" "t36" "origin" "512 752 28" "classname" "path_corner" } { "target" "t36" "origin" "406 750 24" "classname" "monster_demon1" "spawnflags" "256" } { "target" "t34" "origin" "-506 622 24" "classname" "monster_demon1" } { "target" "t39" "targetname" "t43" "origin" "-392 1160 48" "classname" "path_corner" } { "target" "t47" "targetname" "t45" "origin" "120 1784 128" "classname" "path_corner" } { "target" "t88" "targetname" "t47" "origin" "-256 1080 256" "classname" "path_corner" } { "target" "t47" "origin" "-232 1032 256" "classname" "monster_wizard" "angle" "135" } { "target" "t52" "targetname" "t50" "origin" "-56 2040 -168" "classname" "path_corner" } { "target" "t48" "targetname" "t52" "origin" "400 1904 24" "classname" "path_corner" } { "target" "t49" "targetname" "t48" "origin" "872 2040 -168" "classname" "path_corner" } { "target" "t50" "targetname" "t49" "origin" "400 1776 24" "classname" "path_corner" } { "target" "t150" "targetname" "t58" "origin" "1496 -456 -104" "classname" "path_corner" } { "target" "t58" "targetname" "t57" "origin" "768 -496 24" "classname" "path_corner" } { "origin" "152 -624 0" "classname" "item_shells" } { "origin" "-192 -392 -48" "classname" "item_health" "target" "t203" } { "origin" "-128 -440 -48" "classname" "item_health" "target" "t203" } { "origin" "-64 -392 -48" "classname" "item_health" "target" "t203" } { "origin" "-168 -432 -48" "classname" "item_health" "spawnflags" "2048" "target" "t203" } { "origin" "-88 -432 -48" "classname" "item_health" "spawnflags" "2048" "target" "t203" } { "spawnflags" "1" "origin" "592 -1072 224" "classname" "item_health" } { "spawnflags" "1" "origin" "-928 256 224" "classname" "item_health" } { "origin" "672 256 0" "classname" "item_health" } { "spawnflags" "1" "origin" "-928 -1152 0" "classname" "item_health" } { "origin" "384 -1152 224" "classname" "item_shells" "spawnflags" "1" } { "origin" "-640 256 224" "classname" "item_spikes" "spawnflags" "1" } { "origin" "320 256 224" "classname" "item_spikes" "spawnflags" "1" } { "origin" "-896 -480 224" "classname" "item_health" } { "origin" "680 -96 0" "classname" "item_shells" "spawnflags" "1" } { "origin" "-936 -96 0" "classname" "item_spikes" } { "origin" "-936 -928 0" "classname" "item_spikes" } { "style" "11" "light" "400" "origin" "1578 282 -172" "classname" "light_flame_large_yellow" } { "style" "11" "light" "400" "origin" "1338 282 -172" "classname" "light_flame_large_yellow" } { "target" "t11" "origin" "-1616 -616 184" "classname" "monster_wizard" } { "angle" "270" "origin" "-1170 1358 160" "classname" "monster_demon1" "target" "t197" } { "angle" "0" "origin" "-1938 1102 160" "classname" "monster_demon1" "spawnflags" "768" } { "angle" "0" "origin" "-1906 -50 168" "classname" "monster_demon1" "target" "t158" } { "spawnflags" "256" "origin" "-1610 -970 168" "classname" "monster_demon1" "angle" "90" } { "target" "t73" "targetname" "t72" "origin" "1064 824 88" "classname" "path_corner" } { "target" "t72" "targetname" "t73" "origin" "968 632 96" "classname" "path_corner" } { "target" "t79" "targetname" "t76" "origin" "968 808 192" "classname" "path_corner" } { "target" "t76" "targetname" "t79" "origin" "1064 616 160" "classname" "path_corner" } { "target" "t84" "targetname" "t87" "origin" "1080 808 192" "classname" "path_corner" } { "target" "t87" "targetname" "t84" "origin" "1176 616 256" "classname" "path_corner" } { "target" "t80" "targetname" "t83" "origin" "1176 824 344" "classname" "path_corner" } { "target" "t83" "targetname" "t80" "origin" "1080 632 288" "classname" "path_corner" } { "angle" "315" "target" "t72" "origin" "1032 856 88" "classname" "monster_wizard" "spawnflags" "768" } { "angle" "315" "target" "t76" "origin" "944 848 152" "classname" "monster_wizard" "spawnflags" "768" } { "angle" "135" "target" "t80" "origin" "1112 600 328" "classname" "monster_wizard" } { "target" "t84" "angle" "225" "origin" "1208 648 248" "classname" "monster_wizard" } { "target" "t89" "targetname" "t88" "origin" "-504 1720 256" "classname" "path_corner" } { "targetname" "t89" "target" "t45" "origin" "-264 1912 48" "classname" "path_corner" } { "target" "t43" "targetname" "t90" "origin" "-392 1656 48" "classname" "path_corner" } { "spawnflags" "768" "classname" "monster_wizard" "origin" "-488 208 100" "target" "t22" } { "origin" "-1632 -800 136" "classname" "item_shells" } { "spawnflags" "1" "origin" "-1576 -64 136" "classname" "item_health" } { "origin" "-1304 -192 0" "classname" "item_armor1" } { "origin" "-1184 1520 136" "classname" "item_spikes" "spawnflags" "1" } { "origin" "-1184 1088 136" "classname" "item_health" } { "origin" "-800 1088 136" "classname" "item_shells" } { "target" "t97" "targetname" "t95" "origin" "-168 2072 -32" "classname" "path_corner" } { "target" "t95" "targetname" "t97" "origin" "56 1864 -40" "classname" "path_corner" } { "target" "t107" "targetname" "t105" "origin" "760 1664 -56" "classname" "path_corner" } { "target" "t105" "targetname" "t103" "origin" "712 1928 -24" "classname" "path_corner" } { "target" "t103" "targetname" "t108" "origin" "920 2072 -56" "classname" "path_corner" } { "target" "t108" "targetname" "t107" "origin" "840 1856 -24" "classname" "path_corner" } { "target" "t103" "origin" "752 1920 -56" "classname" "monster_fish" "spawnflags" "256" } { "target" "t107" "angle" "45" "origin" "784 1840 -56" "classname" "monster_fish" } { "target" "t29" "targetname" "t109" "origin" "120 1152 40" "classname" "path_corner" } { "target" "t112" "targetname" "t111" "origin" "-40 1792 24" "classname" "path_corner" } { "target" "t113" "targetname" "t112" "origin" "352 1792 -168" "classname" "path_corner" } { "target" "t111" "targetname" "t113" "origin" "184 1664 0" "classname" "path_corner" } { "target" "t112" "origin" "304 1792 -8" "classname" "monster_fish" } { "target" "t111" "origin" "-16 1752 -160" "classname" "monster_fish" "spawnflags" "256" } { "classname" "item_spikes" "origin" "-400 64 0" "spawnflags" "1" } { "classname" "item_spikes" "origin" "144 64 0" "spawnflags" "1" } { "classname" "monster_fish" "origin" "-80 2000 -112" "target" "t95" } { "classname" "path_corner" "origin" "-1384 -784 208" "targetname" "t116" "target" "t115" } { "classname" "path_corner" "origin" "-1072 -784 208" "targetname" "t115" "target" "t116" } { "classname" "path_corner" "origin" "-112 -1320 176" "targetname" "t118" "target" "t119" } { "classname" "path_corner" "origin" "-112 -1640 176" "targetname" "t119" "target" "t118" } { "classname" "item_spikes" "origin" "-1248 32 0" "spawnflags" "1" } { "classname" "item_health" "origin" "-1152 -32 0" } { "classname" "item_health" "origin" "-1304 -1504 0" } { "wait" "-1" "classname" "func_door" "speed" "300" "angle" "-2" "targetname" "t125" "lip" "0" "model" "*3" } { "wait" "-1" "classname" "func_door" "speed" "300" "angle" "-2" "targetname" "t125" "lip" "0" "model" "*4" } { "classname" "trigger_once" "target" "t125" "model" "*5" } { "classname" "monster_demon1" "origin" "-560 -416 -104" "angle" "90" "targetname" "t125" } { "classname" "monster_demon1" "origin" "-656 -32 -104" "angle" "270" "targetname" "t125" } { "wait" "-1" "classname" "func_door" "speed" "50" "angle" "270" "targetname" "t126" "sounds" "3" "model" "*6" } { "wait" "-1" "classname" "func_door" "angle" "270" "speed" "50" "targetname" "t126" "sounds" "3" "model" "*7" } { "wait" "-1" "classname" "func_door" "angle" "270" "speed" "50" "targetname" "t126" "sounds" "3" "model" "*8" } { "classname" "path_corner" "origin" "-1232 -1248 280" "targetname" "t139" "target" "t129" } { "classname" "path_corner" "origin" "-1304 -928 64" "targetname" "t129" "target" "t130" } { "classname" "path_corner" "origin" "-1152 -928 64" "targetname" "t138" "target" "t139" } { "classname" "path_corner" "origin" "-1304 -656 64" "targetname" "t130" "target" "t131" } { "classname" "path_corner" "origin" "-1152 -656 64" "targetname" "t137" "target" "t138" } { "classname" "path_corner" "origin" "-1304 -344 288" "targetname" "t131" "target" "t137" } { "classname" "monster_wizard" "origin" "-1176 -608 56" "target" "t137" "angle" "315" } { "classname" "path_corner" "origin" "192 -1480 256" "targetname" "t144" "target" "t145" } { "classname" "path_corner" "origin" "0 -1408 56" "targetname" "t145" "target" "t146" } { "classname" "path_corner" "origin" "0 -1568 56" "targetname" "t143" "target" "t144" } { "classname" "path_corner" "origin" "-256 -1568 56" "targetname" "t142" "target" "t143" } { "classname" "path_corner" "origin" "-256 -1408 56" "targetname" "t146" "target" "t148" } { "classname" "path_corner" "origin" "-768 -1488 224" "targetname" "t148" "target" "t142" } { "classname" "monster_wizard" "origin" "-208 -1408 248" "target" "t146" } { "spawnflags" "768" "classname" "monster_wizard" "origin" "-56 -1568 48" "target" "t143" "angle" "0" } { "classname" "item_rockets" "origin" "-120 2048 -192" "spawnflags" "768" } { "classname" "item_health" "origin" "640 1696 -192" } { "classname" "item_spikes" "origin" "64 1600 -192" "spawnflags" "1" } { "classname" "item_spikes" "origin" "904 1984 -192" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-608 2024 16" } { "classname" "item_health" "origin" "-608 928 16" } { "classname" "item_health" "origin" "192 1856 -192" } { "classname" "item_health" "origin" "768 1448 16" } { "classname" "item_health" "origin" "960 960 16" "spawnflags" "1" } { "classname" "item_shells" "origin" "1008 1328 16" "spawnflags" "1" } { "classname" "item_health" "origin" "0 904 16" } { "classname" "item_shells" "origin" "-624 592 0" "spawnflags" "1" } { "classname" "item_health" "origin" "-616 768 0" } { "classname" "item_health" "origin" "432 1328 16" } { "classname" "light" "origin" "-160 2048 0" } { "classname" "path_corner" "origin" "1480 -528 -104" "target" "t57" "targetname" "t150" } { "classname" "light_flame_small_yellow" "origin" "-1230 -294 364" } { "classname" "light_flame_small_yellow" "origin" "-1230 -526 364" } { "classname" "light_flame_small_yellow" "origin" "-606 -1486 324" } { "classname" "light_flame_small_yellow" "origin" "-382 -1486 324" } { "classname" "light_flame_small_yellow" "origin" "66 -1486 324" } { "classname" "monster_wizard" "origin" "256 224 100" "target" "t16" "angle" "0" } { "classname" "light" "origin" "680 -496 40" "light" "200" } { "classname" "light" "light" "200" "origin" "400 -1032 272" "angle" "0" } { "classname" "monster_demon1" "origin" "376 984 40" "target" "t33" "spawnflags" "1024" } { "classname" "light_torch_small_walltorch" "origin" "458 850 128" "light" "400" } { "light" "150" "origin" "256 -272 136" "classname" "light" } { "classname" "light" "origin" "256 -80 136" "light" "150" } { "light" "150" "origin" "-480 -80 136" "classname" "light" } { "classname" "light" "origin" "-480 -272 136" "light" "150" } { "light" "150" "origin" "-480 -464 136" "classname" "light" } { "classname" "light" "origin" "-472 -704 136" "light" "200" } { "light" "200" "origin" "240 -704 136" "classname" "light" } { "origin" "1496 -568 -128" "classname" "item_shells" "spawnflags" "1" } { "origin" "640 -464 224" "classname" "item_armor1" } { "origin" "-606 -486 -68" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-606 50 -68" } { "light" "200" "origin" "-904 -216 -84" "classname" "light" } { "origin" "400 1728 0" "classname" "light" } { "target" "t49" "origin" "448 1776 -24" "classname" "monster_fish" "spawnflags" "256" } { "target" "t50" "origin" "0 2024 -152" "classname" "monster_fish" } { "target" "t52" "origin" "352 1904 -40" "classname" "monster_fish" "spawnflags" "256" } { "target" "t48" "origin" "832 2032 -152" "classname" "monster_fish" } { "style" "32" "light" "500" "origin" "1072 696 168" "classname" "light" "target" "t202" "targetname" "t205" } { "classname" "monster_knight" "origin" "-384 -176 24" "angle" "90" } { "angle" "90" "origin" "160 -176 24" "classname" "monster_knight" } { "classname" "light_torch_small_walltorch" "light" "250" "origin" "444 -1488 60" } { "light" "200" "origin" "840 -496 40" "classname" "light" } { "origin" "1530 -502 -68" "classname" "light_torch_small_walltorch" } { "light" "120" "origin" "40 -1160 94" "classname" "light" } { "classname" "light" "origin" "-264 -1160 94" "light" "120" } { "light" "150" "origin" "256 -464 136" "classname" "light" } { "classname" "light" "origin" "-896 -80 136" "light" "150" } { "light" "150" "origin" "-896 -336 136" "classname" "light" } { "classname" "light" "origin" "-896 -656 136" "light" "150" } { "light" "150" "origin" "-896 -912 136" "classname" "light" } { "classname" "light" "origin" "-624 -1112 136" "light" "150" } { "light" "150" "origin" "400 -1112 136" "classname" "light" } { "classname" "light" "origin" "672 -912 136" "light" "150" } { "light" "150" "origin" "672 -656 136" "classname" "light" } { "classname" "light" "origin" "672 -336 136" "light" "150" } { "light" "150" "origin" "672 -80 136" "classname" "light" } { "origin" "-112 280 136" "classname" "monster_demon1" "spawnflags" "768" } { "classname" "light" "origin" "-440 1488 336" "target" "t165" "style" "2" } { "spawnflags" "1" "origin" "-1840 -536 56" "classname" "monster_wizard" "targetname" "t197" } { "origin" "-1856 -664 56" "classname" "monster_wizard" "targetname" "t158" "spawnflags" "1" } { "targetname" "t197" "classname" "trigger_teleport" "target" "t196" "spawnflags" "2" "model" "*9" } { "targetname" "t158" "classname" "trigger_teleport" "target" "t154" "spawnflags" "2" "model" "*10" } { "classname" "info_teleport_destination" "origin" "-1616 -264 200" "angle" "45" "targetname" "t154" } { "classname" "func_button" "target" "t126" "wait" "-1" "angle" "-2" "sounds" "1" "model" "*11" } { "classname" "trigger_once" "target" "t166" "targetname" "t165" "wait" "-1" "model" "*12" } { "targetname" "t166" "classname" "func_train" "target" "t168" "wait" "1.5" "model" "*13" } { "wait" "2" "classname" "path_corner" "origin" "784 1728 -16" "targetname" "t167" "target" "t168" } { "origin" "784 2016 -16" "classname" "path_corner" "targetname" "t168" "target" "t167" } { "classname" "func_train" "target" "t170" "model" "*14" } { "origin" "16 1728 -16" "classname" "path_corner" "targetname" "t169" "target" "t170" "wait" "1.5" } { "classname" "path_corner" "origin" "16 2024 -16" "targetname" "t170" "target" "t169" } { "style" "32" "sounds" "2" "classname" "item_key1" "origin" "1072 752 40" "targetname" "t175" "spawnflags" "2048" "target" "t205" } { "classname" "monster_demon1" "origin" "-1952 -544 24" "targetname" "t191" "target" "t206" "angle" "0" "spawnflags" "257" } { "classname" "monster_demon1" "origin" "-1952 -648 24" "target" "t207" "targetname" "t191" "spawnflags" "257" } { "classname" "monster_demon1" "origin" "-2056 -648 24" "targetname" "t171" "spawnflags" "769" } { "origin" "-2056 -544 24" "classname" "monster_demon1" "targetname" "t172" "spawnflags" "769" } { "spawnflags" "768" "classname" "monster_demon1" "origin" "-992 -1744 24" "angle" "0" "targetname" "t174" } { "target" "t183" "angle" "0" "origin" "-976 -1488 24" "classname" "monster_demon1" "targetname" "t173" "spawnflags" "256" } { "spawnflags" "256" "targetname" "t183" "classname" "monster_demon1" "origin" "-1232 -1488 24" "angle" "90" "target" "t173" } { "classname" "trigger_once" "target" "t174" "model" "*15" } { "classname" "monster_knight" "origin" "-1328 -16 24" "angle" "270" "spawnflags" "768" } { "angle" "270" "origin" "-1280 -64 24" "classname" "monster_knight" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t176" "sounds" "1" "model" "*16" } { "classname" "trigger_once" "target" "t176" "model" "*17" } { "classname" "monster_demon1" "origin" "400 2272 56" "angle" "270" } { "classname" "monster_demon1" "origin" "1424 -456 -104" "target" "t58" } { "classname" "monster_hell_knight" "origin" "704 -1088 248" "angle" "270" "target" "t13" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "-880 -1168 248" "angle" "180" "target" "t20" } { "classname" "monster_hell_knight" "origin" "-960 240 248" "target" "t15" "angle" "90" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "624 320 248" "angle" "0" "target" "t12" } { "targetname" "t187" "target" "t186" "classname" "monster_demon1" "origin" "640 -896 248" "angle" "270" "spawnflags" "768" } { "target" "t187" "targetname" "t186" "spawnflags" "768" "angle" "90" "origin" "640 -400 248" "classname" "monster_demon1" } { "target" "t185" "targetname" "t184" "classname" "monster_demon1" "origin" "-864 -32 248" "angle" "90" "spawnflags" "768" } { "target" "t189" "targetname" "t188" "classname" "monster_demon1" "origin" "224 -1056 248" "angle" "0" } { "angle" "45" "origin" "-352 -576 24" "classname" "monster_knight" } { "classname" "monster_knight" "origin" "-192 -304 24" "angle" "180" } { "angle" "0" "origin" "-32 -304 24" "classname" "monster_knight" } { "classname" "monster_knight" "origin" "-112 432 24" "angle" "0" } { "classname" "monster_knight" "origin" "-288 -1136 24" "angle" "315" "targetname" "t178" } { "angle" "225" "origin" "64 -1136 24" "classname" "monster_knight" "targetname" "t177" } { "classname" "trigger_once" "target" "t177" "model" "*18" } { "classname" "trigger_once" "target" "t178" "model" "*19" } { "classname" "item_shells" "origin" "-408 -624 0" } { "classname" "item_shells" "origin" "800 584 0" "spawnflags" "1" } { "classname" "item_shells" "origin" "-1248 -656 0" } { "classname" "item_shells" "origin" "-128 -1760 144" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-624 -1384 0" } { "classname" "item_spikes" "origin" "-400 -1624 0" "spawnflags" "1" } { "classname" "item_health" "origin" "384 2432 32" "spawnflags" "2" } { "classname" "light" "origin" "-320 -584 56" "light" "150" } { "light" "150" "origin" "96 -584 56" "classname" "light" } { "classname" "light" "origin" "176 -192 152" "light" "100" } { "light" "100" "origin" "-400 -192 152" "classname" "light" } { "classname" "item_armorInv" "origin" "-112 568 0" } { "style" "33" "origin" "-376 1488 288" "classname" "light" "targetname" "t166" } { "classname" "light" "origin" "328 248 136" "light" "150" } { "light" "150" "origin" "-616 288 136" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "122 2322 140" } { "light" "300" "origin" "682 2314 140" "classname" "light_torch_small_walltorch" } { "targetname" "t185" "target" "t184" "spawnflags" "768" "angle" "270" "origin" "-864 -560 248" "classname" "monster_demon1" } { "spawnflags" "1280" "target" "t118" "origin" "-112 -1440 176" "classname" "monster_demon1" } { "spawnflags" "1280" "target" "t116" "angle" "180" "origin" "-1288 -784 208" "classname" "monster_demon1" } { "angle" "180" "origin" "-1104 -88 24" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "light" "origin" "-112 80 56" } { "classname" "light" "origin" "-368 232 -72" } { "classname" "light" "origin" "144 224 -72" } { "classname" "func_door" "angle" "-1" "wait" "-1" "sounds" "3" "model" "*20" } { "classname" "monster_hell_knight" "origin" "744 -1624 24" "angle" "90" "spawnflags" "256" } { "angle" "270" "origin" "744 -1352 24" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "trigger_once" "target" "t198" "model" "*21" } { "classname" "monster_shambler" "origin" "384 -1880 24" "angle" "90" "target" "t25" "spawnflags" "768" } { "angle" "45" "classname" "info_teleport_destination" "origin" "488 -1352 8" "targetname" "t182" } { "classname" "trigger_teleport" "target" "t182" "spawnflags" "2" "model" "*22" } { "targetname" "t189" "target" "t188" "angle" "180" "origin" "-440 -1056 248" "classname" "monster_demon1" } { "light" "200" "origin" "88 1992 56" "classname" "light" } { "classname" "light" "origin" "392 1928 56" "light" "200" } { "style" "33" "light" "200" "origin" "712 1992 56" "classname" "light" "targetname" "t166" "spawnflags" "1" } { "style" "33" "spawnflags" "1" "classname" "light" "origin" "936 1976 56" "light" "200" "targetname" "t166" } { "style" "33" "spawnflags" "1" "light" "200" "origin" "824 1784 56" "classname" "light" "targetname" "t166" } { "targetname" "t166" "lip" "4" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*23" } { "spawnflags" "768" "angle" "225" "origin" "656 2192 56" "classname" "monster_demon1" } { "spawnflags" "768" "angle" "315" "origin" "144 2192 56" "classname" "monster_demon1" } { "spawnflags" "1" "origin" "272 2384 32" "classname" "item_spikes" } { "spawnflags" "1" "origin" "496 2384 32" "classname" "item_spikes" } { "wait" "10" "target" "t190" "classname" "trigger_multiple" "model" "*24" } { "speed" "300" "angle" "-2" "targetname" "t190" "classname" "func_door" "sounds" "1" "spawnflags" "4" "model" "*25" } { "wait" "-1" "speed" "300" "angle" "-2" "targetname" "t190" "classname" "func_door" "sounds" "1" "model" "*26" } { "angle" "135" "origin" "-1840 944 320" "classname" "monster_knight" "spawnflags" "768" } { "classname" "monster_knight" "origin" "-1840 1264 320" "angle" "225" "spawnflags" "768" } { "spawnflags" "256" "angle" "270" "origin" "-2032 1264 320" "classname" "monster_knight" } { "classname" "monster_knight" "origin" "-2032 944 320" "angle" "90" "spawnflags" "256" } { "lip" "-8" "speed" "500" "targetname" "t191" "dmg" "60" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*27" } { "target" "t191" "wait" "5" "classname" "trigger_multiple" "model" "*28" } { "light" "200" "origin" "-784 1248 304" "classname" "light" } { "light" "200" "classname" "light" "origin" "-784 1344 304" } { "origin" "-414 146 108" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "194 146 108" } { "origin" "-110 -1486 324" "classname" "light_flame_small_yellow" } { "light" "150" "origin" "752 -496 264" "classname" "light" } { "classname" "light" "origin" "752 336 264" "light" "150" } { "light" "150" "origin" "-976 -160 264" "classname" "light" } { "origin" "-1230 -782 364" "classname" "light_flame_small_yellow" } { "light" "150" "classname" "light" "origin" "-976 1104 232" } { "origin" "-1392 1104 232" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-1168 1440 232" } { "origin" "-1968 1104 232" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-1616 752 232" } { "origin" "-1616 304 232" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-1968 -48 232" } { "origin" "-1616 -432 232" "classname" "light" "light" "150" } { "light" "150" "classname" "light" "origin" "-1616 -912 232" } { "light" "200" "origin" "256 2048 152" "classname" "light" } { "classname" "light" "origin" "528 2048 152" "light" "200" } { "light" "250" "origin" "-816 -224 320" "classname" "light" } { "light" "150" "origin" "-960 -1184 296" "classname" "light" } { "light" "150" "origin" "232 -1400 76" "classname" "light" } { "light" "150" "origin" "-112 -1624 76" "classname" "light" } { "classname" "light" "origin" "-112 -1352 76" "light" "150" } { "classname" "item_health" "origin" "-104 -392 -48" "spawnflags" "2048" "target" "t203" } { "origin" "-152 -392 -48" "classname" "item_health" "spawnflags" "2048" "target" "t203" } { "target" "t192" "health" "1" "classname" "trigger_once" "model" "*29" } { "targetname" "t192" "speed" "400" "wait" "-1" "angle" "-2" "classname" "func_door" "sounds" "3" "model" "*30" } { "spawnflags" "768" "angle" "90" "target" "t118" "origin" "-112 -1568 176" "classname" "monster_shambler" } { "spawnflags" "768" "angle" "180" "target" "t116" "origin" "-1160 -784 208" "classname" "monster_shambler" } { "targetname" "t192" "angle" "90" "origin" "-112 -1120 24" "classname" "monster_demon1" } { "origin" "-184 -1144 24" "classname" "item_artifact_invulnerability" } { "spawnflags" "1" "origin" "-200 -1120 0" "classname" "item_spikes" } { "wait" "-1" "targetname" "t195" "angle" "180" "classname" "func_door_secret" "sounds" "3" "lip" "8" "model" "*31" } { "delay" "6" "target" "t195" "targetname" "t190" "classname" "trigger_multiple" "model" "*32" } { "target" "t196" "classname" "trigger_teleport" "model" "*33" } { "origin" "-1960 792 216" "classname" "light" } { "origin" "-1824 800 160" "classname" "item_artifact_super_damage" } { "targetname" "t196" "angle" "315" "origin" "-784 1504 264" "classname" "info_teleport_destination" } { "angle" "180" "origin" "1160 1536 40" "classname" "monster_demon1" "spawnflags" "256" } { "light" "300" "origin" "394 2482 140" "classname" "light_torch_small_walltorch" } { "spawnflags" "1792" "origin" "-464 1488 200" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "-600 -208 -128" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "632 -1480 0" "classname" "weapon_rocketlauncher" } { "angle" "90" "origin" "864 -1624 24" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-160 -1760 168" "classname" "info_player_deathmatch" } { "angle" "0" "origin" "-2016 -104 160" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "-1184 16 24" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "168 -528 24" "classname" "info_player_deathmatch" } { "angle" "45" "origin" "48 952 40" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "1344 512 -232" "classname" "info_player_deathmatch" } { "spawnflags" "769" "origin" "-136 -880 0" "classname" "item_shells" } { "spawnflags" "769" "origin" "664 -1496 0" "classname" "item_spikes" } { "spawnflags" "769" "origin" "-1080 -1504 0" "classname" "item_shells" } { "spawnflags" "769" "origin" "-1248 -896 0" "classname" "item_spikes" } { "classname" "light" "origin" "-448 2080 40" "light" "250" } { "light" "250" "origin" "-632 2080 40" "classname" "light" } { "classname" "light" "origin" "-632 1856 40" "light" "250" } { "light" "250" "origin" "-632 1472 40" "classname" "light" } { "classname" "light" "origin" "-632 1656 40" "light" "250" } { "classname" "light" "origin" "-632 1280 40" "light" "250" } { "light" "250" "origin" "-632 1088 40" "classname" "light" } { "classname" "light" "origin" "-632 896 40" "light" "250" } { "light" "250" "origin" "-120 896 40" "classname" "light" } { "classname" "light" "origin" "-384 896 40" "light" "250" } { "light" "250" "origin" "-56 1080 40" "classname" "light" } { "classname" "light" "origin" "8 1272 40" "light" "250" } { "classname" "light" "origin" "72 1464 40" "light" "250" } { "light" "250" "origin" "920 576 40" "classname" "light" } { "classname" "light" "origin" "1216 576 40" "light" "250" } { "light" "250" "origin" "1216 768 40" "classname" "light" } { "classname" "light" "origin" "1216 960 40" "light" "250" } { "light" "250" "origin" "1216 1152 40" "classname" "light" } { "classname" "light" "origin" "1216 1344 40" "light" "250" } { "light" "250" "origin" "1216 1536 40" "classname" "light" } { "classname" "light" "origin" "928 768 40" "light" "250" } { "light" "250" "origin" "904 952 40" "classname" "light" } { "classname" "light" "origin" "840 1144 40" "light" "250" } { "light" "250" "origin" "776 1336 40" "classname" "light" } { "classname" "light" "origin" "712 1512 40" "light" "250" } { "classname" "trigger_changelevel" "map" "e4m5" "model" "*34" } { "origin" "-1224 -200 -68" "classname" "light" } { "light" "200" "origin" "-1784 936 368" "classname" "light" } { "classname" "light" "origin" "-1992 952 368" "light" "200" } { "classname" "light" "origin" "608 272 112" "light" "200" } { "light" "200" "origin" "608 -1136 112" "classname" "light" } { "classname" "light" "origin" "-864 -1152 112" "light" "200" } { "light" "200" "origin" "-864 272 112" "classname" "light" } { "classname" "light" "origin" "-352 80 112" "light" "200" } { "light" "200" "origin" "128 80 112" "classname" "light" } { "classname" "light_torch_small_walltorch" "origin" "562 -78 148" "light" "350" } { "light" "350" "origin" "562 -654 148" "classname" "light_torch_small_walltorch" } { "light" "350" "origin" "-782 -78 148" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-782 -654 148" "light" "350" } { "classname" "light" "origin" "-968 328 288" "light" "150" } { "classname" "light" "origin" "-672 -1032 320" "light" "250" } { "light" "250" "origin" "-976 -480 288" "classname" "light" } { "light" "250" "origin" "-96 -1032 320" "classname" "light" } { "classname" "light" "light" "200" "origin" "-624 168 272" "angle" "0" } { "classname" "light" "origin" "584 -800 320" "light" "250" } { "angle" "0" "origin" "736 -1184 272" "light" "150" "classname" "light" } { "light" "250" "origin" "584 -160 320" "classname" "light" } { "classname" "light" "origin" "416 168 320" "light" "250" } { "light" "250" "origin" "-96 168 320" "classname" "light" } { "light" "300" "origin" "304 448 288" "classname" "light" } { "classname" "light" "origin" "-112 784 208" "light" "200" } { "light" "200" "origin" "-616 704 160" "classname" "light" } { "classname" "light" "origin" "384 592 160" "light" "200" } { "light" "200" "origin" "816 704 160" "classname" "light" } { "classname" "light" "origin" "336 1536 160" "light" "200" } { "light" "200" "origin" "464 1536 160" "classname" "light" } { "classname" "light" "origin" "576 1680 160" "light" "200" } { "light" "200" "origin" "224 1680 160" "classname" "light" } { "origin" "1088 1552 288" "classname" "light" } { "classname" "light" "origin" "1200 1248 288" } { "origin" "1200 832 288" "classname" "light" } { "classname" "light" "origin" "1072 592 288" } { "classname" "light" "origin" "944 832 288" } { "classname" "light" "origin" "824 1272 288" } { "origin" "720 1584 288" "classname" "light" } { "origin" "80 1584 288" "classname" "light" } { "classname" "light" "origin" "-24 1272 288" } { "origin" "-192 912 288" "classname" "light" } { "classname" "light" "origin" "-576 912 288" } { "origin" "-576 1344 288" "classname" "light" } { "classname" "light" "origin" "-576 1632 288" } { "origin" "-576 1552 288" "classname" "light" } { "classname" "light" "origin" "-576 1424 288" } { "origin" "-616 1952 288" "classname" "light" } { "classname" "light" "origin" "-288 2064 288" } { "origin" "120 2016 288" "classname" "light" } { "style" "33" "classname" "light" "origin" "688 2016 288" "targetname" "t166" "spawnflags" "1" } { "origin" "400 1960 288" "classname" "light" } { "light" "250" "origin" "-808 -800 320" "classname" "light" } { "classname" "light" "origin" "-1504 -736 288" "light" "150" } { "light" "250" "origin" "-1056 -1456 96" "classname" "light" } { "classname" "light" "origin" "-1056 -1776 96" "light" "250" } { "light" "250" "origin" "-1280 -1632 96" "classname" "light" } { "classname" "light" "origin" "-544 -1712 224" "light" "250" } { "light" "250" "origin" "-64 -1728 256" "classname" "light" } { "light" "250" "origin" "-416 -1616 160" "classname" "light" } { "classname" "light" "origin" "-416 -1360 160" "light" "250" } { "classname" "light" "origin" "-1104 -544 160" "light" "250" } { "classname" "light" "origin" "-1360 -192 160" "light" "250" } { "classname" "light" "origin" "800 -1360 112" "light" "250" } { "light" "250" "origin" "800 -1616 112" "classname" "light" } { "light" "250" "origin" "-1360 -784 400" "classname" "light" } { "classname" "item_shells" "origin" "-1360 -752 184" } { "style" "33" "spawnflags" "1" "light" "200" "origin" "896 2064 160" "classname" "light" "targetname" "t166" } { "style" "33" "light" "200" "origin" "920 1856 160" "classname" "light" "targetname" "t166" "spawnflags" "1" } { "classname" "trigger_secret" "model" "*35" } { "classname" "trigger_secret" "model" "*36" } { "classname" "trigger_secret" "model" "*37" } { "classname" "weapon_supershotgun" "origin" "1448 -544 -128" } { "classname" "weapon_grenadelauncher" "origin" "-112 -560 0" } { "classname" "monster_knight" "origin" "128 -576 24" "angle" "135" "spawnflags" "256" } { "classname" "weapon_grenadelauncher" "origin" "-776 1424 136" "spawnflags" "2048" } { "classname" "weapon_supernailgun" "origin" "400 2024 48" } { "classname" "weapon_nailgun" "origin" "-2000 -48 136" } { "classname" "weapon_lightning" "origin" "416 1824 -160" "spawnflags" "1792" } { "classname" "item_artifact_envirosuit" "origin" "368 1344 40" "spawnflags" "1536" } { "classname" "item_artifact_invisibility" "origin" "-424 1432 224" } { "classname" "item_spikes" "origin" "-2080 1088 136" } { "classname" "func_door" "wait" "-1" "targetname" "t198" "model" "*38" } { "light" "150" "classname" "light" "origin" "864 2016 -128" } { "origin" "864 1824 -128" "classname" "light" "light" "150" } { "classname" "light" "origin" "784 1984 56" "light" "150" } { "height" "100" "speed" "300" "angle" "90" "classname" "trigger_monsterjump" "model" "*39" } { "height" "100" "classname" "trigger_monsterjump" "angle" "270" "speed" "300" "model" "*40" } { "angle" "180" "classname" "trigger_monsterjump" "model" "*41" } { "angle" "270" "classname" "trigger_monsterjump" "model" "*42" } { "classname" "trigger_monsterjump" "angle" "90" "model" "*43" } { "classname" "item_health" "origin" "1440 416 -256" "spawnflags" "2050" } { "classname" "trigger_multiple" "wait" "2" "message" "Are you sure you want to exit now? \n You left something important behind." "targetname" "t201" "spawnflags" "2048" "model" "*44" } { "mangle" "-15 75 0" "origin" "-1344 -1160 256" "classname" "info_intermission" } { "mangle" "15 20 0" "origin" "-336 -928 256" "classname" "info_intermission" } { "mangle" "-15 50 0" "origin" "-544 1296 256" "classname" "info_intermission" } { "mangle" "0 135 0" "origin" "592 -1136 320" "classname" "info_intermission" } { "classname" "func_wall" "spawnflags" "1792" "model" "*45" } { "classname" "info_null" "origin" "1068 748 20" "targetname" "t202" } { "classname" "item_cells" "origin" "1040 1032 16" "spawnflags" "1793" } { "classname" "item_cells" "origin" "512 672 0" "spawnflags" "1793" } { "classname" "item_cells" "origin" "-464 1200 16" "spawnflags" "1793" } { "classname" "item_artifact_invisibility" "origin" "400 2368 56" "spawnflags" "1792" } { "classname" "item_artifact_invulnerability" "origin" "1168 688 40" } { "classname" "weapon_grenadelauncher" "origin" "-40 -1144 0" "spawnflags" "1792" } { "classname" "weapon_lightning" "origin" "-152 -1496 152" "spawnflags" "1792" } { "classname" "item_cells" "origin" "-512 -1568 0" "spawnflags" "1793" } { "classname" "item_artifact_invisibility" "origin" "-1192 -40 24" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-288 224 224" "spawnflags" "1792" } { "spawnflags" "2817" "origin" "-1248 -1328 0" "classname" "item_shells" } { "classname" "func_door" "angle" "90" "sounds" "3" "wait" "-1" "model" "*46" } { "wait" "-1" "sounds" "3" "angle" "270" "classname" "func_door" "model" "*47" } { "classname" "light" "origin" "1208 -1488 136" "light" "200" } { "angle" "270" "origin" "1552 496 -232" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "1344 448 -232" "angle" "270" } { "angle" "270" "origin" "1552 384 -232" "classname" "info_player_coop" } { "light" "200" "origin" "920 -1488 120" "classname" "light" } { "light" "150" "origin" "-96 2016 -128" "classname" "light" } { "classname" "light" "origin" "-32 1824 -128" "light" "150" } { "light" "150" "origin" "96 1632 -128" "classname" "light" } { "spawnflags" "1793" "origin" "400 1872 -192" "classname" "item_cells" } { "spawnflags" "1793" "origin" "464 1808 -160" "classname" "item_cells" } { "classname" "item_cells" "origin" "336 1808 -160" "spawnflags" "1793" } { "classname" "light" "origin" "96 1952 -128" "light" "150" } { "light" "150" "origin" "224 1816 -128" "classname" "light" } { "classname" "light" "origin" "400 1952 -128" "light" "150" } { "light" "150" "origin" "608 1824 -128" "classname" "light" } { "classname" "light" "origin" "400 1656 -128" "light" "150" } { "light" "150" "origin" "664 2016 -128" "classname" "light" } { "classname" "weapon_lightning" "origin" "-112 624 0" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "648 -1096 224" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-864 -1080 224" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "632 224 224" "spawnflags" "1792" } { "classname" "item_artifact_super_damage" "origin" "-848 208 248" "spawnflags" "1792" } { "classname" "weapon_supernailgun" "origin" "856 -1392 0" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-1616 -48 136" "spawnflags" "1792" } { "classname" "item_health" "origin" "-672 -472 -128" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-592 8 -128" } { "classname" "item_spikes" "origin" "-128 -224 -128" } { "classname" "item_spikes" "origin" "-1632 1088 136" } { "classname" "item_shells" "origin" "-2080 -64 136" } { "classname" "item_shells" "origin" "-640 -1120 0" } { "classname" "item_shells" "origin" "144 -272 0" } { "classname" "trigger_secret" "message" "You have found a healing pool!" "model" "*48" } { "classname" "trigger_counter" "count" "7" "spawnflags" "1" "targetname" "t203" "message" "You have drained the healing \n pool of all its power. " "model" "*49" } { "classname" "func_wall" "spawnflags" "1792" "model" "*50" } { "killtarget" "t201" "target" "t201" "classname" "trigger_once" "model" "*51" } { "classname" "trigger_teleport" "target" "t196" "model" "*52" } { "classname" "info_teleport_destination" "origin" "656 -1456 168" "angle" "180" "targetname" "t204" } { "classname" "item_spikes" "origin" "-128 456 112" } { "classname" "item_spikes" "origin" "384 1496 16" } { "target" "t154" "spawnflags" "2" "classname" "trigger_teleport" "model" "*53" } { "target" "t196" "spawnflags" "2" "classname" "trigger_teleport" "model" "*54" } { "origin" "-1232 -1040 360" "classname" "light_flame_small_yellow" } { "origin" "-1614 302 292" "classname" "light_flame_large_yellow" } { "origin" "-1614 750 288" "classname" "light_flame_large_yellow" } { "origin" "-1614 -430 292" "classname" "light_flame_large_yellow" } { "origin" "-1614 -910 292" "classname" "light_flame_large_yellow" } { "origin" "-1966 -46 292" "classname" "light_flame_large_yellow" } { "origin" "-1966 1106 292" "classname" "light_flame_large_yellow" } { "origin" "-1390 1106 292" "classname" "light_flame_large_yellow" } { "origin" "-974 1106 292" "classname" "light_flame_large_yellow" } { "origin" "-1166 1442 292" "classname" "light_flame_large_yellow" } { "light" "200" "origin" "800 1672 -72" "classname" "light" } { "classname" "ambient_drip" "origin" "-110 -446 32" } { "classname" "ambient_drip" "origin" "410 1562 64" } { "origin" "42 1650 64" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-126 1986 64" } { "origin" "634 1730 64" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "834 1986 64" } { "origin" "402 1858 64" "classname" "ambient_drip" } { "targetname" "t206" "target" "t172" "origin" "-2000 -496 64" "classname" "trigger_relay" } { "targetname" "t207" "target" "t171" "classname" "trigger_relay" "origin" "-2000 -616 64" } { "light" "250" "origin" "664 -1488 224" "classname" "light" } { "origin" "544 -1464 160" "classname" "item_health" } { "origin" "560 -1528 184" "classname" "item_artifact_invisibility" } { "classname" "trigger_secret" "model" "*55" } { "classname" "item_armor1" "origin" "880 -1488 0" } //////////////////////////////////////////////// // Capture the Flag Modifications // Team 1 { "origin" "1168 1056 40" "classname" "item_flag_team1" } { "angle" "90" "origin" "1120 912 40" "classname" "info_player_team1" } { "angle" "90" "origin" "976 912 40" "classname" "info_player_team1" } { "angle" "90" "origin" "976 1200 40" "classname" "info_player_team1" } { "angle" "90" "origin" "1072 1200 40" "classname" "info_player_team1" } { "angle" "90" "origin" "1168 1200 40" "classname" "info_player_team1" } { "angle" "90" "origin" "1072 1344 40" "classname" "info_player_team1" } // Team 2 { "origin" "1170 -1490 24" "classname" "item_flag_team2" } { "angle" "180" "origin" "832 -1496 24" "classname" "info_player_team1" } { "angle" "180" "origin" "1120 -1496 24" "classname" "info_player_team2" } { "angle" "180" "origin" "1120 -1544 24" "classname" "info_player_team2" } { "angle" "180" "origin" "1120 -1448 24" "classname" "info_player_team2" } { "angle" "180" "origin" "880 -1592 24" "classname" "info_player_team2" } { "angle" "180" "origin" "880 -1592 24" "classname" "info_player_team2" } // Team 1 Base Upgrade { "classname" "weapon_supershotgun" "origin" "976 672 40" } { "classname" "weapon_supernailgun" "origin" "1168 1392 40" } { "classname" "item_spikes" "origin" "976 624 40" } { "classname" "item_spikes" "origin" "1024 624 40" } { "classname" "item_spikes" "origin" "1072 624 40" } { "classname" "item_shells" "origin" "1024 672 40" } { "classname" "item_shells" "origin" "1072 672 240" } { "classname" "item_health" "origin" "1120 624 40" } // Team 2 Base Upgrade { "classname" "weapon_supershotgun" "origin" "832 -1592 24" } { "classname" "item_spikes" "origin" "784 -1592 24" } { "classname" "item_spikes" "origin" "784 -1400 24" } { "classname" "item_shells" "origin" "1072 -1592 24" } { "classname" "item_shells" "origin" "1120 -1592 24" } { "classname" "item_shells" "origin" "1168 -1592 24" } { "classname" "item_health" "origin" "1072 -1400 24" } { "classname" "item_health" "origin" "1120 -1400 24" } { "classname" "item_health" "origin" "1168 -1400 24" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m5.ent000066400000000000000000001312041475442401000251770ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "gfx/wizard.wad" "worldtype" "0" "message" "Hell's Atrium" "sounds" "11" } { "origin" "2048 -1184 88" "angle" "180" "classname" "info_player_start" } { "light" "200" "origin" "184 -928 160" "classname" "light" } { "light" "200" "origin" "-248 -992 160" "classname" "light" } { "light" "200" "origin" "-32 -1080 160" "classname" "light" } { "light" "200" "origin" "72 -1248 176" "classname" "light" } { "light" "500" "target" "t142" "angle" "0" "origin" "288 -1216 176" "classname" "light" "style" "5" } { "light" "200" "origin" "224 -1528 176" "classname" "light" } { "origin" "-224 -1528 160" "light" "200" "classname" "light" } { "origin" "-416 -1272 160" "light" "200" "classname" "light" } { "origin" "-632 -1056 160" "light" "300" "classname" "light" } { "origin" "-480 -680 128" "light" "300" "classname" "light" } { "light" "200" "origin" "376 -1248 176" "classname" "light" } { "light" "200" "origin" "376 -1440 176" "classname" "light" } { "target" "t15" "targetname" "t14" "angle" "0" "origin" "-1472 -2624 -244" "classname" "path_corner" } { "target" "t16" "targetname" "t15" "angle" "0" "origin" "-960 -2560 -240" "classname" "path_corner" } { "target" "t17" "targetname" "t16" "angle" "0" "origin" "-960 -1920 -144" "classname" "path_corner" } { "target" "t18" "targetname" "t17" "angle" "0" "origin" "-960 -920 -256" "classname" "path_corner" } { "target" "t19" "targetname" "t18" "angle" "0" "origin" "-1472 -960 -256" "classname" "path_corner" } { "targetname" "t19" "target" "t14" "angle" "0" "origin" "-1472 -1696 -368" "classname" "path_corner" } { "angle" "0" "origin" "1248 -616 40" "classname" "light" } { "angle" "0" "origin" "1248 160 40" "classname" "light" } { "origin" "-328 -992 160" "light" "200" "classname" "light" } { "target" "t21" "targetname" "t20" "origin" "992 1184 120" "classname" "path_corner" } { "target" "t22" "targetname" "t21" "origin" "1504 1184 120" "classname" "path_corner" } { "target" "t20" "targetname" "t22" "origin" "1248 856 120" "classname" "path_corner" } { "origin" "1248 2208 184" "classname" "light" "light" "400" } { "origin" "1232 1232 96" "classname" "item_rockets" "spawnflags" "1" } { "origin" "1232 -432 8" "classname" "item_spikes" "spawnflags" "1" } { "style" "32" "origin" "-320 -1408 80" "classname" "light" "target" "t124" "targetname" "t49" } { "origin" "-56 -512 152" "classname" "item_health" "spawnflags" "1" } { "spawnflags" "1" "origin" "176 8 152" "classname" "item_spikes" } { "origin" "112 152 0" "classname" "item_shells" } { "light" "400" "origin" "960 64 -8" "classname" "light" } { "light" "400" "origin" "960 -512 -8" "classname" "light" } { "light" "400" "origin" "960 -128 -8" "classname" "light" } { "light" "400" "classname" "light" "origin" "1536 -512 -8" } { "light" "400" "classname" "light" "origin" "1536 64 -8" } { "light" "300" "origin" "1248 -288 40" "classname" "light" } { "target" "t79" "classname" "trigger_teleport" "spawnflags" "2" "model" "*1" } { "targetname" "t33" "dmg" "80" "angle" "-2" "classname" "func_door" "speed" "15" "spawnflags" "2304" "model" "*2" } { "targetname" "t33" "dmg" "80" "angle" "-2" "classname" "func_door" "speed" "15" "spawnflags" "2304" "model" "*3" } { "origin" "2384 -480 32" "classname" "item_rockets" } { "targetname" "t71" "target" "t150" "classname" "trigger_teleport" "spawnflags" "2" "model" "*4" } { "target" "t39" "classname" "trigger_once" "model" "*5" } { "style" "32" "wait" "-1" "target" "t49" "angle" "180" "classname" "func_button" "targetname" "t122" "model" "*6" } { "origin" "-960 -1696 -240" "classname" "light" } { "origin" "-1472 -1192 -352" "classname" "light" } { "origin" "-1472 -2016 -352" "classname" "light" } { "origin" "-960 -2144 -240" "classname" "light" } { "targetname" "t42" "angle" "-1" "wait" "-1" "classname" "func_door" "model" "*7" } { "target" "t43" "classname" "trigger_teleport" "spawnflags" "2" "model" "*8" } { "target" "t46" "classname" "trigger_teleport" "spawnflags" "2" "model" "*9" } { "target" "t42" "classname" "trigger_once" "model" "*10" } { "angle" "270" "targetname" "t43" "origin" "-1496 -2432 -280" "classname" "info_teleport_destination" } { "angle" "90" "targetname" "t46" "origin" "-960 -1976 -168" "classname" "info_teleport_destination" } { "origin" "-976 -880 -288" "classname" "item_health" } { "origin" "-1784 -1080 -288" "classname" "item_spikes" } { "origin" "-1408 -1616 -400" "classname" "item_health" } { "spawnflags" "1" "origin" "-1840 -1616 -400" "classname" "item_shells" } { "origin" "-1552 -2960 -288" "classname" "item_spikes" } { "origin" "-464 -1936 -96" "classname" "item_rockets" "spawnflags" "768" } { "spawnflags" "1" "origin" "-896 -1856 -176" "classname" "item_health" } { "spawnflags" "1" "origin" "-208 -912 64" "classname" "item_spikes" } { "spawnflags" "1" "origin" "-48 -1448 128" "classname" "item_rockets" } { "origin" "-32 -808 16" "classname" "light" } { "height" "144" "classname" "func_plat" "sounds" "2" "model" "*11" } { "targetname" "t48" "classname" "func_plat" "sounds" "2" "model" "*12" } { "wait" "-1" "targetname" "t49" "angle" "180" "classname" "func_door" "sounds" "1" "speed" "200" "lip" "-8" "model" "*13" } { "target" "t50" "classname" "trigger_teleport" "model" "*14" } { "origin" "-2632 -2560 -232" "classname" "light" } { "angle" "90" "targetname" "t50" "origin" "-216 -1440 168" "classname" "info_teleport_destination" } { "classname" "func_button" "angle" "-2" "wait" "-1" "target" "t48" "targetname" "t88" "sounds" "2" "model" "*15" } { "style" "33" "classname" "light" "origin" "88 -224 120" "light" "200" "target" "t125" "targetname" "t69" } { "classname" "item_spikes" "origin" "2392 8 32" } { "classname" "item_health" "origin" "-112 152 0" "spawnflags" "1" } { "classname" "item_health" "origin" "112 -504 156" "spawnflags" "2" } { "classname" "item_armor1" "origin" "-1408 -2176 -288" } { "classname" "light_flame_large_yellow" "origin" "1666 -1054 140" } { "classname" "light_flame_large_yellow" "origin" "1666 -1318 140" } { "classname" "light_flame_large_yellow" "origin" "1122 -862 140" } { "classname" "light_flame_large_yellow" "origin" "1370 -862 140" } { "classname" "light_flame_large_yellow" "origin" "-478 158 76" } { "origin" "-478 -608 76" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "444 -608 76" } { "origin" "444 158 76" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "546 158 76" } { "origin" "546 -608 76" "classname" "light_flame_large_yellow" } { "origin" "-670 -98 204" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-356 -2016 -44" } { "origin" "-868 -2656 -212" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-1380 -2976 -212" } { "origin" "-1140 -1696 -308" "classname" "light_flame_large_yellow" } { "origin" "-1822 -1056 -212" "classname" "light_flame_large_yellow" } { "origin" "-1474 -866 -212" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-1056 -1920 -124" } { "origin" "-1216 -2466 -212" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "-1378 -2274 -212" } { "classname" "light_flame_large_yellow" "origin" "-868 -866 -212" } { "classname" "light_flame_large_yellow" "origin" "-1218 -1056 -212" } { "origin" "-1056 -1248 -212" "classname" "light_flame_large_yellow" } { "classname" "info_teleport_destination" "origin" "-104 -224 160" "targetname" "t79" "angle" "0" } { "origin" "1186 -1244 140" "classname" "light_flame_large_yellow" } { "classname" "path_corner" "origin" "1312 -1184 96" "targetname" "t80" "target" "t89" } { "classname" "path_corner" "origin" "1248 -384 40" "targetname" "t82" "target" "t89" } { "origin" "-48 -464 152" "classname" "item_health" } { "origin" "16 -472 152" "classname" "item_health" } { "target" "t80" "angle" "180" "origin" "1880 -1184 88" "classname" "monster_zombie" } { "origin" "1176 1944 24" "classname" "light" } { "origin" "1320 1768 24" "classname" "light" } { "origin" "1248 888 96" "classname" "item_armor1" "target" "t155" } { "origin" "96 48 176" "classname" "monster_zombie" "angle" "315" "spawnflags" "768" } { "origin" "-40 -360 176" "classname" "monster_zombie" "angle" "90" "spawnflags" "768" } { "classname" "func_button" "angle" "90" "target" "t87" "spawnflags" "1792" "model" "*16" } { "angle" "180" "origin" "200 -736 88" "classname" "monster_zombie" } { "targetname" "t91" "target" "t90" "classname" "trigger_teleport" "spawnflags" "2" "model" "*17" } { "classname" "func_door" "angle" "-2" "lip" "32" "targetname" "t85" "sounds" "3" "model" "*18" } { "lip" "-8" "wait" "-1" "classname" "func_door" "angle" "180" "targetname" "t39" "sounds" "3" "model" "*19" } { "classname" "light_flame_large_yellow" "origin" "704 -226 108" } { "origin" "606 -226 76" "classname" "light_flame_large_yellow" } { "classname" "light" "origin" "1536 -128 -8" "light" "400" } { "classname" "light" "origin" "1032 -376 0" } { "origin" "1448 -376 0" "classname" "light" } { "origin" "1630 1118 172" "classname" "light_flame_large_yellow" "light" "350" } { "classname" "light_flame_large_yellow" "origin" "864 1118 172" "light" "350" } { "classname" "light" "origin" "1248 1784 248" } { "classname" "light" "origin" "1248 1916 248" } { "light" "500" "origin" "248 -226 204" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "56 62 220" "light" "400" } { "classname" "trigger_multiple" "target" "t33" "spawnflags" "2048" "model" "*20" } { "angle" "90" "classname" "monster_zombie" "origin" "0 -496 176" "spawnflags" "768" } { "classname" "trigger_multiple" "target" "t33" "spawnflags" "2048" "model" "*21" } { "speed" "10" "classname" "func_door" "angle" "-2" "dmg" "5000" "spawnflags" "1792" "targetname" "t87" "model" "*22" } { "origin" "1248 -1056 96" "classname" "path_corner" "targetname" "t89" "target" "t82" } { "light" "150" "origin" "168 -1192 280" "classname" "light" } { "classname" "light" "origin" "288 -1440 280" "light" "150" } { "light" "150" "origin" "112 -1008 280" "classname" "light" } { "classname" "light" "origin" "-176 -912 280" "light" "150" } { "light" "150" "origin" "-416 -1184 280" "classname" "light" } { "classname" "light" "origin" "-544 -768 280" "light" "150" } { "light" "150" "origin" "-200 -1408 264" "classname" "light" } { "classname" "light" "origin" "-448 -1472 264" "light" "150" } { "angle" "-2" "wait" "6" "target" "t85" "classname" "func_button" "targetname" "t123" "model" "*23" } { "classname" "light" "origin" "-416 -1352 160" } { "classname" "monster_zombie" "origin" "200 -784 88" "angle" "180" } { "classname" "monster_zombie" "origin" "-232 -896 88" "angle" "0" } { "angle" "90" "origin" "-152 -1504 56" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "-352 -1112 56" "angle" "0" } { "origin" "-480 -1248 56" "classname" "monster_zombie" "angle" "0" } { "angle" "180" "origin" "352 -1152 120" "classname" "monster_zombie" } { "target" "t91" "classname" "monster_zombie" "origin" "360 -1512 120" "angle" "135" } { "angle" "315" "targetname" "t90" "origin" "0 -960 192" "classname" "info_teleport_destination" } { "classname" "light" "origin" "-1536 -2816 8" "light" "200" } { "light" "200" "origin" "-1536 -2304 8" "classname" "light" } { "classname" "light" "origin" "-896 -2496 8" "light" "200" } { "classname" "monster_demon1" "origin" "-1032 -2560 -264" "angle" "0" "target" "t15" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "-952 -2008 -152" "angle" "90" "target" "t16" } { "classname" "monster_demon1" "origin" "-960 -1032 -264" "angle" "90" "target" "t17" "spawnflags" "768" } { "target" "t19" "angle" "270" "origin" "-1472 -1520 -376" "classname" "monster_demon1" } { "target" "t18" "spawnflags" "768" "angle" "180" "origin" "-1344 -960 -264" "classname" "monster_demon1" } { "spawnflags" "768" "target" "t14" "angle" "270" "origin" "-1456 -2512 -264" "classname" "monster_demon1" } { "light" "200" "origin" "-1024 -1856 40" "classname" "light" } { "light" "200" "origin" "-896 -1536 40" "classname" "light" } { "light" "200" "origin" "-1024 -1024 40" "classname" "light" } { "classname" "light" "origin" "-1664 -896 40" "light" "200" } { "origin" "-1544 -1344 8" "classname" "light" } { "origin" "-1536 -1664 -88" "classname" "light" } { "origin" "-1408 -2016 8" "classname" "light" } { "target" "t16" "angle" "270" "origin" "-1088 -720 -168" "classname" "monster_demon1" } { "classname" "monster_demon1" "origin" "-1216 -720 -168" "angle" "270" "target" "t14" } { "classname" "monster_demon1" "origin" "-1344 -720 -168" "angle" "270" "spawnflags" "768" "target" "t15" } { "classname" "trigger_teleport" "target" "t93" "spawnflags" "2" "model" "*24" } { "classname" "info_teleport_destination" "origin" "-1112 -2560 -280" "angle" "0" "targetname" "t93" } { "classname" "monster_zombie" "origin" "-448 -1984 -72" "angle" "90" } { "angle" "90" "origin" "-352 -1960 -72" "classname" "monster_zombie" "spawnflags" "768" } { "spawnflags" "768" "angle" "90" "origin" "-1280 -1056 -264" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "-864 -928 -264" "angle" "135" "spawnflags" "768" } { "angle" "45" "origin" "-1056 -1312 -264" "classname" "monster_zombie" "spawnflags" "768" } { "classname" "monster_zombie" "origin" "-1056 -1856 -152" "angle" "225" "targetname" "t132" } { "spawnflags" "768" "angle" "135" "origin" "-864 -2592 -264" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "-1272 -2456 -264" "angle" "225" "spawnflags" "768" } { "angle" "180" "origin" "168 -1064 88" "classname" "monster_zombie" "targetname" "t107" } { "angle" "180" "origin" "200 -688 88" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "136 -736 96" "angle" "180" "spawnflags" "256" } { "angle" "180" "origin" "136 -784 88" "classname" "monster_zombie" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "136 -688 88" "angle" "180" "spawnflags" "256" } { "classname" "func_button" "wait" "6" "angle" "-2" "target" "t85" "sounds" "2" "model" "*25" } { "classname" "monster_demon1" "origin" "-216 -736 104" "angle" "315" "targetname" "t91" "spawnflags" "256" } // { // "classname" "item_key1" // "origin" "-1960 -920 -56" // "sounds" "2" // } // Huh? This always appearing in Deathmatch. Commented it out { "targetname" "t155" "classname" "trigger_teleport" "target" "t120" "model" "*26" } { "classname" "info_teleport_destination" "origin" "1248 568 248" "angle" "90" "targetname" "t120" } { "origin" "2458 -100 100" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "2458 -350 100" } { "style" "35" "wait" "-1" "lip" "4" "target" "t23" "spawnflags" "2064" "angle" "90" "classname" "func_door" "model" "*27" } { "origin" "584 -48 0" "classname" "item_health" } { "classname" "item_health" "origin" "584 -432 0" } { "light" "200" "origin" "0 0 104" "classname" "light" } { "light" "200" "classname" "light" "origin" "0 -448 104" } { "light" "200" "origin" "192 -256 104" "classname" "light" } { "light" "200" "classname" "light" "origin" "-160 -224 104" } { "light" "200" "origin" "-552 -104 64" "classname" "light" } { "light" "200" "origin" "1528 -280 192" "classname" "light" } { "origin" "2184 -232 144" "classname" "light" } { "classname" "light" "origin" "-104 -648 152" "light" "200" } { "classname" "light" "origin" "-216 -1304 152" } { "classname" "light" "origin" "128 8 192" "light" "120" } { "light" "120" "origin" "-128 24 192" "classname" "light" } { "classname" "light" "origin" "-160 -448 192" "light" "200" } { "light" "150" "origin" "-48 -424 192" "classname" "light" } { "classname" "light" "origin" "-512 -1608 128" "light" "200" } { "classname" "info_null" "origin" "-492 -1440 72" "targetname" "t124" } { "classname" "info_null" "origin" "28 -220 28" "targetname" "t125" } { "style" "34" "classname" "light" "origin" "2432 -256 120" "target" "t126" "targetname" "t71" } { "classname" "info_null" "origin" "2464 -224 40" "targetname" "t126" } { "style" "35" "classname" "light" "origin" "1088 1600 192" "target" "t127" "targetname" "t23" } { "classname" "info_null" "origin" "1124 1644 140" "targetname" "t127" } { "light" "150" "origin" "32 -224 112" "classname" "light" } { "origin" "-1232 -888 -288" "classname" "item_spikes" } { "spawnflags" "768" "angle" "225" "origin" "-1376 -2208 -264" "classname" "monster_zombie" } { "origin" "-608 -1840 56" "classname" "light" } { "origin" "-784 -1920 -120" "classname" "monster_demon1" "spawnflags" "768" "angle" "0" } { "origin" "-1728 -1696 -400" "classname" "item_health" } { "classname" "item_health" "origin" "-1152 -1520 -400" } { "spawnflags" "1" "origin" "-1720 -1576 -400" "classname" "item_spikes" } { "light" "120" "origin" "1464 1472 200" "classname" "light" } { "classname" "light" "origin" "1032 1472 200" "light" "200" } { "light" "150" "origin" "1224 840 224" "classname" "light" } { "classname" "light" "origin" "1280 856 104" "light" "150" } { "classname" "light_flame_large_yellow" "origin" "1248 320 172" } { "origin" "1424 312 96" "classname" "item_health" } { "classname" "light_flame_large_yellow" "origin" "864 412 172" } { "origin" "864 514 172" "classname" "light_flame_large_yellow" "light" "400" } { "origin" "1630 412 172" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "1630 514 172" "light" "400" } { "origin" "2018 -608 76" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "2018 158 76" } { "origin" "1916 158 76" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "1916 -608 76" } { "origin" "1758 -226 108" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "1856 -226 76" } { "classname" "item_health" "origin" "1840 -48 0" } { "origin" "1840 -432 0" "classname" "item_health" } { "targetname" "t71" "target" "t129" "classname" "trigger_teleport" "spawnflags" "2" "model" "*28" } { "origin" "2268 158 92" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "2268 -608 92" } { "targetname" "t129" "classname" "info_teleport_destination" "origin" "2064 -360 136" "angle" "45" } { "origin" "1248 0 168" "classname" "light" } { "classname" "item_artifact_super_damage" "origin" "-128 -480 180" } { "classname" "item_artifact_super_damage" "origin" "1320 840 120" } { "classname" "item_health" "origin" "1040 312 96" } { "classname" "light" "origin" "1992 -1184 136" } { "classname" "trigger_once" "target" "t132" "model" "*29" } { "classname" "light" "origin" "1248 1376 200" "light" "200" } { "light" "200" "origin" "1248 1536 200" "classname" "light" } { "classname" "light" "origin" "-1800 -2560 -232" } { "wait" "-1" "speed" "300" "lip" "32" "targetname" "t133" "sounds" "3" "angle" "180" "classname" "func_door" "model" "*30" } { "target" "t133" "classname" "trigger_once" "model" "*31" } { "targetname" "t133" "angle" "90" "origin" "-2096 -2808 -264" "classname" "monster_demon1" } { "targetname" "t133" "classname" "monster_demon1" "origin" "-1936 -2312 -264" "angle" "270" } { "target" "t137" "wait" "-1" "sounds" "1" "angle" "270" "classname" "func_button" "model" "*32" } { "target" "t137" "classname" "func_button" "angle" "90" "sounds" "1" "wait" "-1" "model" "*33" } { "target" "t138" "targetname" "t137" "classname" "trigger_counter" "model" "*34" } { "light" "150" "origin" "1472 832 176" "classname" "light" } { "classname" "light" "origin" "1024 832 176" "light" "150" } { "light" "150" "origin" "1632 376 144" "classname" "light" } { "angle" "180" "origin" "1656 356 132" "classname" "trap_spikeshooter" "targetname" "t68" } { "classname" "trigger_multiple" "wait" "0.5" "target" "t68" "model" "*35" } { "classname" "trap_spikeshooter" "origin" "904 420 128" "angle" "0" "targetname" "t68" } { "classname" "trigger_once" "target" "t71" "model" "*36" } { "classname" "monster_zombie" "origin" "2040 -184 24" "angle" "180" } { "origin" "2160 -96 24" "classname" "monster_zombie" "angle" "225" } { "classname" "monster_zombie" "origin" "2160 -352 24" "angle" "135" } { "origin" "2064 -448 24" "classname" "monster_zombie" "angle" "135" } { "classname" "monster_zombie" "origin" "2304 56 40" "angle" "225" } { "classname" "monster_zombie" "origin" "2048 56 24" "angle" "270" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "4" "lip" "-104" "targetname" "t23" "speed" "300" "spawnflags" "2048" "model" "*37" } { "targetname" "t141" "classname" "func_door_secret" "angle" "0" "spawnflags" "257" "model" "*38" } { "classname" "item_artifact_invisibility" "origin" "352 -1648 120" } { "targetname" "t142" "origin" "288 -1092 176" "classname" "info_null" } { "targetname" "t143" "origin" "-240 -64 192" "classname" "info_null" } { "style" "36" "targetname" "t144" "target" "t143" "origin" "-320 -64 192" "classname" "light" } { "style" "36" "wait" "-1" "target" "t144" "sounds" "1" "angle" "0" "classname" "func_door" "health" "1" "model" "*39" } { "spawnflags" "32" "targetname" "t144" "sounds" "3" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*40" } { "classname" "light_flame_large_yellow" "origin" "-670 -352 204" } { "origin" "-368 -320 104" "classname" "light" "light" "200" } { "angle" "315" "origin" "-160 -16 176" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "trigger_once" "target" "t145" "model" "*41" } { "classname" "light" "origin" "1824 -1448 128" "light" "150" } { "lip" "-8" "wait" "-1" "speed" "400" "angle" "0" "classname" "func_door" "targetname" "t145" "model" "*42" } { "angle" "90" "origin" "1792 -1408 88" "classname" "monster_hell_knight" "targetname" "t145" } { "spawnflags" "256" "angle" "90" "origin" "1856 -1408 88" "classname" "monster_hell_knight" "targetname" "t145" } { "spawnflags" "1" "classname" "item_spikes" "origin" "1232 1120 96" } { "spawnflags" "2048" "classname" "weapon_supernailgun" "origin" "-32 -896 64" } { "classname" "weapon_lightning" "origin" "-1168 -1600 -400" "spawnflags" "2048" } { "classname" "light_flame_large_yellow" "origin" "-1762 -1506 -308" } { "classname" "light" "origin" "-2464 -1416 -200" "light" "200" } { "classname" "light" "origin" "-2552 -1600 -200" "light" "200" } { "classname" "light" "origin" "-2720 -1736 -200" "light" "200" } { "classname" "light" "origin" "-2968 -1856 -200" "light" "200" } { "classname" "light" "light" "300" "origin" "-2528 -1032 -200" } { "classname" "light" "origin" "-2720 -1976 -200" "light" "200" } { "classname" "light" "origin" "-2912 -1976 -200" "light" "200" } { "classname" "light" "light" "200" "origin" "-2464 -1272 -200" } { "classname" "item_spikes" "origin" "-2744 -1608 -272" } { "light" "200" "origin" "-2400 -2008 -200" "classname" "light" } { "classname" "light" "origin" "-2152 -1888 -200" "light" "200" } { "light" "200" "origin" "-2208 -1416 -200" "classname" "light" } { "classname" "light" "origin" "-2112 -1600 -232" } { "classname" "monster_hell_knight" "origin" "1104 1152 120" "target" "t20" } { "origin" "1344 1216 120" "classname" "monster_hell_knight" "target" "t21" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "1296 928 120" "target" "t22" "spawnflags" "768" } { "classname" "light" "origin" "-1832 -872 -24" "light" "200" } { "light" "200" "origin" "-1832 -1048 -24" "classname" "light" } { "classname" "light" "origin" "-1928 -1096 -32" "light" "200" } { "classname" "light" "origin" "-1792 -1216 -96" "light" "200" } { "light" "200" "origin" "-1856 -1344 -192" "classname" "light" } { "classname" "light" "origin" "-2208 -1272 -200" "light" "200" } { "classname" "func_wall" "spawnflags" "2048" "model" "*43" } { "spawnflags" "2048" "classname" "func_wall" "model" "*44" } { "classname" "func_wall" "spawnflags" "2048" "model" "*45" } { "angle" "225" "origin" "-1696 -1184 -160" "classname" "monster_hell_knight" "spawnflags" "256" } { "classname" "light" "origin" "-2264 -1632 -200" "light" "200" } { "light" "200" "origin" "-2376 -1632 -200" "classname" "light" } { "light" "200" "origin" "-2912 -1440 -96" "classname" "light" } { "classname" "light" "origin" "-2896 -1656 -232" "style" "2" } { "classname" "item_artifact_invulnerability" "origin" "-2944 -1632 -264" } { "classname" "item_armor2" "origin" "-2848 -1632 -288" } { "light" "200" "origin" "-2144 -1032 -200" "classname" "light" } { "origin" "-2712 -1152 -200" "light" "300" "classname" "light" } { "classname" "func_plat" "sounds" "2" "model" "*46" } { "classname" "light" "origin" "-3160 -1560 -120" "light" "200" } { "classname" "light" "origin" "-3144 -1832 -224" "light" "200" } { "classname" "func_door" "angle" "270" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t149" "model" "*47" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "180" "classname" "func_door" "targetname" "t149" "model" "*48" } { "classname" "func_door" "angle" "180" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t149" "model" "*49" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "0" "classname" "func_door" "targetname" "t149" "model" "*50" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "90" "classname" "func_door" "targetname" "t149" "model" "*51" } { "classname" "func_door" "angle" "180" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t149" "model" "*52" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "180" "classname" "func_door" "targetname" "t149" "model" "*53" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "180" "classname" "func_door" "targetname" "t149" "model" "*54" } { "classname" "func_door" "angle" "90" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t149" "model" "*55" } { "classname" "func_door" "angle" "180" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t147" "model" "*56" } { "sounds" "4" "wait" "-1" "lip" "-8" "angle" "180" "classname" "func_door" "targetname" "t147" "model" "*57" } { "classname" "func_door" "angle" "270" "lip" "-8" "wait" "-1" "sounds" "4" "targetname" "t147" "model" "*58" } { "angle" "315" "origin" "-2856 -1688 -136" "classname" "monster_hell_knight" "targetname" "t149" "spawnflags" "256" } { "classname" "monster_zombie" "origin" "-2720 -1648 -248" "angle" "270" "targetname" "t149" } { "angle" "0" "origin" "-2640 -1600 -248" "classname" "monster_zombie" "targetname" "t149" } { "classname" "monster_zombie" "origin" "-2720 -2072 -248" "angle" "90" "targetname" "t149" } { "angle" "90" "origin" "-2912 -2072 -248" "classname" "monster_zombie" "targetname" "t149" } { "angle" "90" "origin" "-2400 -2088 -248" "classname" "monster_zombie" "targetname" "t149" } { "classname" "monster_zombie" "origin" "-2072 -1888 -248" "angle" "180" "targetname" "t149" } { "classname" "monster_zombie" "origin" "-2800 -1152 -248" "angle" "0" "targetname" "t147" } { "classname" "monster_zombie" "origin" "-2528 -944 -248" "angle" "270" "targetname" "t147" } { "classname" "item_health" "origin" "-2544 -904 -272" } { "classname" "item_artifact_super_damage" "origin" "-2720 -2120 -248" } { "classname" "item_cells" "origin" "-2912 -1584 -288" "spawnflags" "1" } { "classname" "trigger_secret" "model" "*59" } { "classname" "item_health" "origin" "-2872 -1168 -272" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-2160 -904 -272" } { "classname" "item_cells" "origin" "-1664 -1208 -184" } { "classname" "item_health" "origin" "-1968 -1208 -120" "spawnflags" "1" } { "classname" "trigger_secret" "model" "*60" } { "classname" "info_teleport_destination" "origin" "2072 -80 136" "angle" "315" "targetname" "t150" } { "classname" "light" "origin" "1248 704 136" "light" "150" } { "light" "150" "origin" "1248 872 136" "classname" "light" } { "classname" "light" "origin" "192 -192 168" "light" "150" } { "classname" "item_cells" "origin" "-2296 -1416 -160" "spawnflags" "1" } { "classname" "func_door" "angle" "-1" "health" "1" "wait" "-1" "sounds" "3" "model" "*61" } { "classname" "light" "origin" "928 400 136" "light" "170" } { "classname" "light" "origin" "1248 -512 168" } { "classname" "item_cells" "origin" "-1816 -1808 -168" } { "light" "250" "origin" "-1664 -1792 -120" "classname" "light" } { "classname" "light" "origin" "-1920 -1984 -120" "light" "200" } { "classname" "light" "origin" "-1936 -2272 -184" "light" "150" } { "light" "150" "origin" "-2096 -2848 -184" "classname" "light" } { "classname" "light" "origin" "-2304 -2440 -376" "light" "150" } { "light" "200" "origin" "-2304 -2680 -376" "classname" "light" } { "classname" "trigger_secret" "model" "*62" } { "spawnflags" "1" "classname" "item_cells" "origin" "-1120 -2680 -104" } { "classname" "light" "origin" "-2624 -2688 -376" "light" "150" } { "light" "150" "origin" "-2624 -2432 -376" "classname" "light" } { "classname" "light" "origin" "-2176 -2432 -280" "light" "150" } { "light" "150" "origin" "-1920 -2688 -280" "classname" "light" } { "classname" "light" "origin" "-2904 -1552 -96" } { "classname" "weapon_rocketlauncher" "origin" "-1960 -968 -80" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "-1224 -968 -288" "spawnflags" "1792" } { "classname" "weapon_lightning" "origin" "-2896 -1616 -288" "spawnflags" "1792" } { "classname" "monster_hell_knight" "origin" "-80 -1280 56" "targetname" "t39" "angle" "180" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "-80 -1168 56" "targetname" "t39" "spawnflags" "256" "angle" "180" } { "classname" "item_artifact_invulnerability" "origin" "-432 -752 56" } { "classname" "item_rockets" "origin" "-1232 -2672 -288" "spawnflags" "768" } { "classname" "light" "origin" "-152 -360 200" "light" "150" } { "classname" "light" "origin" "120 -392 200" "light" "150" } { "classname" "item_key2" "origin" "2464 -224 56" "sounds" "2" "spawnflags" "2048" } { "classname" "func_door" "angle" "90" "spawnflags" "2056" "sounds" "4" "wait" "-1" "model" "*63" } { "classname" "func_door" "spawnflags" "2056" "wait" "-1" "sounds" "4" "angle" "270" "model" "*64" } { "classname" "func_button" "angle" "-2" "wait" "-1" "sounds" "1" "target" "t153" "model" "*65" } { "classname" "trigger_once" "target" "t149" "delay" "1" "targetname" "t153" "model" "*66" } { "classname" "monster_tarbaby" "origin" "-2464 -1504 -264" "angle" "270" "spawnflags" "257" } { "classname" "monster_tarbaby" "origin" "712 248 120" "targetname" "t155" } { "classname" "monster_tarbaby" "origin" "-1184 -1536 -376" "angle" "180" "spawnflags" "257" } { "style" "37" "classname" "light" "origin" "-1584 -2408 -216" "spawnflags" "1" "targetname" "t133" } { "classname" "monster_tarbaby" "origin" "-1664 -2656 -264" "spawnflags" "1" "angle" "45" } { "classname" "monster_tarbaby" "origin" "-384 -1824 -72" "spawnflags" "257" "angle" "135" } { "classname" "monster_tarbaby" "origin" "-1160 -960 -264" "spawnflags" "1" "angle" "0" } { "classname" "monster_tarbaby" "origin" "-352 -576 248" "angle" "45" "spawnflags" "257" } { "spawnflags" "768" "angle" "180" "origin" "2584 -288 120" "classname" "monster_tarbaby" } { "angle" "180" "origin" "2584 -232 120" "classname" "monster_tarbaby" } { "spawnflags" "256" "angle" "135" "origin" "2304 -504 40" "classname" "monster_hell_knight" } { "origin" "1232 1520 96" "classname" "item_spikes" } { "wait" "-1" "angle" "180" "sounds" "1" "targetname" "t138" "classname" "func_door" "spawnflags" "1" "model" "*67" } { "spawnflags" "768" "angle" "270" "origin" "-1952 -1824 -144" "classname" "monster_hell_knight" } { "angle" "135" "origin" "-1664 -1984 -144" "classname" "monster_hell_knight" "spawnflags" "256" } { "style" "37" "targetname" "t133" "spawnflags" "1" "origin" "-1584 -2712 -216" "classname" "light" } { "angle" "315" "origin" "-1704 -880 -264" "classname" "monster_tarbaby" } { "spawnflags" "256" "angle" "315" "origin" "976 -720 88" "classname" "monster_tarbaby" } { "classname" "monster_tarbaby" "origin" "1520 -720 88" "angle" "225" "spawnflags" "256" } { "angle" "270" "origin" "-416 96 24" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "2000 -1064 88" "classname" "info_player_deathmatch" } { "angle" "315" "origin" "2096 112 24" "classname" "info_player_deathmatch" } { "angle" "180" "origin" "1408 1376 120" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "224 -1464 120" "classname" "info_player_deathmatch" } { "angle" "90" "origin" "-1440 -2976 -264" "classname" "info_player_deathmatch" } { "angle" "45" "origin" "-2672 -1256 -296" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "200 -1280 96" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "-384 -792 32" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "712 -128 0" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "-1240 -1600 -400" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "1248 -1184 64" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "2272 -216 16" "classname" "item_armorInv" } { "spawnflags" "1792" "origin" "1248 1072 96" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "-168 32 152" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "classname" "func_wall" "model" "*68" } { "origin" "-1344 -2680 -104" "classname" "item_cells" } { "classname" "func_door" "angle" "90" "wait" "-1" "targetname" "t23" "spawnflags" "2049" "model" "*69" } { "classname" "trigger_changelevel" "map" "e4m8" "model" "*70" } { "classname" "trigger_changelevel" "map" "e4m6" "model" "*71" } { "classname" "light" "origin" "-2528 -2536 -376" "light" "150" } { "light" "150" "origin" "-2400 -2600 -376" "classname" "light" } { "classname" "monster_fish" "origin" "-2640 -2704 -416" "angle" "45" "target" "t158" "spawnflags" "256" } { "classname" "path_corner" "origin" "-2608 -2672 -416" "targetname" "t158" "target" "t159" } { "origin" "-2296 -2424 -416" "classname" "path_corner" "targetname" "t159" "target" "t158" } { "classname" "monster_fish" "origin" "-2296 -2704 -336" "angle" "135" "target" "t160" "spawnflags" "256" } { "classname" "path_corner" "origin" "-2320 -2680 -336" "targetname" "t160" "target" "t161" } { "origin" "-2640 -2416 -336" "classname" "path_corner" "targetname" "t161" "target" "t160" } { "classname" "item_health" "origin" "-1392 -1936 -104" } { "classname" "trigger_secret" "model" "*72" } { "classname" "path_corner" "origin" "-2528 -2408 -336" "targetname" "t163" "target" "t164" } { "origin" "-2296 -2616 -336" "classname" "path_corner" "targetname" "t164" "target" "t163" } { "angle" "135" "origin" "-2264 -2640 -336" "classname" "monster_fish" "target" "t164" "spawnflags" "256" } { "classname" "path_corner" "origin" "-2552 -2696 -416" "targetname" "t165" "target" "t166" } { "origin" "-2296 -2504 -416" "classname" "path_corner" "targetname" "t166" "target" "t165" } { "classname" "monster_fish" "origin" "-2512 -2672 -408" "angle" "225" "target" "t165" "spawnflags" "256" } { "classname" "item_artifact_super_damage" "origin" "-2560 -2496 -424" } { "classname" "item_cells" "origin" "-2384 -2712 -448" } { "height" "250" "speed" "300" "angle" "180" "classname" "trigger_monsterjump" "model" "*73" } { "classname" "trigger_monsterjump" "angle" "180" "speed" "300" "height" "250" "model" "*74" } { "angle" "135" "classname" "trigger_monsterjump" "speed" "400" "height" "600" "model" "*75" } { "angle" "90" "classname" "trigger_monsterjump" "model" "*76" } { "angle" "90" "classname" "trigger_monsterjump" "model" "*77" } { "spawnflags" "2050" "origin" "1920 -1200 64" "classname" "item_health" } { "target" "t168" "angle" "180" "origin" "2632 -40 120" "classname" "monster_shalrath" } { "target" "t20" "classname" "monster_shalrath" "origin" "2632 -152 120" "angle" "180" } { "target" "t167" "classname" "trigger_teleport" "spawnflags" "2" "model" "*78" } { "target" "t120" "classname" "trigger_teleport" "spawnflags" "2" "model" "*79" } { "target" "t169" "targetname" "t168" "origin" "800 -616 40" "classname" "path_corner" } { "target" "t168" "targetname" "t169" "classname" "path_corner" "origin" "800 160 40" } { "angle" "270" "targetname" "t167" "origin" "800 64 8" "classname" "info_teleport_destination" } { "targetname" "t68" "angle" "-1" "classname" "func_door" "model" "*80" } { "targetname" "t133" "classname" "func_door" "angle" "-1" "model" "*81" } { "targetname" "t170" "angle" "270" "spawnflags" "256" "origin" "1248 1616 120" "classname" "monster_demon1" } { "spawnflags" "768" "targetname" "t23" "angle" "135" "origin" "1448 2112 120" "classname" "monster_shalrath" } { "classname" "trigger_monsterjump" "angle" "135" "height" "400" "speed" "400" "model" "*82" } { "classname" "monster_shalrath" "origin" "328 -1592 120" "angle" "90" "spawnflags" "256" } { "mangle" "15 185 0" "origin" "-944 -864 0" "classname" "info_intermission" } { "origin" "16 -1416 32" "classname" "item_health" } { "spawnflags" "1" "origin" "16 -1496 32" "classname" "item_spikes" } { "targetname" "t171" "message" "Are you sure you want to exit now? \n You left behind something important." "wait" "2" "angle" "90" "classname" "trigger_multiple" "spawnflags" "2048" "model" "*83" } { "mangle" "20 135 0" "origin" "1728 -560 176" "classname" "info_intermission" } { "mangle" "20 320 0" "origin" "2048 0 208" "classname" "info_intermission" } { "mangle" "0 315 0" "origin" "-576 -736 208" "classname" "info_intermission" } { "classname" "func_door" "angle" "-2" "wait" "-1" "targetname" "t39" "model" "*84" } { "targetname" "t39" "classname" "trigger_teleport" "spawnflags" "2" "target" "t173" "model" "*85" } { "targetname" "t39" "spawnflags" "2" "classname" "trigger_teleport" "target" "t175" "model" "*86" } { "targetname" "t39" "classname" "trigger_teleport" "spawnflags" "2" "target" "t176" "model" "*87" } { "targetname" "t39" "spawnflags" "2" "classname" "trigger_teleport" "target" "t50" "model" "*88" } { "targetname" "t39" "classname" "trigger_teleport" "spawnflags" "2" "target" "t90" "model" "*89" } { "targetname" "t39" "spawnflags" "2" "classname" "trigger_teleport" "target" "t174" "model" "*90" } { "classname" "info_teleport_destination" "origin" "-32 -736 136" "angle" "270" "targetname" "t173" } { "classname" "info_teleport_destination" "origin" "-64 -960 192" "angle" "225" "targetname" "t174" } { "classname" "info_teleport_destination" "origin" "-200 -1208 144" "angle" "180" "targetname" "t175" } { "classname" "info_teleport_destination" "origin" "136 -1136 136" "angle" "135" "targetname" "t176" } { "classname" "info_teleport_destination" "origin" "1248 1024 104" "angle" "90" "targetname" "t177" } { "wait" "-1" "sounds" "3" "angle" "270" "spawnflags" "2064" "classname" "func_door" "model" "*91" } { "classname" "weapon_grenadelauncher" "origin" "2160 -224 0" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "1248 -792 64" "spawnflags" "1792" } { "classname" "weapon_supernailgun" "origin" "1248 1128 96" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-352 -480 0" "spawnflags" "1792" } { "classname" "info_player_coop" "origin" "1952 -1120 88" "angle" "180" } { "angle" "180" "origin" "1952 -1248 88" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "2016 -1312 88" "angle" "180" } { "classname" "weapon_grenadelauncher" "origin" "-456 -1848 -96" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "-920 -1248 -288" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-1544 -2656 -288" "spawnflags" "1792" } { "classname" "item_artifact_invulnerability" "origin" "-2448 -2608 -424" "spawnflags" "1792" } { "classname" "func_door" "angle" "180" "wait" "-1" "sounds" "3" "model" "*92" } { "angle" "0" "classname" "func_door" "wait" "-1" "sounds" "3" "model" "*93" } { "classname" "func_door" "spawnflags" "2064" "angle" "90" "sounds" "3" "wait" "-1" "model" "*94" } { "classname" "trigger_teleport" "target" "t178" "model" "*95" } { "classname" "info_null" "origin" "796 2212 260" "targetname" "t178" } { "classname" "light" "origin" "880 2216 184" "light" "250" } { "classname" "item_cells" "origin" "-496 -816 32" "spawnflags" "1" } { "classname" "item_cells" "origin" "-112 32 152" } { "classname" "item_spikes" "origin" "1808 -1464 64" "spawnflags" "1" } { "classname" "trigger_once" "health" "1" "target" "t141" "model" "*96" } { "classname" "item_spikes" "origin" "288 -1664 96" "spawnflags" "1" } { "classname" "light" "origin" "328 -1656 152" "light" "150" } { "classname" "item_artifact_super_damage" "origin" "-448 -1776 -72" } { "classname" "light" "origin" "-448 -1776 -8" "light" "150" } { "classname" "item_cells" "origin" "-920 -1936 -176" } { "classname" "monster_hell_knight" "origin" "-1896 -960 -56" "angle" "0" "spawnflags" "256" } { "classname" "item_cells" "origin" "-1776 -1616 -400" "spawnflags" "1" } { "classname" "light" "origin" "-2720 -2104 -248" "light" "150" } { "classname" "item_cells" "origin" "-2928 -2136 -272" } { "classname" "func_wall" "spawnflags" "1792" "model" "*97" } { "classname" "func_wall" "spawnflags" "1792" "model" "*98" } { "origin" "-1928 -952 -8" "classname" "light" } { "classname" "item_spikes" "origin" "-1584 -2208 -288" "spawnflags" "769" } { "classname" "item_shells" "origin" "-2464 -1760 -288" "spawnflags" "1" } { "classname" "item_rockets" "origin" "-2096 -1264 -320" "spawnflags" "1" } { "classname" "item_shells" "origin" "-1904 -1216 -120" } { "classname" "trigger_once" "target" "t171" "killtarget" "t171" "model" "*99" } { "origin" "1250 786 172" "classname" "light_flame_large_yellow" } { "classname" "item_spikes" "origin" "2064 -240 0" "spawnflags" "2816" } { "classname" "item_rockets" "origin" "696 -336 0" } { "classname" "func_wall" "spawnflags" "1792" "model" "*100" } { "classname" "item_spikes" "origin" "-32 -1280 32" } { "classname" "item_health" "origin" "-32 -1184 32" "spawnflags" "1" } { "angle" "135" "origin" "-1056 -1984 -152" "classname" "monster_zombie" "targetname" "t132" } { "classname" "monster_shalrath" "origin" "-608 64 24" "targetname" "t33" } { "classname" "monster_tarbaby" "origin" "-3064 -1848 -264" "spawnflags" "768" "angle" "0" "targetname" "t149" } { "classname" "monster_tarbaby" "origin" "-2936 -1592 -264" "angle" "90" "spawnflags" "257" } { "origin" "962 -542 96" "classname" "ambient_swamp1" } { "classname" "ambient_swamp1" "origin" "1538 -550 96" } { "origin" "962 106 96" "classname" "ambient_swamp2" } { "origin" "-2302 -2558 -256" "classname" "ambient_drip" } { "classname" "ambient_swamp2" "origin" "1538 106 96" } { "spawnflags" "768" "origin" "2432 -440 32" "classname" "item_rockets" } { "origin" "-2704 -1608 -272" "classname" "item_rockets" } { "origin" "-2416 -2152 -272" "classname" "item_rockets" } { "origin" "-2040 -1904 -272" "classname" "item_rockets" } { "target" "t147" "spawnflags" "1" "origin" "-2736 -1040 -272" "classname" "item_cells" } { "targetname" "t147" "angle" "270" "origin" "-2144 -944 -248" "classname" "monster_tarbaby" } { "spawnflags" "768" "origin" "-1944 -1240 -96" "classname" "monster_tarbaby" } { "classname" "item_cells" "origin" "-2208 -1632 -288" "spawnflags" "1" } { "classname" "item_artifact_invisibility" "origin" "1248 480 120" } ///////////////////////////////////////////////// // Capture the Flag Changes. // team1 { "origin" "1245 2370 120" "classname" "item_flag_team1" "angle" "90" } { "angle" "270" "origin" "1400 2335 120" "classname" "info_player_team1" } { "angle" "270" "origin" "1400 2230 120" "classname" "info_player_team1" } { "angle" "270" "origin" "1245 2230 120" "classname" "info_player_team1" } { "angle" "270" "origin" "1110 2230 120" "classname" "info_player_team1" } { "angle" "270" "origin" "1110 2370 120" "classname" "info_player_team1" } { "angle" "270" "origin" "1245 2300 120" "classname" "info_player_team1" } // team2 { "origin" "-2944 -1856 -264" "classname" "item_flag_team2" } { "angle" "0" "origin" "-2765 -1760 -264" "classname" "info_player_team2" } { "angle" "0" "origin" "-2960 -1760 -264" "classname" "info_player_team2" } { "angle" "0" "origin" "-2986 -1950 -264" "classname" "info_player_team2" } { "angle" "0" "origin" "-2765 -1960 -264" "classname" "info_player_team2" } { "angle" "0" "origin" "-2725 -1875 -264" "classname" "info_player_team2" } { "angle" "0" "origin" "-2725 -1950 -264" "classname" "info_player_team2" } // BASE1 UPGRADE { "classname" "weapon_supershotgun" "origin" "1376 2272 120" } { "classname" "weapon_supernailgun" "origin" "1168 2272 120" } { "classname" "item_armor2" "origin" "1072 2064 120" } { "classname" "item_shells" "origin" "1072 2224 120" } { "classname" "item_shells" "origin" "1072 2320 120" } { "classname" "item_shells" "origin" "1072 2272 120" } { "classname" "item_spikes" "origin" "1120 2224 120" } { "classname" "item_spikes" "origin" "1120 2320 120" } { "classname" "item_spikes" "origin" "1120 2272 120" } { "classname" "item_health" "origin" "1424 2224 120" } { "classname" "item_health" "origin" "1424 2320 120" } { "classname" "item_health" "origin" "1424 2272 120" } // BASE2 Upgrade { "classname" "item_spikes" "origin" "-2944 -1952 -264" "angle" "180" } { "classname" "item_spikes" "origin" "-2896 -1952 -264" "angle" "180" } { "classname" "item_spikes" "origin" "-2848 -1952 -264" "angle" "180" } { "classname" "item_shells" "origin" "-2944 -1904 -264" "angle" "180" } { "classname" "item_shells" "origin" "-2896 -1904 -264" "angle" "180" } { "classname" "item_health" "origin" "-2944 -1760 -264" } { "classname" "item_health" "origin" "-2896 -1760 -264" } { "classname" "item_health" "origin" "-2848 -1760 -264" } { "classname" "item_armor2" "origin" "-2752 -1856 -264" "angle" "180" } { "classname" "weapon_supernailgun" "origin" "-2752 -1904 -264" } { "classname" "weapon_supershotgun" "origin" "-2752 -1808 -264" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m6.ent000066400000000000000000001242221475442401000252020ustar00rootroot00000000000000{ "worldtype" "0" "classname" "worldspawn" "wad" "gfx/wizard.wad" "message" "The Pain Maze" "sounds" "4" } { "classname" "light" "origin" "-160 -1392 96" } { "classname" "light" "origin" "32 -1392 96" } { "classname" "light" "origin" "480 -1392 96" } { "classname" "light" "origin" "672 -1392 96" } { "classname" "light" "origin" "-240 -1120 96" } { "classname" "light" "origin" "752 -1120 96" } { "classname" "light" "origin" "456 -480 288" "angle" "0" "light" "400" } { "classname" "light" "origin" "56 -480 288" "angle" "0" "light" "400" } { "classname" "light" "origin" "56 -672 288" "angle" "0" "light" "400" } { "classname" "light" "origin" "456 -672 288" "angle" "0" "light" "400" } { "light" "150" "classname" "light" "origin" "392 -672 320" } { "light" "150" "classname" "light" "origin" "392 -480 320" } { "light" "150" "classname" "light" "origin" "120 -480 320" } { "light" "150" "classname" "light" "origin" "120 -672 320" } { "classname" "info_player_deathmatch" "origin" "368 -896 184" "angle" "135" } { "light" "150" "classname" "light" "origin" "392 -672 192" } { "light" "150" "classname" "light" "origin" "392 -480 192" } { "classname" "light" "origin" "456 -480 192" "angle" "0" "light" "300" } { "classname" "light" "origin" "456 -672 192" "angle" "0" "light" "300" } { "light" "150" "classname" "light" "origin" "120 -672 192" } { "light" "150" "classname" "light" "origin" "120 -480 192" } { "classname" "light" "origin" "56 -480 192" "angle" "0" "light" "300" } { "classname" "light" "origin" "56 -672 192" "angle" "0" "light" "300" } { "classname" "info_player_deathmatch" "origin" "-336 1824 200" "angle" "315" } { "classname" "light" "origin" "1336 128 280" "angle" "0" } { "wait" "5" "classname" "func_plat" "model" "*1" } { "classname" "light_torch_small_walltorch" "origin" "682 -238 212" "light" "300" } { "classname" "light" "origin" "-64 -328 168" "light" "200" } { "spawnflags" "1" "classname" "light" "origin" "704 -672 -8" "light" "200" } { "sounds" "4" "wait" "-1" "classname" "func_door" "angle" "0" "model" "*2" } { "target" "t12" "classname" "trigger_teleport" "spawnflags" "2" "model" "*3" } { "target" "t11" "classname" "trigger_teleport" "spawnflags" "2" "model" "*4" } { "angle" "-1" "wait" "-1" "targetname" "t10" "classname" "func_door" "model" "*5" } { "classname" "item_health" "origin" "728 -1272 16" "spawnflags" "1" } { "classname" "item_health" "origin" "728 -1000 16" "spawnflags" "1" } { "classname" "item_health" "origin" "80 -1008 16" "spawnflags" "1" } { "classname" "item_armor1" "origin" "-32 -736 0" } { "classname" "item_health" "origin" "152 -368 144" } { "classname" "item_health" "origin" "328 -368 144" } { "classname" "item_health" "origin" "272 1544 0" } { "classname" "item_health" "origin" "432 1872 176" } { "spawnflags" "1" "classname" "item_shells" "origin" "464 1544 0" } { "classname" "item_rockets" "origin" "-496 1424 176" } { "spawnflags" "1" "classname" "item_health" "origin" "1520 464 0" } { "spawnflags" "1" "classname" "item_shells" "origin" "1528 144 0" } { "targetname" "t11" "origin" "-160 -1104 24" "classname" "info_teleport_destination" } { "targetname" "t12" "origin" "-16 -1296 24" "classname" "info_teleport_destination" } { "target" "t14" "targetname" "t13" "origin" "-160 -1232 40" "classname" "path_corner" } { "target" "t80" "targetname" "t17" "origin" "16 -1152 40" "classname" "path_corner" } { "target" "t13" "targetname" "t15" "origin" "-136 -1008 40" "classname" "path_corner" } { "target" "t15" "targetname" "t14" "origin" "-208 -1088 40" "classname" "path_corner" } { "target" "t17" "targetname" "t16" "origin" "-96 -1344 40" "classname" "path_corner" } { "angle" "-1" "wait" "-1" "targetname" "t10" "classname" "func_door" "model" "*6" } { "target" "t19" "classname" "trigger_teleport" "spawnflags" "2" "model" "*7" } { "target" "t18" "classname" "trigger_teleport" "spawnflags" "2" "model" "*8" } { "target" "t109" "targetname" "t21" "origin" "672 -1360 40" "classname" "path_corner" } { "targetname" "t19" "origin" "504 -1216 32" "classname" "info_teleport_destination" } { "targetname" "t18" "origin" "704 -1216 32" "classname" "info_teleport_destination" } { "target" "t24" "targetname" "t23" "origin" "392 -1144 40" "classname" "path_corner" } { "target" "t25" "targetname" "t24" "origin" "256 -1016 40" "classname" "path_corner" } { "target" "t23" "targetname" "t25" "origin" "136 -1144 32" "classname" "path_corner" } { "target" "t21" "targetname" "t26" "origin" "712 -1032 40" "classname" "path_corner" } { "spawnflags" "2" "origin" "1800 296 0" "classname" "item_health" } { "target" "t44" "targetname" "t43" "origin" "776 1888 200" "classname" "path_corner" } { "target" "t43" "targetname" "t44" "origin" "168 1888 200" "classname" "path_corner" } { "light" "300" "origin" "-446 1686 116" "classname" "light_torch_small_walltorch" } { "light" "300" "origin" "102 1978 116" "classname" "light_torch_small_walltorch" } { "light" "300" "origin" "818 1898 116" "classname" "light_torch_small_walltorch" } { "light" "400" "origin" "2336 728 144" "classname" "light" } { "classname" "path_corner" "origin" "16 -1344 40" "target" "t16" "targetname" "t80" } { "classname" "item_shells" "origin" "-248 -1272 16" } { "light" "150" "origin" "378 -998 340" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "134 -998 340" "classname" "light_torch_small_walltorch" } { "target" "t26" "targetname" "t109" "origin" "576 -1216 40" "classname" "path_corner" } { "target" "t124" "targetname" "t123" "origin" "8 -632 24" "classname" "path_corner" } { "target" "t125" "targetname" "t124" "origin" "-160 -536 24" "classname" "path_corner" } { "target" "t123" "targetname" "t125" "origin" "-192 -256 24" "classname" "path_corner" } { "classname" "trigger_changelevel" "map" "e4m7" "model" "*9" } { "target" "t145" "targetname" "t143" "origin" "256 -1752 224" "classname" "path_corner" } { "targetname" "t145" "target" "t143" "origin" "256 -1352 224" "classname" "path_corner" } { "origin" "256 -1520 96" "classname" "light" } { "light" "200" "classname" "light" "origin" "-160 -832 96" } { "origin" "-160 -752 96" "classname" "light" } { "origin" "256 -976 96" "classname" "light" } { "classname" "light" "origin" "-96 -1832 264" "light" "400" } { "classname" "info_player_deathmatch" "origin" "16 -1816 216" "angle" "135" } { "angle" "90" "origin" "-112 -1808 216" "classname" "info_player_start" } { "targetname" "t164" "sounds" "2" "classname" "func_plat" "model" "*10" } { "classname" "weapon_rocketlauncher" "origin" "296 736 240" "target" "t219" } { "classname" "item_armorInv" "origin" "408 24 240" } { "targetname" "t147" "angle" "0" "classname" "func_door_secret" "wait" "-1" "lip" "-8" "model" "*11" } { "height" "144" "classname" "func_plat" "model" "*12" } { "sounds" "4" "angle" "180" "classname" "func_door" "wait" "-1" "model" "*13" } { "light" "200" "origin" "712 -440 120" "classname" "light" } { "classname" "light" "origin" "712 -632 120" "light" "200" } { "light" "200" "origin" "712 -824 120" "classname" "light" } { "light" "400" "angle" "0" "origin" "456 -864 288" "classname" "light" } { "light" "150" "origin" "392 -864 320" "classname" "light" } { "light" "150" "origin" "392 -864 192" "classname" "light" } { "light" "300" "angle" "0" "origin" "456 -864 192" "classname" "light" } { "origin" "640 -1624 24" "classname" "monster_tarbaby" "targetname" "t208" } { "targetname" "t148" "origin" "720 -1760 24" "classname" "monster_demon1" } { "targetname" "t148" "classname" "monster_demon1" "origin" "808 -1760 24" "spawnflags" "768" } { "target" "t148" "classname" "trigger_once" "angle" "90" "model" "*14" } { "targetname" "t160" "angle" "315" "origin" "512 -456 264" "classname" "info_teleport_destination" } { "targetname" "t150" "angle" "90" "origin" "576 -640 232" "classname" "info_teleport_destination" } { "targetname" "t151" "angle" "45" "classname" "info_teleport_destination" "origin" "520 -832 264" } { "target" "t150" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t148" "model" "*15" } { "target" "t151" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t148" "model" "*16" } { "origin" "824 -1624 24" "classname" "monster_tarbaby" "targetname" "t167" "angle" "90" } { "classname" "monster_tarbaby" "origin" "768 -1624 24" "angle" "90" "targetname" "t167" } { "origin" "704 -1624 24" "classname" "monster_tarbaby" "spawnflags" "768" "angle" "90" "targetname" "t167" } { "target" "t150" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t167" "model" "*17" } { "target" "t151" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t167" "model" "*18" } { "target" "t160" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t167" "model" "*19" } { "origin" "-464 -576 64" "classname" "light" } { "light" "200" "classname" "light" "origin" "-384 -576 64" } { "classname" "light" "origin" "-768 -1184 64" } { "light" "150" "origin" "-888 -456 184" "classname" "light" } { "classname" "light" "origin" "-888 -584 184" "light" "150" } { "light" "150" "origin" "-888 -712 184" "classname" "light" } { "classname" "light" "origin" "-888 -840 184" "light" "150" } { "light" "150" "origin" "-888 -968 184" "classname" "light" } { "classname" "light" "origin" "-648 -968 184" "light" "150" } { "light" "150" "origin" "-648 -840 184" "classname" "light" } { "classname" "light" "origin" "-648 -696 184" "light" "150" } { "light" "150" "origin" "-648 -456 184" "classname" "light" } { "classname" "light" "origin" "-768 -456 184" "light" "150" } { "targetname" "t154" "sounds" "4" "angle" "90" "classname" "func_door" "speed" "500" "model" "*20" } { "classname" "func_door" "angle" "270" "sounds" "4" "speed" "500" "model" "*21" } { "dmg" "100" "lip" "-624" "sounds" "3" "targetname" "t155" "angle" "270" "classname" "func_door" "speed" "100" "model" "*22" } { "sounds" "3" "target" "t155" "classname" "trigger_once" "model" "*23" } { "targetname" "t211" "angle" "90" "origin" "-960 -1752 -104" "classname" "monster_tarbaby" } { "targetname" "t211" "angle" "135" "classname" "monster_tarbaby" "origin" "-704 -1752 -104" } { "angle" "45" "origin" "-832 -1280 -104" "classname" "monster_tarbaby" } { "angle" "135" "classname" "monster_tarbaby" "origin" "-704 -1344 -104" } { "angle" "180" "origin" "-640 -1152 -104" "classname" "monster_tarbaby" } { "angle" "90" "classname" "monster_tarbaby" "origin" "-832 -1536 -104" } { "angle" "0" "spawnflags" "768" "origin" "-1024 -1472 -104" "classname" "monster_tarbaby" } { "angle" "90" "classname" "monster_tarbaby" "origin" "-512 -1472 -104" "spawnflags" "768" } { "targetname" "t211" "angle" "90" "spawnflags" "768" "origin" "-576 -1752 -104" "classname" "monster_tarbaby" } { "targetname" "t211" "angle" "90" "classname" "monster_tarbaby" "origin" "-832 -1816 -104" "spawnflags" "768" } { "targetname" "t211" "angle" "90" "spawnflags" "768" "origin" "-768 -1608 -104" "classname" "monster_tarbaby" } { "angle" "135" "classname" "monster_tarbaby" "origin" "-672 -1504 -104" "spawnflags" "768" } { "angle" "45" "spawnflags" "768" "origin" "-960 -1248 -104" "classname" "monster_tarbaby" } { "targetname" "t156" "classname" "func_plat" "model" "*24" } { "target" "t157" "angle" "0" "wait" "-1" "sounds" "1" "classname" "func_button" "model" "*25" } { "target" "t157" "classname" "func_button" "sounds" "1" "wait" "-1" "angle" "270" "model" "*26" } { "target" "t157" "angle" "90" "wait" "-1" "sounds" "1" "classname" "func_button" "model" "*27" } { "target" "t157" "classname" "func_button" "sounds" "1" "wait" "-1" "angle" "180" "model" "*28" } { "targetname" "t157" "target" "t156" "count" "4" "classname" "trigger_counter" "model" "*29" } { "origin" "-960 -1656 -128" "classname" "item_health" } { "classname" "item_health" "origin" "-544 -1376 -128" } { "origin" "-1024 -1376 -128" "classname" "item_rockets" } { "spawnflags" "1" "origin" "-616 -1840 -128" "classname" "item_cells" } { "origin" "-952 -1840 -128" "classname" "item_health" } { "origin" "-192 -1504 200" "classname" "item_artifact_super_damage" } { "target" "t10" "classname" "trigger_once" "model" "*30" } { "sounds" "2" "origin" "-328 -1552 200" "classname" "item_key2" "spawnflags" "2048" } { "light" "200" "origin" "-64 -520 168" "classname" "light" } { "classname" "light" "origin" "-64 -712 168" "light" "200" } { "light" "150" "origin" "1368 440 224" "classname" "light" } { "classname" "light" "origin" "1560 440 224" "light" "150" } { "light" "150" "origin" "1752 440 224" "classname" "light" } { "light" "150" "origin" "1240 440 64" "classname" "light" } { "classname" "light" "origin" "1432 440 64" "light" "150" } { "light" "150" "origin" "1624 440 64" "classname" "light" } { "classname" "light" "origin" "1816 440 64" "light" "150" } { "light" "150" "origin" "1496 312 256" "classname" "light" } { "classname" "light" "origin" "1688 312 256" "light" "150" } { "light" "150" "origin" "1880 312 256" "classname" "light" } { "classname" "light" "origin" "1240 184 64" "light" "150" } { "angle" "0" "origin" "1528 128 280" "classname" "light" } { "classname" "light" "origin" "1720 128 160" "angle" "0" } { "angle" "0" "origin" "1720 128 280" "classname" "light" } { "angle" "0" "origin" "1528 128 160" "classname" "light" } { "classname" "light" "origin" "1336 128 160" "angle" "0" } { "light" "180" "origin" "-960 -1752 -32" "classname" "light" } { "classname" "light" "origin" "-1024 -1344 -32" "light" "180" } { "light" "180" "origin" "-512 -1344 -32" "classname" "light" } { "classname" "light" "origin" "-512 -1472 -32" "light" "180" } { "light" "180" "origin" "-704 -1752 -32" "classname" "light" } { "classname" "light" "origin" "-576 -1752 -32" "light" "180" } { "light" "180" "origin" "-832 -1752 -32" "classname" "light" } { "classname" "light" "origin" "-1024 -1472 -32" "light" "180" } { "origin" "-768 -1504 72" "classname" "light" } { "classname" "light" "origin" "-640 -1344 -32" "light" "180" } { "light" "180" "origin" "-960 -1624 -32" "classname" "light" } { "classname" "light" "origin" "-896 -1344 -32" "light" "180" } { "light" "180" "origin" "-576 -1624 -32" "classname" "light" } { "light" "150" "origin" "-960 -1184 -32" "classname" "light" } { "classname" "light" "origin" "-568 -1184 -32" "light" "150" } { "targetname" "t163" "lip" "-8" "wait" "-1" "sounds" "1" "speed" "500" "angle" "180" "classname" "func_door" "spawnflags" "256" "model" "*31" } { "targetname" "t162" "classname" "func_door" "angle" "0" "speed" "500" "sounds" "1" "wait" "-1" "lip" "-8" "model" "*32" } { "target" "t163" "classname" "trigger_once" "model" "*33" } { "origin" "960 -768 16" "classname" "item_artifact_envirosuit" } { "origin" "816 -720 -8" "classname" "item_rockets" } { "origin" "944 -592 -8" "classname" "weapon_lightning" } { "origin" "864 -640 -8" "classname" "item_health" } { "origin" "760 -672 -80" "classname" "light" } { "origin" "912 -784 -80" "classname" "light" } { "classname" "light" "origin" "832 -672 96" } { "light" "200" "origin" "912 -480 0" "classname" "light" } { "light" "200" "origin" "736 352 -64" "classname" "light" } { "classname" "light" "origin" "912 -256 -208" } { "origin" "688 128 -208" "classname" "light" } { "target" "t164" "sounds" "1" "wait" "-1" "angle" "-2" "spawnflags" "2056" "classname" "func_door" "model" "*34" } { "classname" "monster_tarbaby" "origin" "584 -1624 24" "targetname" "t208" } { "origin" "528 -1624 24" "classname" "monster_tarbaby" "targetname" "t208" } { "target" "t150" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t208" "model" "*35" } { "target" "t151" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t208" "model" "*36" } { "target" "t160" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t208" "model" "*37" } { "targetname" "t10" "angle" "90" "classname" "func_door_secret" "sounds" "1" "spawnflags" "1" "model" "*38" } { "light" "200" "origin" "-384 -1576 -64" "classname" "light" } { "classname" "light" "origin" "-384 -1552 64" "light" "200" } { "light" "200" "origin" "-384 -1528 256" "classname" "light" } { "light" "150" "origin" "-768 -576 216" "classname" "light" } { "classname" "light" "origin" "-768 -704 216" "light" "150" } { "light" "150" "origin" "-768 -832 216" "classname" "light" } { "classname" "light" "origin" "-768 -960 216" "light" "150" } { "light" "150" "origin" "-424 -408 64" "classname" "light" } { "classname" "light" "origin" "-424 -744 64" "light" "150" } { "light" "200" "origin" "40 -1016 128" "classname" "light" } { "light" "150" "origin" "256 -1120 128" "classname" "light" } { "classname" "light" "origin" "472 -1016 128" "light" "200" } { "light" "200" "origin" "632 -1000 96" "classname" "light" } { "origin" "410 -198 68" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "594 -198 68" } { "origin" "202 -202 212" "classname" "light_torch_small_walltorch" } { "origin" "584 -264 140" "classname" "item_health" } { "classname" "func_button" "angle" "270" "wait" "-1" "sounds" "1" "target" "t147" "model" "*39" } { "classname" "monster_shalrath" "origin" "-160 -608 24" "target" "t124" } { "classname" "light" "origin" "-888 -424 40" "light" "200" } { "light" "200" "origin" "-760 -424 40" "classname" "light" } { "classname" "light" "origin" "-632 -424 40" "light" "200" } { "classname" "trigger_secret" "model" "*40" } { "classname" "monster_fish" "origin" "912 -784 -72" "angle" "135" "spawnflags" "256" } { "spawnflags" "768" "angle" "225" "origin" "976 -592 -72" "classname" "monster_fish" } { "classname" "item_spikes" "origin" "160 -512 144" "spawnflags" "1" } { "spawnflags" "1" "origin" "320 -512 144" "classname" "item_spikes" } { "classname" "item_shells" "origin" "240 -696 144" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-352 -736 -16" "spawnflags" "1" } { "classname" "monster_fish" "origin" "688 208 -200" "angle" "270" "spawnflags" "256" } { "sounds" "2" "height" "144" "classname" "func_plat" "model" "*41" } { "spawnflags" "1" "origin" "-192 80 32" "classname" "item_health" } { "spawnflags" "1" "origin" "-192 32 32" "classname" "item_spikes" } { "origin" "40 88 64" "classname" "light" } { "origin" "-64 64 64" "classname" "light" } { "light" "200" "classname" "light" "origin" "-416 -352 -80" } { "origin" "-416 96 -80" "classname" "light" } { "origin" "170 562 104" "classname" "light_torch_small_walltorch" } { "origin" "602 562 104" "classname" "light_torch_small_walltorch" } { "origin" "650 82 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "602 82 104" } { "origin" "170 82 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "122 82 104" } { "origin" "306 218 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "306 266 104" } { "origin" "466 378 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "466 426 104" } { "classname" "light_torch_small_walltorch" "origin" "386 762 168" } { "classname" "light_torch_small_walltorch" "origin" "386 -22 168" } { "origin" "-118 322 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "826 322 104" } { "classname" "light_torch_small_walltorch" "origin" "-118 322 328" } { "origin" "146 218 264" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "626 218 264" } { "origin" "626 586 264" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "146 586 264" } { "light" "400" "origin" "384 320 392" "classname" "light" } { "light" "200" "origin" "64 448 -8" "classname" "light" } { "classname" "light" "origin" "64 192 -8" "light" "200" } { "light" "200" "origin" "256 0 -8" "classname" "light" } { "classname" "light" "origin" "512 0 -8" "light" "200" } { "light" "200" "origin" "512 640 -8" "classname" "light" } { "classname" "light" "origin" "256 640 -8" "light" "200" } { "light" "200" "origin" "704 448 -8" "classname" "light" } { "classname" "light" "origin" "704 192 -8" "light" "200" } { "targetname" "t168" "lip" "-128" "sounds" "3" "wait" "6" "angle" "-1" "classname" "func_door" "model" "*42" } { "target" "t168" "health" "1" "classname" "trigger_multiple" "model" "*43" } { "classname" "trigger_secret" "model" "*44" } { "spawnflags" "2" "origin" "-32 -1696 176" "classname" "item_health" } { "origin" "378 -1718 244" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "138 -1462 244" } { "origin" "378 -1286 244" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "256 -1728 96" } { "target" "t154" "classname" "trigger_multiple" "wait" "4" "model" "*45" } { "light" "200" "origin" "-768 -1888 -64" "classname" "light" } { "light" "150" "origin" "256 -768 320" "classname" "light" } { "light" "150" "origin" "256 -576 320" "classname" "light" } { "light" "150" "origin" "256 -384 320" "classname" "light" } { "light" "150" "origin" "122 -862 276" "classname" "light_torch_small_walltorch" } { "targetname" "t183" "angle" "270" "origin" "384 672 328" "classname" "info_teleport_destination" } { "targetname" "t185" "angle" "90" "origin" "376 8 328" "classname" "info_teleport_destination" } { "target" "t167" "targetname" "t148" "delay" "3" "classname" "trigger_once" "model" "*46" } { "spawnflags" "256" "angle" "45" "origin" "848 -752 16" "classname" "monster_tarbaby" } { "spawnflags" "768" "angle" "135" "origin" "976 -688 16" "classname" "monster_tarbaby" } { "classname" "trigger_secret" "model" "*47" } { "origin" "256 -160 160" "classname" "item_key1" "spawnflags" "2048" } { "spawnflags" "1" "origin" "640 -232 144" "classname" "item_cells" } { "target" "t177" "targetname" "t176" "spawnflags" "2064" "wait" "-1" "angle" "-1" "classname" "func_door" "model" "*48" } { "targetname" "t177" "target" "t176" "classname" "func_door" "angle" "-1" "wait" "-1" "spawnflags" "2064" "model" "*49" } { "target" "t179" "targetname" "t178" "origin" "-416 1376 200" "classname" "path_corner" } { "target" "t180" "targetname" "t179" "classname" "path_corner" "origin" "-384 1728 200" } { "target" "t181" "targetname" "t180" "origin" "-32 1904 200" "classname" "path_corner" } { "target" "t178" "targetname" "t181" "classname" "path_corner" "origin" "-320 1728 200" } { "origin" "672 1560 0" "classname" "item_armor2" } { "origin" "386 1546 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "578 1546 116" } { "classname" "light_torch_small_walltorch" "origin" "98 1794 212" } { "origin" "386 1794 212" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "674 1794 212" } { "origin" "-110 1730 212" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-222 1562 212" } { "light" "150" "origin" "-488 1376 200" "classname" "light" } { "classname" "light" "origin" "-448 1568 200" "light" "150" } { "light" "150" "origin" "-352 1768 200" "classname" "light" } { "classname" "light" "origin" "-216 1872 200" "light" "150" } { "light" "150" "origin" "-24 1952 200" "classname" "light" } { "classname" "light" "origin" "256 1952 200" "light" "150" } { "classname" "light" "origin" "736 1952 200" "light" "150" } { "target" "t182" "angle" "315" "origin" "-352 1536 24" "classname" "monster_demon1" } { "target" "t186" "classname" "monster_demon1" "origin" "544 1888 24" "angle" "225" } { "targetname" "t182" "spawnflags" "256" "angle" "135" "origin" "-128 1104 216" "classname" "monster_tarbaby" } { "targetname" "t182" "spawnflags" "768" "angle" "135" "classname" "monster_tarbaby" "origin" "-80 1184 216" } { "targetname" "t182" "spawnflags" "768" "angle" "135" "origin" "0 1328 216" "classname" "monster_tarbaby" } { "targetname" "t182" "spawnflags" "256" "angle" "135" "classname" "monster_tarbaby" "origin" "48 1424 216" } { "targetname" "t182" "spawnflags" "768" "angle" "135" "origin" "112 1504 216" "classname" "monster_tarbaby" } { "spawnflags" "2048" "targetname" "t182" "wait" "-1" "lip" "-160" "angle" "-2" "classname" "func_door" "model" "*50" } { "targetname" "t182" "spawnflags" "256" "origin" "-32 1264 216" "classname" "monster_tarbaby" "angle" "135" } { "origin" "88 1464 200" "classname" "light" } { "classname" "light" "origin" "-120 1128 200" } { "origin" "-8 1304 200" "classname" "light" } { "origin" "-440 808 -8" "classname" "light" } { "classname" "light" "origin" "-312 648 -8" } { "origin" "-184 808 -8" "classname" "light" } { "origin" "-328 520 104" "classname" "light" } { "origin" "-38 570 212" "classname" "light_torch_small_walltorch" } { "target" "t185" "classname" "trigger_teleport" "model" "*51" } { "target" "t184" "classname" "trigger_teleport" "model" "*52" } { "target" "t183" "classname" "trigger_teleport" "model" "*53" } { "angle" "225" "targetname" "t184" "origin" "360 320 176" "classname" "info_teleport_destination" } { "targetname" "t10" "classname" "monster_hell_knight" "origin" "272 880 152" "angle" "270" "spawnflags" "1" } { "targetname" "t10" "angle" "270" "origin" "360 880 152" "classname" "monster_hell_knight" "spawnflags" "1" } { "targetname" "t10" "classname" "monster_hell_knight" "origin" "520 880 152" "angle" "270" "spawnflags" "1" } { "targetname" "t210" "origin" "256 976 152" "classname" "monster_shalrath" "spawnflags" "1" } { "spawnflags" "256" "targetname" "t186" "angle" "90" "origin" "384 1024 152" "classname" "monster_shalrath" } { "target" "t187" "classname" "trigger_teleport" "targetname" "t186" "model" "*54" } { "targetname" "t187" "angle" "135" "origin" "128 1632 136" "classname" "info_teleport_destination" } { "light" "200" "classname" "light" "origin" "456 0 320" } { "spawnflags" "2048" "sounds" "3" "targetname" "t189" "lip" "64" "wait" "-1" "angle" "-2" "classname" "func_door" "model" "*55" } { "origin" "456 640 320" "classname" "light" "light" "200" } { "target" "t188" "angle" "-2" "sounds" "1" "wait" "-1" "classname" "func_button" "model" "*56" } { "targetname" "t188" "height" "232" "speed" "75" "sounds" "2" "classname" "func_plat" "delay" "2" "model" "*57" } { "origin" "768 896 408" "classname" "light" } { "light" "200" "origin" "712 608 408" "classname" "light" } { "classname" "func_plat" "model" "*58" } { "classname" "light" "origin" "768 1408 256" } { "origin" "768 1728 256" "classname" "light" } { "spawnflags" "2048" "origin" "24 1360 192" "classname" "item_health" } { "spawnflags" "2049" "origin" "-80 1208 192" "classname" "item_spikes" } { "spawnflags" "2048" "speed" "50" "lip" "-8" "sounds" "3" "target" "t189" "wait" "-1" "angle" "90" "classname" "func_button" "model" "*59" } { "origin" "122 562 104" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "650 562 104" } { "origin" "384 712 280" "classname" "light" } { "target" "t192" "classname" "trigger_teleport" "model" "*60" } { "targetname" "t192" "angle" "315" "origin" "144 400 360" "classname" "info_teleport_destination" } { "light" "200" "origin" "896 320 320" "classname" "light" } { "origin" "1146 322 296" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "1178 322 104" } { "spawnflags" "1" "origin" "1224 328 -128" "classname" "item_spikes" } { "spawnflags" "1" "origin" "1720 144 0" "classname" "item_cells" } { "spawnflags" "1" "origin" "1232 272 -128" "classname" "item_rockets" } { "origin" "1216 160 24" "classname" "item_artifact_super_damage" } { "origin" "544 544 -104" "classname" "item_artifact_envirosuit" } { "origin" "800 584 344" "classname" "item_artifact_envirosuit" } { "origin" "240 528 -104" "classname" "item_artifact_invisibility" } { "origin" "624 -48 184" "classname" "item_artifact_super_damage" } { "origin" "344 -40 240" "classname" "item_cells" } { "wait" "-1" "targetname" "t193" "angle" "270" "classname" "func_door" "spawnflags" "2048" "model" "*61" } { "wait" "-1" "angle" "90" "classname" "func_door" "spawnflags" "2048" "model" "*62" } { "spawnflags" "768" "angle" "45" "origin" "1592 240 24" "classname" "monster_shalrath" } { "classname" "monster_shalrath" "origin" "1592 392 24" "angle" "315" } { "classname" "func_illusionary" "model" "*63" } { "classname" "func_illusionary" "model" "*64" } { "classname" "func_illusionary" "model" "*65" } { "angle" "90" "height" "500" "speed" "500" "classname" "trigger_monsterjump" "model" "*66" } { "classname" "trigger_monsterjump" "speed" "500" "height" "500" "angle" "90" "model" "*67" } { "angle" "90" "height" "500" "speed" "500" "classname" "trigger_monsterjump" "model" "*68" } { "targetname" "t202" "angle" "90" "origin" "1336 48 152" "classname" "monster_tarbaby" } { "targetname" "t202" "spawnflags" "256" "classname" "monster_tarbaby" "origin" "1336 0 152" "angle" "90" } { "targetname" "t202" "spawnflags" "768" "angle" "90" "origin" "1336 -48 152" "classname" "monster_tarbaby" } { "targetname" "t202" "spawnflags" "768" "classname" "monster_tarbaby" "origin" "1336 -96 152" "angle" "90" } { "targetname" "t202" "angle" "90" "origin" "1528 -48 152" "classname" "monster_tarbaby" "spawnflags" "768" } { "targetname" "t202" "spawnflags" "768" "classname" "monster_tarbaby" "origin" "1528 -96 152" "angle" "90" } { "targetname" "t202" "angle" "90" "origin" "1720 -96 152" "classname" "monster_tarbaby" "spawnflags" "768" } { "targetname" "t202" "spawnflags" "768" "classname" "monster_tarbaby" "origin" "1720 -48 152" "angle" "90" } { "targetname" "t202" "angle" "90" "origin" "1528 0 152" "classname" "monster_tarbaby" "spawnflags" "256" } { "targetname" "t202" "spawnflags" "256" "classname" "monster_tarbaby" "origin" "1720 0 152" "angle" "90" } { "targetname" "t202" "classname" "monster_tarbaby" "origin" "1528 48 152" "angle" "90" } { "targetname" "t202" "angle" "90" "origin" "1720 48 152" "classname" "monster_tarbaby" } { "spawnflags" "1" "origin" "1328 144 0" "classname" "item_spikes" } { "classname" "item_shells" "origin" "512 32 -128" } { "classname" "item_shells" "origin" "32 352 -128" } { "classname" "item_health" "origin" "152 712 -128" } { "classname" "item_health" "origin" "208 -80 -128" } { "light" "200" "classname" "light" "origin" "256 -736 232" } { "classname" "trigger_monsterjump" "angle" "90" "model" "*69" } { "classname" "weapon_grenadelauncher" "origin" "-144 -1712 176" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "256 -608 144" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "864 -576 16" "angle" "45" } { "classname" "weapon_supernailgun" "origin" "-112 64 32" "spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "624 472 320" "spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "640 1904 0" "spawnflags" "1792" } { "classname" "weapon_grenadelauncher" "origin" "64 1888 176" "spawnflags" "1792" } { "classname" "weapon_lightning" "origin" "768 736 320" "spawnflags" "1792" } { "classname" "weapon_supernailgun" "origin" "1520 272 0" "spawnflags" "1792" } { "spawnflags" "1792" "classname" "weapon_grenadelauncher" "origin" "2320 656 72" } { "classname" "info_player_deathmatch" "origin" "2448 720 96" "angle" "225" } { "classname" "weapon_supershotgun" "origin" "2432 312 104" "spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "-200 512 152" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "-224 72 56" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "248 48 376" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "144 656 376" "angle" "315" } { "classname" "info_player_deathmatch" "origin" "768 784 344" "angle" "225" } { "angle" "180" "origin" "784 368 376" "classname" "info_player_deathmatch" } { "classname" "trigger_once" "angle" "270" "target" "t208" "model" "*70" } { "classname" "monster_shalrath" "origin" "272 -680 434" "angle" "225" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "584 -1320 40" "angle" "90" "target" "t109" } { "classname" "monster_demon1" "origin" "-160 -1312 40" "target" "t16" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "336 -1024 40" "target" "t24" "spawnflags" "768" } { "classname" "func_door_secret" "spawnflags" "4" "angle" "0" "model" "*71" } { "classname" "trigger_secret" "model" "*72" } { "classname" "item_cells" "origin" "336 344 -120" "spawnflags" "1" } { "classname" "item_artifact_invulnerability" "origin" "416 320 -96" } { "target" "t178" "origin" "-416 1440 200" "classname" "monster_hell_knight" } { "target" "t43" "origin" "704 1888 200" "classname" "monster_shalrath" } { "style" "32" "targetname" "t209" "spawnflags" "1" "origin" "1752 312 96" "classname" "light" } { "origin" "2106 386 172" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "2106 242 172" } { "classname" "light" "origin" "2336 272 192" } { "origin" "2472 448 192" "classname" "light" } { "message" "The altar has been defiled." "target" "t162" "health" "50" "classname" "trigger_once" "spawnflags" "2048" "model" "*73" } { "target" "t210" "classname" "trigger_once" "model" "*74" } { "targetname" "t210" "origin" "520 1032 152" "classname" "monster_hell_knight" "spawnflags" "1" } { "targetname" "t210" "angle" "270" "classname" "monster_hell_knight" "origin" "408 880 152" "spawnflags" "1" } { "target" "t211" "classname" "trigger_once" "sounds" "3" "model" "*75" } { "target" "t202" "classname" "trigger_once" "model" "*76" } { "spawnflags" "256" "angle" "0" "origin" "2224 464 112" "classname" "monster_hell_knight" } { "classname" "monster_hell_knight" "origin" "2328 312 144" "angle" "180" "spawnflags" "768" } { "spawnflags" "768" "angle" "270" "origin" "2304 704 96" "classname" "monster_hell_knight" "targetname" "t217" } { "origin" "-416 1232 40" "classname" "light" } { "classname" "light" "origin" "496 1952 200" "light" "150" } { "targetname" "t10" "spawnflags" "256" "angle" "90" "origin" "-32 -2112 24" "classname" "monster_tarbaby" } { "target" "t212" "classname" "trigger_teleport" "spawnflags" "2" "targetname" "t10" "model" "*77" } { "targetname" "t212" "angle" "135" "origin" "-8 -1768 328" "classname" "info_teleport_destination" } { "target" "t13" "angle" "90" "origin" "-224 -2192 24" "classname" "monster_tarbaby" } { "target" "t16" "origin" "-128 -2192 56" "classname" "monster_tarbaby" } { "target" "t23" "origin" "544 -1760 24" "classname" "monster_tarbaby" } { "target" "t109" "classname" "monster_tarbaby" "origin" "624 -1760 24" } { "target" "t143" "spawnflags" "256" "angle" "270" "origin" "256 -1632 224" "classname" "monster_demon1" } { "spawnflags" "768" "angle" "270" "origin" "192 -1120 224" "classname" "monster_hell_knight" } { "classname" "monster_hell_knight" "origin" "320 -1120 224" "angle" "270" } { "angle" "180" "spawnflags" "256" "origin" "464 -248 168" "classname" "monster_hell_knight" } { "spawnflags" "1" "origin" "-168 488 128" "classname" "item_shells" } { "origin" "224 384 160" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "512 224 160" } { "targetname" "t213" "message" "An unholy altar! Shoot it repeatedly!" "classname" "trigger_multiple" "spawnflags" "2048" "model" "*78" } { "targetname" "t214" "target" "t193" "health" "50" "message" "You have defiled the altar!" "classname" "trigger_once" "spawnflags" "2048" "model" "*79" } { "style" "32" "targetname" "t215" "target" "t209" "message" "Shoot the unholy altar \n to open this door." "classname" "trigger_multiple" "spawnflags" "2048" "model" "*80" } { "style" "32" "killtarget" "t215" "target" "t215" "targetname" "t193" "classname" "trigger_once" "model" "*81" } { "origin" "0 232 -128" "classname" "item_cells" } { "spawnflags" "769" "origin" "768 192 -128" "classname" "item_spikes" } { "spawnflags" "768" "origin" "552 704 -128" "classname" "item_shells" } { "classname" "item_rockets" "origin" "752 800 320" } { "spawnflags" "768" "origin" "752 856 320" "classname" "item_rockets" } { "spawnflags" "768" "origin" "128 -24 160" "classname" "item_shells" } { "classname" "monster_shalrath" "origin" "160 -680 432" } { "classname" "monster_shalrath" "origin" "352 -680 432" } { "classname" "monster_tarbaby" "origin" "704 1664 24" "spawnflags" "768" "angle" "180" } { "angle" "180" "spawnflags" "768" "origin" "768 1728 24" "classname" "monster_tarbaby" } { "classname" "monster_tarbaby" "origin" "768 1600 24" "spawnflags" "768" "angle" "180" } { "angle" "180" "spawnflags" "768" "origin" "640 1600 24" "classname" "monster_tarbaby" } { "classname" "monster_tarbaby" "origin" "640 1728 24" "spawnflags" "768" "angle" "180" } { "light" "150" "origin" "256 -200 184" "classname" "light" } { "origin" "304 368 -80" "classname" "light" } { "light" "200" "origin" "768 1152 384" "classname" "light" } { "spawnflags" "2048" "classname" "trigger_multiple" "message" "Are you sure you want to exit now? \n You left something important behind." "wait" "2" "target" "t217" "targetname" "t218" "model" "*82" } { "classname" "trigger_once" "target" "t218" "killtarget" "t218" "targetname" "t219" "model" "*83" } { "classname" "info_intermission" "origin" "664 0 376" "mangle" "25 120 0" } { "mangle" "-25 325 0" "origin" "-896 -1280 -48" "classname" "info_intermission" } { "mangle" "0 330 0" "origin" "304 -1088 112" "classname" "info_intermission" } { "mangle" "0 330 0" "origin" "1344 416 208" "classname" "info_intermission" } { "origin" "-416 1296 24" "classname" "item_artifact_invisibility" } { "classname" "func_door_secret" "angle" "180" "targetname" "t162" "sounds" "1" "spawnflags" "1" "model" "*84" } { "targetname" "t186" "origin" "552 1752 8" "classname" "trigger_relay" } { "classname" "info_player_coop" "origin" "-48 -1744 200" "angle" "90" } { "angle" "90" "origin" "-200 -1808 200" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-208 -1736 200" "angle" "90" } { "classname" "item_cells" "origin" "0 -256 0" "spawnflags" "1" } { "classname" "item_rockets" "origin" "160 -1056 200" } { "spawnflags" "1" "classname" "item_cells" "origin" "320 -1440 200" } { "classname" "item_cells" "origin" "336 264 -120" "spawnflags" "1" } { "classname" "item_rockets" "origin" "752 968 320" } { "classname" "item_cells" "origin" "752 1168 176" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "1" "target" "t164" "spawnflags" "1792" "model" "*85" } { "classname" "weapon_lightning" "origin" "256 -1208 200" "spawnflags" "1792" } { "classname" "func_wall" "spawnflags" "1792" "model" "*86" } { "target" "t213" "killtarget" "t213" "targetname" "t162" "origin" "424 -776 152" "classname" "trigger_relay" } { "origin" "512 -1184 16" "classname" "item_cells" } { "spawnflags" "1" "origin" "-32 -1568 48" "classname" "item_cells" } { "origin" "-352 -448 -16" "classname" "item_rockets" } { "classname" "item_cells" "origin" "640 -288 144" "spawnflags" "1" } { "spawnflags" "769" "origin" "896 -720 -8" "classname" "item_rockets" } { "spawnflags" "1" "origin" "-544 -1568 -128" "classname" "item_shells" } { "light" "120" "origin" "-192 -1544 264" "classname" "light" } { "spawnflags" "1" "origin" "208 -1400 200" "classname" "item_spikes" } { "spawnflags" "1" "origin" "288 304 -120" "classname" "item_spikes" } { "origin" "368 456 0" "classname" "item_rockets" } { "spawnflags" "1792" "classname" "func_wall" "model" "*87" } { "origin" "-414 -318 24" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "-318 66 32" } { "origin" "690 -662 32" "classname" "ambient_drip" } { "origin" "922 -414 32" "classname" "ambient_drip" } { "origin" "-318 834 32" "classname" "ambient_drip" } { "origin" "1282 322 64" "classname" "ambient_drip" } { "classname" "ambient_swamp1" "origin" "650 602 32" } { "classname" "ambient_swamp2" "origin" "650 58 32" } { "origin" "386 498 320" "classname" "ambient_swamp1" } { "origin" "386 138 320" "classname" "ambient_swamp2" } { "origin" "114 58 32" "classname" "ambient_swamp2" } { "origin" "122 602 32" "classname" "ambient_swamp1" } { "classname" "light" "origin" "384 600 96" } { "classname" "func_door" "angle" "270" "targetname" "t10" "model" "*88" } { "angle" "270" "classname" "func_door" "targetname" "t210" "model" "*89" } { "angle" "0" "classname" "func_door" "targetname" "t10" "model" "*90" } { "classname" "func_door" "angle" "0" "targetname" "t210" "model" "*91" } { "angle" "0" "classname" "func_door" "targetname" "t10" "model" "*92" } { "classname" "func_door" "angle" "0" "targetname" "t210" "lip" "-64" "model" "*93" } { "classname" "item_artifact_invisibility" "origin" "88 -1504 72" "spawnflags" "1024" } // // Capture the flag map mods // // capture spawns // team1 { "origin" "776 1912 34" "classname" "item_flag_team1" } { "angle" "180" "origin" "680 1568 24" "classname" "info_player_team1" } { "angle" "180" "origin" "530 1568 24" "classname" "info_player_team1" } { "angle" "180" "origin" "380 1568 24" "classname" "info_player_team1" } { "angle" "180" "origin" "680 1768 24" "classname" "info_player_team1" } { "angle" "180" "origin" "530 1768 24" "classname" "info_player_team1" } { "angle" "180" "origin" "380 1768 24" "classname" "info_player_team1" } // team2 { "origin" "-768 -1876 -94" "classname" "item_flag_team2" } { "angle" "90" "origin" "-618 -1473 -104" "classname" "info_player_team2" } { "angle" "90" "origin" "-768 -1473 -104" "classname" "info_player_team2" } { "angle" "90" "origin" "-918 -1473 -104" "classname" "info_player_team2" } { "angle" "90" "origin" "-618 -1623 -104" "classname" "info_player_team2" } { "angle" "90" "origin" "-768 -1623 -104" "classname" "info_player_team2" } { "angle" "90" "origin" "-918 -1623 -104" "classname" "info_player_team2" } // base one weapons upgrade { "origin" "300 1618 34" "classname" "item_shells" } { "origin" "300 1668 34" "classname" "item_shells" } { "origin" "300 1718 34" "classname" "item_shells" } { "origin" "250 1618 34" "classname" "item_spikes" } { "origin" "250 1668 34" "classname" "item_spikes" } { "origin" "250 1718 34" "classname" "item_spikes" } { "origin" "200 1618 34" "classname" "weapon_supershotgun" } //already have yellow armor at base //{ //"origin" "200 1668 34" //"classname" "item_armor2" //} { "origin" "200 1718 34" "classname" "weapon_supernailgun" } { "classname" "item_health" "origin" "150 1618 34" } { "classname" "item_health" "origin" "150 1668 34" } { "classname" "item_health" "origin" "150 1718 34" } // base two weapons upgrade { "classname" "item_shells" "origin" "-718 -1375 -94" } { "classname" "item_shells" "origin" "-768 -1375 -94" } { "classname" "item_shells" "origin" "-818 -1375 -94" } { "classname" "item_spikes" "origin" "-718 -1325 -94" } { "classname" "item_spikes" "origin" "-768 -1325 -94" } { "classname" "item_spikes" "origin" "-818 -1325 -94" } { "origin" "-718 -1275 -94" "classname" "weapon_supershotgun" } { "classname" "item_armor2" "origin" "-768 -1275 -94" } { "classname" "weapon_supernailgun" "origin" "-818 -1275 -94" } { "classname" "item_health" "origin" "-718 -1225 -94" } { "classname" "item_health" "origin" "-768 -1225 -94" } { "classname" "item_health" "origin" "-818 -1225 -94" } // end QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m7.ent000066400000000000000000001155511475442401000252100ustar00rootroot00000000000000{ "message" "Azure Agony" "worldtype" "0" "wad" "gfx/medieval.wad" "classname" "worldspawn" "sounds" "7" } { "classname" "light_globe" "origin" "80 152 -100" } { "origin" "528 -192 -100" "classname" "light_globe" } { "classname" "light" "origin" "320 0 -16" "light" "400" } { "classname" "item_armor2" "origin" "592 80 -192" } { "classname" "light" "origin" "648 -128 -8" } { "classname" "light" "origin" "112 -272 -8" } { "origin" "-8 96 -8" "classname" "light" } { "classname" "light" "origin" "432 264 -8" } { "classname" "light" "origin" "-16 -608 -72" } { "classname" "light" "origin" "192 -496 -168" } { "classname" "light" "origin" "192 -608 -16" "light" "200" } { "classname" "info_player_start" "origin" "608 -1008 152" "angle" "90" } { "angle" "-1" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*1" } { "angle" "180" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*2" } { "angle" "0" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*3" } { "sounds" "3" "angle" "-2" "classname" "func_door" "wait" "-1" "spawnflags" "2064" "model" "*4" } { "sounds" "1" "targetname" "t1" "lip" "0" "wait" "-1" "speed" "300" "angle" "270" "classname" "func_door" "model" "*5" } { "target" "t1" "classname" "trigger_once" "model" "*6" } { "targetname" "t3" "height" "152" "classname" "func_plat" "model" "*7" } { "wait" "-1" "angle" "90" "target" "t3" "classname" "func_button" "model" "*8" } { "sounds" "3" "angle" "-1" "classname" "func_door" "model" "*9" } { "target" "t126" "angle" "-2" "classname" "func_button" "wait" "-1" "sounds" "0" "model" "*10" } { "speed" "10" "wait" "-1" "sounds" "3" "angle" "0" "classname" "func_door" "model" "*11" } { "sounds" "3" "wait" "-1" "targetname" "t6" "angle" "-2" "classname" "func_door" "spawnflags" "2048" "model" "*12" } { "angle" "90" "origin" "-192 824 -88" "classname" "monster_demon1" } { "targetname" "t89" "angle" "270" "origin" "-1056 864 -248" "classname" "monster_demon1" } { "sounds" "3" "classname" "func_door" "angle" "180" "model" "*13" } { "sounds" "3" "angle" "0" "classname" "func_door" "model" "*14" } { "sounds" "3" "classname" "func_door" "angle" "270" "model" "*15" } { "sounds" "3" "angle" "90" "classname" "func_door" "model" "*16" } { "classname" "item_health" "origin" "832 1184 -24" } { "classname" "item_health" "origin" "832 1024 -24" } { "classname" "path_corner" "origin" "616 -200 24" "targetname" "t14" "target" "t15" } { "classname" "path_corner" "origin" "200 -208 24" "targetname" "t15" "target" "t16" } { "classname" "path_corner" "origin" "104 272 24" "targetname" "t17" "target" "t18" } { "classname" "path_corner" "origin" "344 272 24" "targetname" "t18" "target" "t17" } { "spawnflags" "256" "classname" "monster_shambler" "origin" "608 -864 280" "angle" "90" "target" "t14" } { "classname" "path_corner" "origin" "104 -120 24" "targetname" "t16" "target" "t17" } { "classname" "item_rockets" "origin" "560 240 -192" } { "classname" "item_health" "origin" "-32 -128 -192" "spawnflags" "1" } { "classname" "item_spikes" "origin" "128 224 -192" } { "classname" "item_health" "origin" "336 -288 -192" } { "classname" "item_spikes" "origin" "-304 -112 2" } { "classname" "item_shells" "origin" "-192 -608 2" } { "classname" "item_shells" "origin" "-880 656 -272" "spawnflags" "1" } { "classname" "item_health" "origin" "-1072 656 -272" "spawnflags" "1" } { "spawnflags" "1" "classname" "item_spikes" "origin" "-1760 1096 -144" } { "classname" "item_health" "origin" "-2032 144 -80" } { "spawnflags" "1" "classname" "monster_demon1" "origin" "-1664 1096 -120" "angle" "270" } { "classname" "light" "origin" "-2016 -48 -48" "light" "450" } { "sounds" "1" "classname" "func_door" "angle" "180" "speed" "400" "targetname" "t26" "wait" "15" "model" "*17" } { "sounds" "1" "classname" "func_door" "angle" "0" "speed" "400" "model" "*18" } { "light" "200" "classname" "light" "origin" "-672 416 -304" } { "style" "5" "classname" "light" "origin" "-648 128 -256" } { "classname" "trigger_teleport" "target" "t27" "model" "*19" } { "classname" "trigger_multiple" "target" "t26" "model" "*20" } { "angle" "180" "classname" "info_teleport_destination" "origin" "408 1120 -16" "targetname" "t27" } { "classname" "item_health" "origin" "824 800 -192" } { "classname" "item_shells" "origin" "784 1072 -24" "spawnflags" "1" } { "sounds" "3" "wait" "-1" "classname" "func_door" "angle" "-1" "targetname" "t32" "model" "*21" } { "spawnflags" "1" "classname" "item_spikes" "origin" "-240 1408 -112" } { "classname" "item_health" "origin" "-680 656 -272" } { "classname" "item_health" "origin" "-2176 64 -224" } { "classname" "item_health" "origin" "-2544 -304 -160" } { "classname" "item_health" "origin" "-2032 -144 -80" } { "classname" "item_shells" "origin" "-2432 -320 -160" "spawnflags" "1" } { "spawnflags" "1" "classname" "item_spikes" "origin" "-2032 -304 -80" } { "classname" "item_shells" "origin" "-1840 -816 2" "spawnflags" "1" } { "origin" "-992 -2636 56" "classname" "light" } { "classname" "light" "origin" "-356 -2016 56" } { "light" "500" "origin" "-976 -2016 184" "classname" "light" } { "origin" "-1216 -1792 -94" "classname" "light" } { "origin" "-768 -1792 -94" "classname" "light" } { "origin" "-768 -2240 -94" "classname" "light" } { "origin" "-1216 -2240 -94" "classname" "light" } { "target" "t49" "targetname" "t48" "origin" "-992 -1912 -232" "classname" "path_corner" } { "target" "t48" "targetname" "t49" "origin" "-992 -1608 -232" "classname" "path_corner" } { "target" "t47" "targetname" "t46" "classname" "path_corner" "origin" "-888 -2016 -232" } { "target" "t46" "targetname" "t47" "classname" "path_corner" "origin" "-584 -2016 -232" } { "target" "t43" "targetname" "t42" "origin" "-992 -2120 -232" "classname" "path_corner" } { "target" "t42" "targetname" "t43" "origin" "-992 -2424 -232" "classname" "path_corner" } { "target" "t45" "targetname" "t44" "classname" "path_corner" "origin" "-1112 -2016 -232" } { "target" "t44" "targetname" "t45" "classname" "path_corner" "origin" "-1400 -2016 -232" } { "origin" "-720 -2320 -256" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "-1296 -2320 -256" } { "origin" "-1296 -1744 -256" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "-720 -1744 -256" } { "angle" "-2" "classname" "func_door" "health" "1" "targetname" "t67" "wait" "-1" "sounds" "3" "model" "*22" } { "target" "t50" "classname" "trigger_teleport" "model" "*23" } { "targetname" "t50" "angle" "135" "origin" "-1632 -32 136" "classname" "info_teleport_destination" } { "spawnflags" "1" "origin" "-1504 448 -168" "classname" "item_spikes" } { "origin" "-2224 -1584 -128" "classname" "item_health" } { "target" "t52" "targetname" "t55" "origin" "-2616 -1032 -72" "classname" "path_corner" } { "target" "t51" "targetname" "t52" "classname" "path_corner" "origin" "-2680 -1336 -72" } { "target" "t53" "targetname" "t56" "origin" "-2056 -1336 -72" "classname" "path_corner" } { "target" "t56" "targetname" "t51" "origin" "-2336 -1432 -72" "classname" "path_corner" } { "target" "t54" "targetname" "t53" "origin" "-2056 -1032 -72" "classname" "path_corner" } { "target" "t55" "targetname" "t54" "origin" "-2336 -1280 -72" "classname" "path_corner" } { "target" "t57" "classname" "trigger_teleport" "model" "*24" } { "classname" "light" "origin" "-2336 -1568 -80" } { "angle" "270" "targetname" "t57" "origin" "-2336 -840 24" "classname" "info_teleport_destination" } { "sounds" "3" "targetname" "t32" "angle" "-1" "classname" "func_door" "wait" "-1" "model" "*25" } { "style" "2" "origin" "-864 320 -256" "classname" "light" } { "target" "t59" "classname" "trigger_teleport" "model" "*26" } { "wait" "-1" "sounds" "3" "health" "1" "angle" "0" "classname" "func_door" "model" "*27" } { "targetname" "t59" "angle" "0" "origin" "-1056 -192 -128" "classname" "info_teleport_destination" } { "origin" "512 272 -192" "classname" "item_spikes" } { "spawnflags" "1" "origin" "208 -656 -112" "classname" "item_spikes" } { "spawnflags" "1" "origin" "-2240 16 -224" "classname" "item_spikes" } { "origin" "136 -296 -128" "classname" "light" "light" "200" } { "health" "1" "angle" "-2" "classname" "func_door" "targetname" "t67" "wait" "-1" "sounds" "3" "model" "*28" } { "origin" "-480 -1984 -256" "classname" "item_rockets" } { "origin" "-480 -2080 -256" "classname" "item_rockets" } { "targetname" "t65" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*29" } { "speed" "10" "sounds" "3" "classname" "func_door" "angle" "180" "targetname" "t126" "wait" "-1" "model" "*30" } { "light" "600" "classname" "light" "origin" "-2336 -1152 168" } { "classname" "item_armor1" "origin" "336 1104 -24" } { "spawnflags" "2048" "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t67" "sounds" "3" "model" "*31" } { "sounds" "3" "angle" "90" "classname" "func_door" "model" "*32" } { "sounds" "3" "angle" "270" "classname" "func_door" "model" "*33" } { "sounds" "3" "angle" "270" "classname" "func_door" "model" "*34" } { "sounds" "3" "angle" "90" "classname" "func_door" "model" "*35" } { "light" "450" "origin" "-1696 536 -120" "classname" "light" } { "light" "400" "origin" "-1312 864 -248" "classname" "light" } { "light" "400" "origin" "-672 992 -234" "classname" "light" } { "light" "400" "origin" "-352 1120 -154" "classname" "light" } { "light" "400" "origin" "160 1120 -58" "classname" "light" } { "light" "400" "origin" "-1056 288 -240" "classname" "light" } { "light" "400" "origin" "-1440 -232 -120" "classname" "light" } { "origin" "-2016 -672 -48" "classname" "light" } { "light" "400" "origin" "-2136 -352 -120" "classname" "light" } { "light" "400" "origin" "-2464 -232 -200" "classname" "light" } { "light" "400" "origin" "-2464 296 -200" "classname" "light" } { "light" "400" "origin" "-2136 416 -120" "classname" "light" } { "light" "450" "origin" "-2016 112 -48" "classname" "light" } { "classname" "light" "origin" "608 -928 96" "light" "400" } { "classname" "light" "origin" "-128 288 64" "light" "200" } { "light" "200" "origin" "-256 288 64" "classname" "light" } { "classname" "light" "origin" "-352 352 80" "light" "200" } { "light" "200" "origin" "-288 -160 80" "classname" "light" } { "classname" "light" "origin" "-416 -608 80" "light" "200" } { "classname" "light" "origin" "-352 -1056 80" "light" "200" } { "light" "200" "origin" "96 -992 80" "classname" "light" } { "classname" "light" "origin" "-1056 -992 80" "light" "200" } { "classname" "light" "origin" "-32 -976 64" "light" "200" } { "light" "200" "origin" "-32 -1144 64" "classname" "light" } { "spawnflags" "768" "angle" "315" "origin" "320 136 24" "classname" "monster_tarbaby" } { "classname" "light" "origin" "672 -480 80" "light" "200" } { "classname" "item_health" "origin" "448 -16 0" } { "classname" "path_corner" "origin" "160 344 -152" "targetname" "t74" "target" "t75" } { "origin" "160 -248 -152" "classname" "path_corner" "targetname" "t75" "target" "t74" } { "classname" "path_corner" "origin" "648 -192 -168" "targetname" "t77" "target" "t76" } { "origin" "648 200 -168" "classname" "path_corner" "targetname" "t76" "target" "t77" } { "classname" "path_corner" "origin" "520 312 -168" "targetname" "t78" "target" "t79" } { "origin" "520 -280 -168" "classname" "path_corner" "targetname" "t79" "target" "t78" } { "lip" "0" "classname" "func_door" "angle" "90" "wait" "-1" "targetname" "t83" "model" "*36" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t82" "model" "*37" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t80" "model" "*38" } { "spawnflags" "2" "classname" "trigger_teleport" "target" "t81" "model" "*39" } { "delay" "4" "lip" "0" "targetname" "t83" "wait" "-1" "angle" "90" "classname" "func_door" "model" "*40" } { "classname" "info_teleport_destination" "origin" "648 -96 136" "targetname" "t80" "angle" "270" } { "classname" "info_teleport_destination" "origin" "432 224 136" "angle" "90" "targetname" "t81" } { "classname" "info_teleport_destination" "origin" "320 -24 136" "angle" "90" "targetname" "t82" } { "target" "t148" "classname" "trigger_once" "model" "*41" } { "origin" "288 480 -192" "classname" "item_spikes" } { "origin" "312 816 -168" "classname" "item_artifact_super_damage" } { "classname" "item_health" "origin" "592 -960 0" "spawnflags" "2" } { "classname" "func_button" "angle" "90" "wait" "-1" "target" "t6" "spawnflags" "2048" "model" "*42" } { "spawnflags" "768" "angle" "225" "origin" "1136 752 -168" "classname" "monster_hell_knight" } { "target" "t85" "classname" "monster_hell_knight" "origin" "16 752 -168" "angle" "315" } { "target" "t86" "targetname" "t85" "count" "3" "spawnflags" "1" "classname" "trigger_counter" "model" "*43" } { "spawnflags" "1536" "target" "t32" "angle" "-2" "classname" "func_button" "wait" "-1" "sounds" "1" "model" "*44" } { "target" "t32" "spawnflags" "2304" "classname" "trigger_once" "model" "*45" } { "origin" "664 1088 -128" "classname" "light" } { "classname" "light" "origin" "840 768 -128" "light" "200" } { "light" "200" "origin" "312 768 -128" "classname" "light" } { "classname" "light" "origin" "1176 704 -128" } { "origin" "-24 704 -128" "classname" "light" } { "classname" "light" "origin" "352 440 -128" } { "origin" "800 440 -128" "classname" "light" } { "light" "200" "origin" "576 864 -80" "classname" "light" } { "light" "200" "classname" "light" "origin" "352 1032 64" } { "light" "200" "origin" "800 1032 64" "classname" "light" } { "origin" "784 1168 -24" "classname" "item_spikes" } { "origin" "1120 1120 56" "classname" "light" } { "origin" "576 1208 64" "classname" "light" "light" "200" } { "origin" "-856 160 -304" "classname" "light" "light" "200" } { "origin" "-688 152 -176" "classname" "item_health" } { "origin" "-32 1160 -34" "classname" "light" } { "light" "200" "origin" "184 1032 46" "classname" "light" } { "targetname" "t87" "spawnflags" "1" "angle" "270" "origin" "-28 1204 -44" "classname" "trap_spikeshooter" } { "target" "t87" "classname" "trigger_multiple" "model" "*46" } { "origin" "-168 1376 -32" "classname" "light" "light" "200" } { "light" "200" "classname" "light" "origin" "-280 928 -32" } { "origin" "-728 1120 -96" "classname" "light" "light" "200" } { "light" "200" "origin" "-1112 672 -192" "classname" "light" } { "classname" "light" "origin" "-544 616 -192" "light" "200" } { "origin" "-448 608 -272" "classname" "item_rockets" } { "origin" "-1056 912 -248" "classname" "item_artifact_envirosuit" } { "target" "t89" "angle" "135" "origin" "-496 624 -248" "classname" "monster_tarbaby" } { "origin" "-672 480 -152" "classname" "item_artifact_super_damage" } { "light" "200" "origin" "-864 104 -120" "classname" "light" } { "angle" "270" "origin" "-1440 416 -136" "classname" "monster_tarbaby" } { "classname" "light" "origin" "-672 472 -120" "light" "200" } { "origin" "-752 -152 -136" "classname" "item_rockets" } { "classname" "item_armorInv" "origin" "-1255 -190 -136" } { "classname" "monster_demon1" "origin" "-1096 -96 -112" "angle" "90" "spawnflags" "769" } { "spawnflags" "1" "angle" "90" "origin" "-1016 -96 -112" "classname" "monster_demon1" } { "classname" "item_cells" "origin" "-704 -152 -136" "spawnflags" "1" } { "classname" "monster_hell_knight" "origin" "-880 -520 -112" "angle" "90" "spawnflags" "256" } { "angle" "90" "origin" "-776 -520 -112" "classname" "monster_hell_knight" "spawnflags" "768" } { "classname" "trigger_teleport" "target" "t59" "model" "*47" } { "classname" "trigger_teleport" "target" "t90" "model" "*48" } { "classname" "info_teleport_destination" "origin" "-928 -104 -128" "angle" "315" "targetname" "t90" } { "classname" "trigger_monsterjump" "angle" "90" "model" "*49" } { "classname" "monster_tarbaby" "origin" "-1496 336 -136" "angle" "270" "spawnflags" "768" } { "classname" "light" "origin" "-1056 -408 -64" "light" "200" } { "light" "200" "origin" "-1288 -200 -64" "classname" "light" } { "classname" "light" "origin" "-600 -224 -64" "light" "200" } { "light" "200" "origin" "-1056 32 -72" "classname" "light" } { "light" "200" "origin" "-1440 472 -120" "classname" "light" } { "classname" "light" "origin" "-1384 -352 0" "light" "200" } { "light" "200" "origin" "-1760 -408 0" "classname" "light" } { "classname" "light" "origin" "-1728 -200 32" "light" "200" } { "origin" "-2520 32 48" "classname" "light" } { "light" "400" "classname" "light" "origin" "-1768 32 48" } { "classname" "light" "origin" "-1640 1056 -72" } { "target" "t95" "targetname" "t94" "origin" "-1664 472 -56" "classname" "path_corner" } { "target" "t92" "targetname" "t95" "classname" "path_corner" "origin" "-2048 472 -56" } { "target" "t93" "targetname" "t92" "origin" "-2048 360 -56" "classname" "path_corner" } { "target" "t94" "targetname" "t93" "classname" "path_corner" "origin" "-1664 360 -56" } { "spawnflags" "256" "angle" "180" "origin" "-1992 472 -56" "classname" "monster_tarbaby" } { "classname" "monster_tarbaby" "origin" "-1712 360 -56" "angle" "0" "spawnflags" "768" } { "light" "200" "classname" "light" "origin" "-1640 416 -16" } { "light" "200" "origin" "-2016 472 -16" "classname" "light" } { "classname" "light" "origin" "-2520 352 -80" } { "origin" "-2160 32 -144" "classname" "light" } { "spawnflags" "1" "origin" "-2176 -32 -224" "classname" "item_shells" } { "origin" "-2440 -48 -16" "classname" "item_rockets" } { "classname" "trigger_secret" "model" "*50" } { "speed" "25" "wait" "-1" "lip" "-24" "angle" "-1" "classname" "func_door" "targetname" "t134" "model" "*51" } { "speed" "20" "lip" "-56" "wait" "-1" "angle" "-1" "classname" "func_door" "targetname" "t134" "model" "*52" } { "speed" "15" "angle" "-1" "wait" "-1" "lip" "-88" "classname" "func_door" "targetname" "t134" "model" "*53" } { "origin" "-2448 48 -224" "classname" "item_health" } { "classname" "monster_demon1" "origin" "-2504 -392 -136" "angle" "45" } { "classname" "monster_hell_knight" "origin" "-1976 -280 -56" "angle" "0" "target" "t104" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "-1488 -416 -56" "angle" "0" "target" "t106" } { "classname" "path_corner" "origin" "-1400 -280 -56" "targetname" "t107" "target" "t104" } { "origin" "-1400 -416 -56" "classname" "path_corner" "targetname" "t106" "target" "t107" } { "classname" "path_corner" "origin" "-2056 -416 -56" "targetname" "t105" "target" "t106" } { "origin" "-2056 -280 -56" "classname" "path_corner" "targetname" "t104" "target" "t105" } { "classname" "trigger_monsterjump" "angle" "180" "model" "*54" } { "classname" "trigger_monsterjump" "angle" "90" "speed" "400" "model" "*55" } { "classname" "monster_hell_knight" "origin" "808 720 -168" "angle" "180" "spawnflags" "256" } { "classname" "item_rockets" "origin" "528 592 32" "spawnflags" "1" } { "spawnflags" "1" "origin" "592 592 32" "classname" "item_rockets" } { "classname" "func_door_secret" "angle" "180" "spawnflags" "2" "model" "*56" } { "classname" "item_rockets" "origin" "-2256 -112 8" "spawnflags" "1" } { "spawnflags" "1" "origin" "-2256 144 8" "classname" "item_rockets" } { "angle" "180" "classname" "func_door_secret" "model" "*57" } { "classname" "monster_tarbaby" "origin" "-344 448 -72" "angle" "90" "spawnflags" "257" } { "angle" "90" "origin" "-256 448 -72" "classname" "monster_tarbaby" "spawnflags" "513" } { "classname" "monster_tarbaby" "origin" "-168 448 -72" "angle" "90" "spawnflags" "257" } { "targetname" "t122" "classname" "func_door" "angle" "-2" "wait" "-1" "lip" "80" "sounds" "3" "model" "*58" } { "targetname" "t122" "classname" "func_door" "sounds" "3" "angle" "-2" "wait" "-1" "lip" "16" "model" "*59" } { "classname" "monster_demon1" "origin" "-280 704 -168" "angle" "180" "spawnflags" "769" } { "spawnflags" "1" "angle" "180" "origin" "-200 632 -168" "classname" "monster_demon1" } { "speed" "600" "angle" "180" "classname" "trigger_monsterjump" "height" "100" "model" "*60" } { "classname" "item_rockets" "origin" "-176 712 -192" } { "classname" "item_cells" "origin" "-176 536 -192" "spawnflags" "1" } { "classname" "item_cells" "origin" "-304 528 -192" "spawnflags" "1" } { "sounds" "1" "classname" "trigger_secret" "model" "*61" } { "classname" "trigger_secret" "model" "*62" } { "classname" "trigger_secret" "model" "*63" } { "classname" "item_cells" "origin" "-1840 -224 -16" } { "classname" "item_artifact_super_damage" "origin" "-2464 -1568 -104" } { "origin" "-1584 -208 8" "classname" "item_artifact_super_damage" } { "classname" "item_health" "origin" "-1600 -128 -16" } { "origin" "-1808 16 -16" "classname" "item_health" } { "classname" "light" "origin" "-1768 -800 64" "light" "200" } { "light" "200" "origin" "-2208 -744 64" "classname" "light" } { "classname" "light" "origin" "-2400 -552 64" "light" "200" } { "classname" "func_button" "angle" "270" "wait" "-1" "target" "t119" "model" "*64" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "targetname" "t118" "model" "*65" } { "classname" "trigger_once" "target" "t118" "targetname" "t119" "model" "*66" } { "spawnflags" "1" "origin" "-656 -152 -136" "classname" "item_cells" } { "classname" "trigger_once" "health" "1" "target" "t65" "model" "*67" } { "spawnflags" "769" "angle" "90" "origin" "-2336 -1528 24" "classname" "monster_hell_knight" } { "classname" "light" "origin" "-2216 -1544 64" "light" "200" } { "classname" "light" "origin" "-2336 -2072 48" "light" "200" } { "light" "200" "origin" "-1952 -1960 48" "classname" "light" } { "classname" "light" "origin" "-1568 -2072 48" "light" "200" } { "classname" "light" "origin" "-1000 -2016 -128" } { "light" "200" "origin" "-928 -1376 80" "classname" "light" } { "spawnflags" "256" "targetname" "t86" "classname" "monster_tarbaby" "origin" "928 808 -168" "angle" "270" } { "spawnflags" "256" "classname" "trigger_monsterjump" "angle" "270" "model" "*68" } { "target" "t149" "classname" "light" "origin" "-2240 64 88" } { "target" "t150" "origin" "-2240 0 88" "classname" "light" } { "targetname" "t150" "classname" "info_null" "origin" "-2240 -56 36" } { "targetname" "t149" "origin" "-2240 120 36" "classname" "info_null" } { "classname" "monster_tarbaby" "origin" "-1696 -352 -56" "spawnflags" "768" "angle" "45" } { "spawnflags" "768" "origin" "-1792 -352 -56" "classname" "monster_tarbaby" "angle" "45" } { "wait" "0.5" "target" "t124" "classname" "trigger_multiple" "model" "*69" } { "classname" "light" "origin" "-864 728 -192" "light" "200" } { "light" "200" "origin" "-1056 920 -192" "classname" "light" } { "light" "400" "classname" "light" "origin" "-1504 864 -216" } { "classname" "light" "origin" "-672 864 -266" "light" "400" } { "light" "400" "origin" "-480 1120 -184" "classname" "light" } { "light" "400" "origin" "-32 1120 -104" "classname" "light" } { "light" "400" "origin" "-2272 416 -152" "classname" "light" } { "light" "400" "origin" "-2272 -352 -152" "classname" "light" } { "light" "400" "origin" "-1440 -32 -168" "classname" "light" } { "classname" "light" "origin" "-1960 -160 0" "light" "200" } { "light" "200" "origin" "-2072 224 0" "classname" "light" } { "spawnflags" "256" "angle" "90" "classname" "trigger_monsterjump" "model" "*70" } { "spawnflags" "256" "angle" "270" "classname" "trigger_monsterjump" "model" "*71" } { "targetname" "t147" "angle" "0" "spawnflags" "769" "origin" "-1576 104 152" "classname" "monster_tarbaby" } { "targetname" "t147" "angle" "0" "spawnflags" "769" "origin" "-1576 32 152" "classname" "monster_tarbaby" } { "spawnflags" "769" "targetname" "t147" "classname" "monster_tarbaby" "origin" "-1576 -40 152" "angle" "0" } { "target" "t122" "wait" "-1" "angle" "90" "classname" "func_button" "message" "A secret lurks in the hall \n of red brick." "model" "*72" } { "origin" "-2336 -1064 8" "classname" "light" } { "origin" "-2400 472 -80" "classname" "light" } { "target" "t134" "wait" "-1" "health" "1" "angle" "90" "classname" "func_button" "model" "*73" } { "targetname" "t124" "spawnflags" "1" "angle" "180" "origin" "1144 1120 8" "classname" "trap_spikeshooter" } { "angle" "0" "spawnflags" "768" "origin" "336 720 -168" "classname" "monster_tarbaby" } { "target" "t44" "origin" "-1248 -2016 -232" "classname" "monster_zombie" } { "target" "t48" "origin" "-992 -1768 -232" "classname" "monster_zombie" } { "target" "t46" "origin" "-744 -2016 -232" "classname" "monster_zombie" } { "target" "t42" "origin" "-992 -2272 -232" "classname" "monster_zombie" } { "target" "t125" "origin" "160 -160 -168" "classname" "monster_zombie" } { "spawnflags" "256" "target" "t125" "classname" "monster_zombie" "origin" "520 -152 -168" } { "target" "t125" "origin" "648 -40 -168" "classname" "monster_zombie" } { "spawnflags" "768" "target" "t77" "classname" "monster_zombie" "origin" "880 -48 24" } { "spawnflags" "768" "target" "t78" "origin" "880 24 24" "classname" "monster_zombie" } { "spawnflags" "768" "target" "t74" "classname" "monster_zombie" "origin" "880 96 24" } { "spawnflags" "256" "target" "t74" "origin" "808 96 24" "classname" "monster_zombie" } { "target" "t78" "classname" "monster_zombie" "origin" "808 24 24" } { "target" "t77" "origin" "808 -48 24" "classname" "monster_zombie" } { "light" "200" "classname" "light" "origin" "576 600 96" } { "spawnflags" "1" "target" "t83" "targetname" "t125" "count" "2" "classname" "trigger_counter" "model" "*74" } { "target" "t125" "angle" "315" "classname" "monster_zombie" "origin" "256 296 -168" } { "spawnflags" "768" "classname" "monster_hell_knight" "origin" "-408 -504 32" "angle" "270" "target" "t127" } { "classname" "monster_hell_knight" "origin" "-296 -368 32" "angle" "270" "target" "t131" } { "classname" "path_corner" "origin" "-408 64 32" "targetname" "t128" "target" "t127" } { "classname" "path_corner" "origin" "-296 192 32" "targetname" "t132" "target" "t131" } { "classname" "path_corner" "origin" "-408 -896 32" "targetname" "t127" "target" "t128" } { "classname" "path_corner" "origin" "-296 -768 32" "targetname" "t131" "target" "t132" } { "classname" "monster_tarbaby" "origin" "-128 -576 32" "angle" "180" "spawnflags" "256" } { "classname" "monster_tarbaby" "origin" "-784 -944 24" "spawnflags" "256" "angle" "0" } { "origin" "-704 -1024 24" "classname" "monster_tarbaby" "angle" "45" } { "spawnflags" "256" "classname" "monster_tarbaby" "origin" "-112 -944 24" "angle" "180" } { "classname" "monster_tarbaby" "origin" "-624 -944 24" "angle" "315" "spawnflags" "768" } { "classname" "monster_tarbaby" "origin" "-112 -1040 24" "spawnflags" "768" "angle" "135" } { "classname" "trigger_once" "health" "1" "target" "t133" "sounds" "3" "model" "*75" } { "classname" "trigger_counter" "targetname" "t133" "target" "t67" "model" "*76" } { "classname" "trigger_once" "health" "10" "target" "t133" "sounds" "3" "model" "*77" } { "classname" "trigger_secret" "model" "*78" } { "classname" "trigger_secret" "model" "*79" } { "classname" "item_rockets" "origin" "-1168 -2000 -256" } { "classname" "item_health" "origin" "-832 -2080 -256" } { "classname" "item_rockets" "origin" "-968 -1856 -256" } { "classname" "item_health" "origin" "-1048 -2336 -256" } { "classname" "item_artifact_super_damage" "origin" "-992 -2592 24" } { "classname" "trigger_secret" "model" "*80" } { "classname" "trigger_secret" "model" "*81" } { "classname" "item_health" "origin" "-1712 80 128" "spawnflags" "2" } { "classname" "item_artifact_invulnerability" "origin" "-352 -1952 24" } { "targetname" "t67" "classname" "trigger_teleport" "target" "t136" "model" "*82" } { "classname" "info_teleport_destination" "origin" "-1024 -1984 72" "targetname" "t136" "angle" "315" } { "spawnflags" "2048" "classname" "item_key1" "origin" "-992 -2016 -64" } { "classname" "item_artifact_invisibility" "origin" "1088 1120 0" } { "classname" "func_plat" "model" "*83" } { "classname" "trigger_monsterjump" "angle" "45" "speed" "400" "height" "300" "model" "*84" } { "height" "300" "speed" "400" "angle" "45" "classname" "trigger_monsterjump" "model" "*85" } { "classname" "trigger_monsterjump" "angle" "135" "speed" "400" "height" "300" "model" "*86" } { "height" "300" "speed" "400" "angle" "315" "classname" "trigger_monsterjump" "model" "*87" } { "height" "300" "speed" "400" "angle" "135" "classname" "trigger_monsterjump" "model" "*88" } { "classname" "trigger_monsterjump" "angle" "315" "speed" "400" "height" "300" "model" "*89" } { "height" "300" "speed" "400" "angle" "225" "classname" "trigger_monsterjump" "model" "*90" } { "classname" "trigger_monsterjump" "angle" "225" "speed" "400" "height" "300" "model" "*91" } { "classname" "weapon_rocketlauncher" "origin" "208 -1872 192" } { "classname" "weapon_supernailgun" "origin" "560 -1520 192" } { "classname" "item_artifact_super_damage" "origin" "576 -2208 216" } { "classname" "monster_shalrath" "origin" "288 -1856 216" "angle" "0" "target" "t140" "targetname" "t143" } { "origin" "864 -1856 216" "classname" "monster_shalrath" "angle" "180" "spawnflags" "256" "target" "t140" "targetname" "t143" } { "classname" "monster_shalrath" "origin" "576 -1568 216" "angle" "270" "spawnflags" "768" "target" "t140" "targetname" "t143" } { "origin" "576 -2144 216" "classname" "monster_shalrath" "angle" "90" "spawnflags" "768" "target" "t140" "targetname" "t143" } { "classname" "trigger_counter" "target" "t141" "count" "4" "spawnflags" "768" "targetname" "t140" "model" "*92" } { "classname" "trigger_counter" "target" "t141" "spawnflags" "1280" "targetname" "t140" "model" "*93" } { "classname" "trigger_once" "targetname" "t140" "target" "t141" "spawnflags" "1536" "model" "*94" } { "spawnflags" "2048" "classname" "func_door" "angle" "270" "wait" "-1" "sounds" "3" "model" "*95" } { "spawnflags" "2048" "classname" "func_door" "angle" "90" "targetname" "t141" "wait" "-1" "sounds" "3" "model" "*96" } { "style" "32" "classname" "light" "origin" "576 -1856 360" "light" "400" "targetname" "t142" "spawnflags" "1" } { "light" "200" "origin" "-64 -1312 80" "classname" "light" } { "classname" "light" "origin" "-64 -1824 80" "light" "200" } { "light" "200" "origin" "0 -1568 80" "classname" "light" } { "classname" "light" "origin" "576 -2208 288" } { "origin" "224 -1856 288" "classname" "light" } { "classname" "light" "origin" "576 -1504 288" } { "classname" "trigger_once" "target" "t143" "model" "*97" } { "target" "t144" "classname" "trigger_teleport" "model" "*98" } { "origin" "1024 -1856 80" "classname" "light" } { "mangle" "15 40 0" "origin" "-1328 -2256 160" "classname" "info_intermission" } { "targetname" "t144" "angle" "315" "origin" "328 -1608 328" "classname" "info_teleport_destination" } { "classname" "light" "origin" "-2016 -840 64" "light" "200" } { "target" "t146" "targetname" "t145" "origin" "-2536 32 16" "classname" "path_corner" } { "target" "t145" "targetname" "t146" "classname" "path_corner" "origin" "-1816 32 16" } { "spawnflags" "256" "target" "t145" "angle" "180" "origin" "-2016 32 8" "classname" "monster_shalrath" } { "angle" "135" "origin" "-1696 -160 8" "classname" "monster_shalrath" } { "target" "t161" "angle" "180" "origin" "-2144 -1984 32" "classname" "monster_shalrath" } { "spawnflags" "1" "target" "t162" "angle" "180" "origin" "-1656 32 152" "classname" "monster_shambler" } { "targetname" "t148" "wait" "-1" "speed" "1000" "angle" "-1" "classname" "func_door" "model" "*99" } { "angle" "90" "classname" "trigger_monsterjump" "model" "*100" } { "classname" "func_door" "lip" "-104" "wait" "-1" "angle" "-1" "speed" "15" "model" "*101" } { "speed" "15" "angle" "-1" "wait" "-1" "lip" "-120" "classname" "func_door" "model" "*102" } { "classname" "func_door" "lip" "-152" "wait" "-1" "angle" "-1" "speed" "15" "model" "*103" } { "light" "150" "origin" "-992 -2400 -200" "classname" "light" } { "light" "150" "classname" "light" "origin" "-608 -2016 -200" } { "origin" "-480 -2016 -200" "classname" "light" } { "origin" "352 -2080 72" "classname" "light" } { "classname" "light" "origin" "800 -2080 72" } { "origin" "800 -1632 72" "classname" "light" } { "classname" "light" "origin" "352 -1632 72" } { "origin" "928 -1856 288" "classname" "light" } { "origin" "-216 744 -56" "classname" "light" } { "classname" "light" "origin" "-216 472 -56" } { "origin" "-232 584 -56" "classname" "light" } { "classname" "light" "origin" "-488 904 -56" } { "origin" "-392 872 -56" "classname" "light" } { "light" "200" "origin" "-1600 32 192" "classname" "light" } { "classname" "trigger_secret" "model" "*104" } { "light" "200" "origin" "-256 -608 136" "classname" "light" } { "spawnflags" "1" "angle" "90" "origin" "-992 -2736 184" "classname" "monster_shalrath" } { "targetname" "t161" "spawnflags" "2048" "lip" "-88" "angle" "90" "classname" "func_door" "model" "*105" } { "spawnflags" "257" "angle" "180" "origin" "-456 -2016 32" "classname" "monster_shalrath" } { "light" "150" "origin" "-1376 -2016 -184" "classname" "light" } { "classname" "light" "origin" "-992 -1632 -184" "light" "150" } { "light" "200" "origin" "576 -1776 72" "classname" "light" } { "classname" "light" "origin" "576 -1936 72" "light" "200" } { "spawnflags" "256" "angle" "270" "origin" "-2400 -584 40" "classname" "monster_tarbaby" } { "classname" "monster_tarbaby" "origin" "-2352 -624 32" "angle" "270" "spawnflags" "768" } { "spawnflags" "768" "angle" "270" "origin" "-2456 -624 32" "classname" "monster_tarbaby" } { "spawnflags" "1" "origin" "-608 -152 -136" "classname" "item_spikes" } { "origin" "-1976 -32 8" "classname" "item_artifact_invisibility" } { "origin" "-2072 80 -16" "classname" "item_shells" } { "origin" "-2544 -48 -16" "classname" "item_cells" } { "target" "t155" "origin" "-1872 -832 40" "classname" "monster_hell_knight" } { "spawnflags" "768" "target" "t153" "classname" "monster_hell_knight" "origin" "-2224 -736 32" } { "target" "t154" "targetname" "t153" "origin" "-2304 -736 24" "classname" "path_corner" } { "target" "t153" "targetname" "t156" "classname" "path_corner" "origin" "-1792 -736 24" } { "target" "t156" "targetname" "t155" "origin" "-1792 -832 24" "classname" "path_corner" } { "target" "t155" "targetname" "t154" "classname" "path_corner" "origin" "-2304 -832 24" } { "classname" "info_intermission" "origin" "-2480 -1296 0" "mangle" "-30 55 0" } { "classname" "info_intermission" "origin" "160 272 -48" "mangle" "10 265 0" } { "classname" "info_intermission" "origin" "-352 -768 64" "mangle" "-25 110 0" } { "origin" "1312 -1952 112" "classname" "light" } { "classname" "light" "origin" "1312 -1760 112" } { "targetname" "t118" "angle" "90" "classname" "func_door" "model" "*106" } { "angle" "90" "origin" "608 -1136 24" "classname" "info_player_deathmatch" } { "angle" "225" "origin" "320 0 120" "classname" "info_player_deathmatch" } { "angle" "135" "origin" "648 -2160 216" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "208 168 -192" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "608 -488 0" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "-992 -2072 -88" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "-992 -1952 -280" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "-2336 -2016 0" "classname" "weapon_supershotgun" } { "angle" "90" "origin" "-1056 -2656 32" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "96 608 -192" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "1056 608 -192" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "576 1056 -192" "classname" "weapon_grenadelauncher" } { "angle" "270" "origin" "-224 1360 -88" "classname" "info_player_deathmatch" } { "classname" "weapon_rocketlauncher" "spawnflags" "1792" "origin" "-655 -230 -136" } { "angle" "270" "origin" "-992 920 -248" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "-1888 32 -16" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "-2336 -1128 64" "classname" "weapon_supernailgun" } { "angle" "315" "origin" "-2464 -544 32" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "origin" "-2328 -1376 -128" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "-1632 88 128" "classname" "weapon_rocketlauncher" } { "map" "start" "classname" "trigger_changelevel" "model" "*107" } { "target" "t157" "classname" "trigger_teleport" "model" "*108" } { "targetname" "t157" "origin" "1456 -1876 184" "classname" "info_teleport_destination" } { "spawnflags" "1" "targetname" "t159" "angle" "0" "origin" "-232 -2072 184" "classname" "monster_shambler" } { "target" "t159" "classname" "trigger_once" "model" "*109" } { "angle" "90" "origin" "672 -1080 24" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "544 -1072 24" "angle" "90" } { "angle" "90" "origin" "752 -1024 24" "classname" "info_player_coop" } { "spawnflags" "1" "origin" "120 -64 -16" "classname" "item_cells" } { "origin" "504 -112 -192" "classname" "item_cells" } { "origin" "800 512 -192" "classname" "item_cells" } { "origin" "928 1184 -24" "classname" "item_cells" } { "spawnflags" "1" "origin" "-2528 80 -16" "classname" "item_spikes" } { "spawnflags" "256" "target" "t55" "origin" "-2608 -976 -88" "classname" "monster_fish" } { "target" "t51" "origin" "-2392 -1424 -56" "classname" "monster_fish" } { "spawnflags" "256" "target" "t53" "origin" "-2040 -1096 -56" "classname" "monster_fish" } { "target" "t54" "origin" "-2264 -1280 -56" "classname" "monster_fish" } { "spawnflags" "256" "angle" "225" "origin" "-784 -1680 -160" "classname" "monster_fish" } { "spawnflags" "256" "angle" "45" "origin" "-1200 -2320 -160" "classname" "monster_fish" } { "spawnflags" "256" "angle" "135" "classname" "monster_fish" "origin" "-760 -2352 -160" } { "angle" "315" "classname" "monster_fish" "origin" "-1216 -1672 -128" "spawnflags" "256" } { "spawnflags" "1792" "classname" "func_wall" "model" "*110" } { "spawnflags" "256" "origin" "-688 -1200 24" "classname" "monster_shalrath" } { "height" "100" "angle" "180" "classname" "trigger_monsterjump" "model" "*111" } { "height" "100" "angle" "90" "classname" "trigger_monsterjump" "model" "*112" } { "classname" "trigger_relay" "origin" "-1656 176 136" "targetname" "t162" "target" "t147" } { "origin" "98 -286 -16" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "10 82 -16" } { "origin" "298 2 -16" "classname" "ambient_drip" } { "classname" "ambient_drip" "origin" "434 242 -16" } { "origin" "634 -126 -16" "classname" "ambient_drip" } { "origin" "-2334 -1190 32" "classname" "ambient_swamp1" } { "origin" "-1230 -1766 -64" "classname" "ambient_swamp1" } { "classname" "ambient_swamp1" "origin" "-1230 -2254 -64" } { "origin" "-750 -1774 -64" "classname" "ambient_swamp2" } { "classname" "ambient_swamp2" "origin" "-750 -2254 -64" } // ================================ // begin extra BSP entity list for e4m7 // ================================ { "classname" "item_flag_team2" "origin" "928 -1877 192" } { "angle" "90" "classname" "item_flag_team1" "origin" "-1032 -365 -136" } { "classname" "info_player_team1" "origin" "-972 -425 -112" } { "classname" "info_player_team1" "origin" "-972 -365 -112" } { "classname" "info_player_team1" "origin" "-972 -305 -112" } { "classname" "info_player_team1" "origin" "-1032 -365 -112" } { "classname" "info_player_team1" "origin" "-1032 -305 -112" } { "classname" "info_player_team1" "origin" "-1092 -365 -112" } { "classname" "info_player_team1" "origin" "-1092 -305 -112" } { "classname" "info_player_team2" "origin" "988 -1877 216" } { "classname" "info_player_team2" "origin" "928 -1937 216" } { "classname" "info_player_team2" "origin" "928 -1877 216" } { "classname" "info_player_team2" "origin" "928 -1817 216" } { "classname" "info_player_team2" "origin" "868 -1937 216" } { "classname" "info_player_team2" "origin" "868 -1877 216" } { "classname" "info_player_team2" "origin" "868 -1817 216" } // ================================ // end extra BSP entity list for e4m7 // ================================ QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/e4m8.ent000066400000000000000000001044351475442401000252100ustar00rootroot00000000000000{ "sounds" "10" "message" "the Nameless City" "wad" "gfx/medieval.wad" "classname" "worldspawn" "worldtype" "0" } { "classname" "info_player_start" "origin" "-448 720 -104" "angle" "270" } { "classname" "light" "origin" "1280 776 160" "angle" "0" } { "classname" "light" "origin" "1280 744 160" "angle" "0" } { "classname" "light" "origin" "1024 488 256" "angle" "0" } { "classname" "light_torch_small_walltorch" "origin" "1480 504 144" "angle" "0" } { "classname" "light" "origin" "1800 160 208" "angle" "0" } { "classname" "light" "origin" "2208 776 128" "angle" "0" } { "classname" "light" "origin" "1312 1080 160" "angle" "0" } { "classname" "light" "origin" "1024 1080 96" "angle" "0" } { "classname" "light" "origin" "1312 1112 160" "angle" "0" } { "classname" "light" "origin" "1024 1112 96" "angle" "0" } { "classname" "light" "origin" "1696 1080 160" "angle" "0" } { "classname" "light" "origin" "2368 928 192" "angle" "0" } { "classname" "light" "origin" "2496 232 96" "angle" "0" } { "classname" "path_corner" "origin" "448 704 32" "angle" "0" "targetname" "t42" "target" "t43" } { "classname" "path_corner" "origin" "232 984 32" "angle" "0" "targetname" "t43" "target" "t44" } { "classname" "path_corner" "origin" "256 704 32" "angle" "0" "targetname" "t44" "target" "t42" } { "classname" "path_corner" "origin" "128 224 -96" "angle" "0" "targetname" "t50" "target" "t256" } { "classname" "path_corner" "origin" "-376 64 -96" "angle" "0" "targetname" "t51" "target" "t61" } { "classname" "light" "origin" "1664 776 96" "angle" "0" } { "classname" "light" "origin" "1664 744 96" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "600 480 -352" "angle" "315" } { "classname" "info_player_deathmatch" "origin" "-224 740 -88" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "1952 -720 24" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1856 816 40" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1048 376 136" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "1468 724 160" "angle" "90" } { "classname" "func_plat" "targetname" "t38" "sounds" "2" "model" "*1" } { "classname" "func_plat" "sounds" "2" "model" "*2" } { "sounds" "2" "classname" "func_plat" "targetname" "t54" "height" "112" "model" "*3" } { "classname" "monster_ogre" "origin" "350 814 24" "angle" "315" "target" "t44" "spawnflags" "768" } { "classname" "item_health" "origin" "416 1120 0" } { "classname" "item_health" "origin" "656 536 0" } { "classname" "item_health" "origin" "2132 368 0" "spawnflags" "2" } { "classname" "item_health" "origin" "1712 432 160" "spawnflags" "1" } { "target" "t259" "classname" "item_health" "origin" "1936 -368 80" "spawnflags" "1" } { "classname" "func_door_secret" "spawnflags" "9" "angle" "90" "targetname" "t60" "sounds" "1" "model" "*4" } { "classname" "monster_ogre" "origin" "902 526 120" "target" "t226" "spawnflags" "768" } { "classname" "path_corner" "origin" "128 64 -96" "target" "t50" "targetname" "t61" } { "origin" "800 744 96" "classname" "light" } { "origin" "800 776 96" "classname" "light" } { "spawnflags" "1" "origin" "960 624 0" "classname" "item_health" } { "light" "200" "origin" "1888 72 48" "classname" "light" } { "light" "200" "origin" "2016 8 208" "classname" "light" } { "origin" "2104 384 208" "classname" "light" } { "light" "200" "origin" "1888 40 48" "classname" "light" } { "light" "200" "origin" "2016 -40 208" "classname" "light" } { "style" "32" "light" "250" "classname" "light" "origin" "1696 1112 160" "targetname" "t237" } { "style" "32" "light" "250" "classname" "light" "origin" "2080 1112 160" "targetname" "t237" } { "classname" "light" "origin" "2080 1080 160" } { "classname" "light" "origin" "1416 288 48" } { "classname" "item_health" "origin" "2288 160 0" "spawnflags" "1" } { "classname" "item_health" "origin" "2288 -56 0" "spawnflags" "1" } { "classname" "item_spikes" "origin" "2064 -144 0" } { "classname" "item_health" "origin" "1544 -304 80" } { "classname" "item_spikes" "origin" "2064 608 0" } { "classname" "light" "origin" "1952 568 208" } { "classname" "light" "origin" "1952 600 208" } { "classname" "light" "origin" "-448 320 -32" } { "light" "350" "classname" "light" "origin" "-448 768 -40" } { "classname" "light" "origin" "1768 160 208" } { "classname" "item_shells" "origin" "1736 608 160" "spawnflags" "1" } { "origin" "1120 384 0" "classname" "item_spikes" } { "origin" "1152 256 0" "classname" "item_health" } { "spawnflags" "1" "origin" "1248 256 0" "classname" "item_shells" } { "origin" "2928 280 80" "classname" "item_rockets" } { "target" "t38" "angle" "90" "classname" "func_button" "sounds" "2" "model" "*5" } { "wait" "-1" "target" "t60" "angle" "0" "classname" "func_button" "sounds" "2" "model" "*6" } { "spawnflags" "2064" "wait" "-1" "classname" "func_door" "angle" "180" "sounds" "1" "model" "*7" } { "classname" "monster_ogre" "origin" "1342 374 120" "angle" "270" "target" "t224" } { "classname" "item_shells" "origin" "1048 624 0" } { "classname" "func_door_secret" "angle" "90" "model" "*8" } { "dmg" "50" "height" "1008" "targetname" "t173" "speed" "300" "classname" "func_plat" "sounds" "2" "model" "*9" } { "target" "t173" "angle" "90" "classname" "func_button" "wait" "-1" "sounds" "2" "model" "*10" } { "origin" "560 912 0" "classname" "item_health" } { "origin" "-528 48 -128" "classname" "item_health" } { "origin" "-464 48 -128" "classname" "item_shells" } { "origin" "1584 640 0" "classname" "item_health" } { "origin" "1632 688 0" "classname" "item_health" } { "origin" "1112 336 472" "classname" "light" } { "angle" "0" "origin" "944 376 368" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "classname" "weapon_grenadelauncher" "origin" "-448 128 0" } { "angle" "90" "origin" "1480 184 26" "classname" "monster_demon1" } { "spawnflags" "1792" "origin" "352 1184 0" //Q-Man "classname" "weapon_supernailgun" } { "sounds" "1" "target" "t54" "wait" "-1" "angle" "-2" "classname" "func_button" "lip" "4" "model" "*11" } { "origin" "1194 138 228" "classname" "light_torch_small_walltorch" } { "origin" "648 928 192" "classname" "light" } { "classname" "trigger_once" "target" "t189" "model" "*12" } { "spawnflags" "256" "classname" "monster_demon1" "origin" "1408 1024 24" "target" "t183" } { "spawnflags" "256" "angle" "225" "classname" "monster_demon1" "origin" "1704 1024 24" "targetname" "t189" } { "angle" "135" "classname" "monster_demon1" "origin" "1704 856 24" "targetname" "t189" "spawnflags" "768" } { "classname" "path_corner" "origin" "960 1024 24" "targetname" "t183" "target" "t184" } { "origin" "1456 1024 24" "classname" "path_corner" "targetname" "t184" "target" "t183" } { "classname" "trigger_multiple" "wait" "1" "target" "t192" "model" "*13" } { "classname" "trap_spikeshooter" "origin" "1808 -16 48" "targetname" "t192" "angle" "0" "wait" "2" "spawnflags" "256" } { "spawnflags" "1" "classname" "monster_demon1" "origin" "2432 -568 104" "angle" "180" "targetname" "t192" } { "targetname" "t212" "classname" "monster_zombie" "origin" "1936 1240 28" "angle" "0" "spawnflags" "768" } { "targetname" "t212" "classname" "monster_zombie" "origin" "1792 1136 28" "angle" "180" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "2216 424 24" "angle" "90" } { "classname" "light" "origin" "1200 416 -576" "light" "400" } { "classname" "func_door" "angle" "-2" "lip" "-185" "targetname" "t194" "wait" "-1" "sounds" "1" "model" "*14" } { "targetname" "t210" "classname" "func_plat" "height" "112" "model" "*15" } { "classname" "func_door" "angle" "-1" "wait" "-1" "targetname" "t197" "sounds" "1" "model" "*16" } { "classname" "info_teleport_destination" "origin" "936 648 104" "angle" "225" "targetname" "t196" } { "spawnflags" "1792" "classname" "weapon_grenadelauncher" //Q-Man "origin" "608 416 -384" } { "classname" "item_health" "origin" "528 464 -384" } { "spawnflags" "256" "classname" "func_button" "angle" "-2" "target" "t211" "sounds" "3" "model" "*17" } { "target" "t199" "classname" "trigger_once" "model" "*18" } { "targetname" "t199" "classname" "func_door" "angle" "-2" "wait" "-1" "spawnflags" "256" "model" "*19" } { "spawnflags" "1" "angle" "180" "origin" "2590 -546 104" "classname" "monster_ogre" } { "spawnflags" "257" "origin" "1310 -546 104" "classname" "monster_ogre" } { "angle" "180" "origin" "1470 910 152" "classname" "monster_ogre" "targetname" "t189" } { "origin" "1648 640 0" "classname" "item_rockets" } { "angle" "225" "target" "t256" "origin" "-328 192 -104" "classname" "monster_zombie" } { "angle" "270" "target" "t51" "classname" "monster_zombie" "origin" "-368 112 -104" } { "angle" "225" "target" "t50" "classname" "monster_zombie" "origin" "200 224 -80" "spawnflags" "768" } { "origin" "1024 280 328" "classname" "light" } { "origin" "1482 538 196" "classname" "light_torch_small_walltorch" } { "targetname" "t209" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*20" } { "angle" "270" "target" "t209" "classname" "func_button" "sounds" "2" "model" "*21" } { "light" "600" "origin" "2064 -680 272" "classname" "light" } { "targetname" "t234" "angle" "180" "origin" "1408 368 -888" "classname" "monster_zombie" } { "targetname" "t234" "angle" "0" "origin" "1344 416 -888" "classname" "monster_zombie" "spawnflags" "768" } { "targetname" "t234" "angle" "90" "origin" "1184 576 -888" "classname" "monster_zombie" } { "targetname" "t234" "angle" "270" "origin" "1184 256 -888" "classname" "monster_zombie" "spawnflags" "768" } { "origin" "1168 248 -584" "classname" "item_armor2" } { "origin" "1384 808 152" "classname" "item_key2" "sounds" "2" "spawnflags" "2048" } { "angle" "0" "origin" "1688 1352 28" "classname" "monster_demon1" } { "spawnflags" "256" "dmg" "75" "targetname" "t211" "wait" "1.5" "speed" "300" "lip" "64" "angle" "-2" "classname" "func_door" "sounds" "1" "model" "*22" } { "target" "t212" "classname" "trigger_once" "model" "*23" } { "targetname" "t212" "angle" "-2" "classname" "func_door" "wait" "-1" "sounds" "3" "model" "*24" } { "targetname" "t212" "angle" "45" "origin" "1920 1128 28" "classname" "monster_zombie" } { "targetname" "t212" "angle" "-2" "classname" "func_door" "wait" "-1" "sounds" "3" "model" "*25" } { "classname" "light" "origin" "648 384 160" } { "origin" "1952 -824 156" "classname" "light" } { "origin" "1568 -208 160" "classname" "light" } { "origin" "2336 -200 160" "classname" "light" } { "angle" "0" "origin" "1768 928 160" "classname" "light" } { "classname" "light" "origin" "1800 928 160" "angle" "0" } { "wait" "-1" "targetname" "t215" "angle" "-1" "classname" "func_door" "sounds" "3" "model" "*26" } { "wait" "-1" "targetname" "t214" "classname" "func_door" "angle" "-1" "sounds" "3" "model" "*27" } { "targetname" "t213" "wait" "12" "spawnflags" "1" "angle" "-1" "classname" "func_door" "sounds" "1" "model" "*28" } { "target" "t213" "classname" "trigger_once" "model" "*29" } { "target" "t215" "delay" "3" "targetname" "t213" "classname" "trigger_once" "model" "*30" } { "target" "t214" "delay" "7" "targetname" "t213" "classname" "trigger_once" "model" "*31" } { "targetname" "t214" "origin" "2088 1952 -104" "classname" "monster_zombie" } { "targetname" "t214" "origin" "2088 1888 -104" "classname" "monster_zombie" "spawnflags" "768" } { "targetname" "t214" "origin" "2088 1824 -104" "classname" "monster_zombie" } { "spawnflags" "256" "targetname" "t215" "origin" "1672 1824 -104" "classname" "monster_zombie" "angle" "180" } { "targetname" "t215" "origin" "1688 1888 -104" "classname" "monster_zombie" "spawnflags" "512" } { "targetname" "t215" "origin" "1688 1952 -104" "classname" "monster_zombie" } { "origin" "1616 1936 -128" "classname" "item_rockets" } { "origin" "2128 1808 -128" "classname" "item_spikes" } { "target" "t216" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*32" } { "targetname" "t216" "classname" "func_plat" "model" "*33" } { "spawnflags" "1" "origin" "2584 1584 -128" "classname" "item_health" } { "spawnflags" "1" "origin" "2584 1328 -128" "classname" "item_health" } { "target" "t217" "classname" "trigger_once" "model" "*34" } { "spawnflags" "256" "angle" "315" "origin" "1952 1024 24" "classname" "monster_demon1" } { "spawnflags" "256" "angle" "270" "origin" "2208 704 26" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "270" "origin" "2280 704 26" "classname" "monster_zombie" } { "origin" "1888 1944 -128" "classname" "item_armor1" } { "origin" "960 704 0" "classname" "item_shells" } { "classname" "path_corner" "origin" "1040 600 -680" "targetname" "t220" "target" "t221" } { "classname" "path_corner" "origin" "1040 232 -680" "target" "t220" "targetname" "t221" } { "origin" "1296 232 -680" "classname" "path_corner" "targetname" "t222" "target" "t223" } { "classname" "path_corner" "origin" "1296 600 -680" "targetname" "t223" "target" "t222" } { "origin" "2032 -912 256" "classname" "item_health" } { "origin" "1840 -912 256" "classname" "item_rockets" } { "origin" "1104 -896 -192" "classname" "item_spikes" } { "height" "120" "classname" "func_plat" "sounds" "2" "model" "*35" } { "height" "120" "classname" "func_plat" "sounds" "2" "model" "*36" } { "height" "120" "classname" "func_plat" "sounds" "2" "model" "*37" } { "height" "120" "classname" "func_plat" "sounds" "2" "model" "*38" } { "origin" "1552 200 -704" "classname" "item_shells" } { "origin" "2312 1616 -144" "classname" "light" } { "classname" "light" "origin" "2312 1528 -144" } { "angle" "0" "origin" "2208 744 128" "classname" "light" } { "classname" "monster_ogre" "origin" "1990 390 152" "angle" "135" } { "classname" "path_corner" "origin" "1344 296 120" "targetname" "t224" "target" "t225" } { "classname" "path_corner" "origin" "1344 696 120" "targetname" "t225" "target" "t224" } { "classname" "path_corner" "origin" "840 528 120" "targetname" "t226" "target" "t227" } { "classname" "path_corner" "origin" "1272 528 120" "targetname" "t227" "target" "t226" } { "classname" "monster_zombie" "origin" "1040 552 -680" "target" "t220" } { "classname" "monster_zombie" "origin" "1296 288 -680" "target" "t222" } { "classname" "monster_zombie" "origin" "2072 -8 24" "angle" "0" } { "origin" "376 144 -64" "classname" "light" } { "origin" "32 264 -64" "classname" "light" } { "origin" "896 856 -848" "classname" "light" } { "origin" "1192 1184 -832" "classname" "light" } { "origin" "1888 1520 -64" "classname" "light" } { "origin" "2312 1440 96" "classname" "light" } { "origin" "2592 1632 96" "classname" "light" } { "origin" "2592 1056 96" "classname" "light" } { "origin" "2592 736 96" "classname" "light" } { "light" "50" "origin" "2352 736 232" "classname" "light" } { "origin" "1632 288 -608" "classname" "light" } { "origin" "1504 -80 80" "classname" "light" } { "origin" "1248 0 416" "classname" "light" } { "origin" "1120 -1088 320" "classname" "light" } { "origin" "1120 -288 -224" "classname" "light" } { "classname" "light" "origin" "1568 -416 -352" } { "light" "150" "origin" "1472 856 88" "classname" "light" } { "classname" "light" "origin" "1744 0 80" } { "light" "100" "origin" "2080 336 80" "classname" "light" } { "origin" "352 1256 112" "classname" "light" } { "light" "100" "origin" "1120 464 72" "classname" "light" } { "origin" "1184 152 -608" "classname" "light" } { "target" "t210" "angle" "270" "classname" "func_button" "sounds" "2" "wait" "-1" "model" "*39" } { "light" "100" "origin" "2048 688 40" "classname" "light" "target" "t275" } { "classname" "light" "origin" "1856 640 40" "light" "150" "target" "t274" } { "origin" "1088 -640 -232" "classname" "light" } { "light" "150" "origin" "2360 64 72" "classname" "light" } { "classname" "light" "origin" "1824 -456 272" "light" "600" } { "light" "100" "origin" "1056 280 136" "classname" "light" } { "classname" "light" "origin" "984 280 136" "light" "100" } { "origin" "1352 248 96" "classname" "item_health" } { "classname" "item_health" "origin" "1352 288 340" } { "angle" "315" "origin" "968 448 364" "classname" "monster_shambler" } { "origin" "1002 554 44" "classname" "light_torch_small_walltorch" } { "origin" "752 408 -136" "classname" "light" } { "origin" "1218 426 52" "classname" "light_torch_small_walltorch" } { "classname" "light" "origin" "1056 -800 -128" } { "classname" "light" "origin" "1064 672 72" "light" "100" } { "light" "150" "origin" "928 1248 -864" "classname" "light" } { "classname" "light" "origin" "1568 480 -608" } { "classname" "light" "origin" "1632 0 -512" } { "origin" "1408 -288 -352" "classname" "light" } { "light" "400" "origin" "1952 -1024 144" "classname" "light" } { "target" "t243" "classname" "trigger_teleport" "model" "*40" } { "targetname" "t231" "classname" "info_teleport_destination" "origin" "1952 -875 88" //Q-Man "angle" "90" } { "targetname" "t259" "angle" "0" "origin" "1952 -888 104" "classname" "monster_demon1" "spawnflags" "769" } { "style" "33" "spawnflags" "1" "light" "200" "targetname" "t234" "origin" "1184 200 -872" "classname" "light" } { "style" "34" "target" "t258" "light" "300" "targetname" "t197" "origin" "904 416 -872" "classname" "light" } { "style" "33" "spawnflags" "1" "light" "200" "targetname" "t234" "origin" "1400 416 -872" "classname" "light" } { "style" "33" "spawnflags" "1" "targetname" "t234" "light" "300" "origin" "1256 960 -848" "classname" "light" } { "origin" "1280 400 -584" "classname" "item_shells" } { "style" "35" "targetname" "t213" "light" "400" "origin" "1888 1928 -64" "classname" "light" } { "style" "36" "spawnflags" "1" "targetname" "t215" "light" "250" "origin" "1608 1952 -72" "classname" "light" } { "style" "36" "spawnflags" "1" "targetname" "t215" "light" "250" "classname" "light" "origin" "1608 1888 -72" } { "style" "36" "spawnflags" "1" "targetname" "t215" "light" "250" "origin" "1608 1824 -72" "classname" "light" } { "style" "37" "spawnflags" "1" "targetname" "t214" "light" "250" "classname" "light" "origin" "2168 1824 -72" } { "style" "37" "spawnflags" "1" "targetname" "t214" "light" "250" "origin" "2168 1888 -72" "classname" "light" } { "style" "37" "spawnflags" "1" "targetname" "t214" "light" "250" "classname" "light" "origin" "2168 1952 -72" } { "origin" "1616 1808 -128" "classname" "item_shells" } { "spawnflags" "1" "origin" "2128 1936 -128" "classname" "item_health" } { "style" "32" "light" "250" "origin" "1888 1440 96" "classname" "light" "targetname" "t237" } { "style" "32" "light" "250" "origin" "1584 1376 96" "classname" "light" "targetname" "t237" } { "angle" "0" "origin" "2496 200 96" "classname" "light" } { "origin" "3024 288 160" "classname" "light" } { "origin" "3032 672 224" "classname" "light" } { "origin" "608 1080 96" "classname" "light" } { "origin" "200 928 96" "classname" "light" } { "target" "t194" "classname" "func_button" "wait" "-1" "model" "*41" } { "classname" "light" "origin" "2136 384 208" } { "classname" "item_health" "origin" "304 48 -128" } { "spawnflags" "1" "origin" "1456 832 16" "classname" "item_spikes" } { "classname" "item_health" "origin" "1104 840 -904" "spawnflags" "1" } { "classname" "trigger_once" "targetname" "t194" "target" "t234" "delay" "3" "model" "*42" } { "classname" "monster_zombie" "origin" "960 680 24" "angle" "180" } { "classname" "monster_zombie" "origin" "1448 32 24" "angle" "45" } { "classname" "monster_zombie" "origin" "1584 -88 24" "angle" "45" } { "classname" "monster_zombie" "origin" "1632 440 24" "angle" "270" } { "classname" "monster_zombie" "origin" "1712 688 24" "angle" "270" } { "style" "32" "classname" "light" "origin" "1864 1120 160" "light" "200" "spawnflags" "1" "targetname" "t237" } { "style" "32" "spawnflags" "1" "light" "200" "origin" "1912 1120 160" "classname" "light" "targetname" "t237" } { "classname" "monster_zombie" "origin" "1984 1184 28" "angle" "45" "targetname" "t212" } { "classname" "monster_zombie" "origin" "1856 1240 28" "angle" "180" } { "classname" "func_button" "angle" "0" "wait" "1" "target" "t238" "model" "*43" } { "style" "32" "classname" "trigger_multiple" "target" "t237" "targetname" "t238" "model" "*44" } { "style" "32" "classname" "trigger_once" "target" "t238" "targetname" "t212" "model" "*45" } { "classname" "light" "origin" "2416 1312 96" } { "classname" "item_armorInv" "origin" "1152 176 168" } { "classname" "light" "origin" "2960 968 240" } { "classname" "monster_zombie" "origin" "1568 -16 -552" "angle" "90" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "1568 -320 -424" "angle" "90" } { "classname" "monster_ogre" "origin" "1510 6 -424" "angle" "270" "spawnflags" "768" } { "classname" "item_health" "origin" "1040 160 -912" } { "classname" "item_rockets" "origin" "1136 944 -904" } { "classname" "trigger_once" "target" "t217" "model" "*46" } { "spawnflags" "768" "angle" "45" "origin" "2280 384 24" "classname" "monster_zombie" } { "classname" "func_illusionary" "model" "*47" } { "classname" "light" "origin" "1952 -936 320" "light" "300" } { "origin" "1224 -1864 152" "classname" "light" } { "classname" "light" "origin" "1608 -1912 152" } { "origin" "1720 -1592 152" "classname" "light" } { "classname" "light" "origin" "1336 -1544 152" } { "light" "200" "origin" "1792 -1344 40" "classname" "light" } { "target" "t261" "classname" "monster_demon1" "origin" "1312 -2080 24" "angle" "45" } { "angle" "90" "origin" "1760 -1944 24" "classname" "monster_demon1" "target" "t261" } { "target" "t261" "classname" "monster_demon1" "origin" "992 -1904 24" "angle" "45" } { "angle" "225" "targetname" "t243" "origin" "1760 -1376 260" "classname" "info_teleport_destination" //Q-Man } { "angle" "180" "origin" "2872 -1280 24" "classname" "monster_shambler" "target" "t249" "targetname" "t268" } { "target" "t244" "classname" "trigger_teleport" "spawnflags" "2" "model" "*48" } { "targetname" "t244" "angle" "45" "origin" "1472 -1728 184" "classname" "info_teleport_destination" } { "classname" "trigger_teleport" "target" "t231" "model" "*49" } { "classname" "light" "origin" "1472 -2304 64" "light" "200" } { "spawnflags" "2048" "classname" "func_door_secret" "angle" "0" "wait" "-1" "targetname" "t249" "sounds" "1" "model" "*50" } { "classname" "item_rockets" "origin" "1136 -1368 0" "spawnflags" "1" } { "classname" "item_health" "origin" "2032 -1744 0" } { "classname" "item_spikes" "origin" "1136 -2128 0" "spawnflags" "1" } { "classname" "item_health" "origin" "880 -1744 0" } { "spawnflags" "2048" "classname" "item_key1" "origin" "1472 -2240 24" "sounds" "2" } { "angle" "180" "origin" "2488 -1280 24" "classname" "monster_demon1" "targetname" "t262" "spawnflags" "256" } { "angle" "180" "origin" "2296 -1280 24" "classname" "monster_demon1" "targetname" "t270" "spawnflags" "256" } { "spawnflags" "256" "classname" "monster_demon1" "origin" "2392 -1280 24" "angle" "180" "targetname" "t271" } { "spawnflags" "768" "angle" "180" "origin" "2584 -1280 24" "classname" "monster_demon1" "targetname" "t265" } { "angle" "180" "origin" "2680 -1280 24" "classname" "monster_demon1" "targetname" "t272" "spawnflags" "768" } { "classname" "monster_demon1" "origin" "2776 -1280 24" "angle" "180" "targetname" "t267" "spawnflags" "768" } { "light" "100" "origin" "1888 1456 96" "classname" "light" } { "classname" "light" "origin" "1568 1376 96" "light" "100" } { "light" "100" "origin" "1696 1128 160" "classname" "light" } { "classname" "light" "origin" "2080 1128 160" "light" "100" } { "light" "150" "origin" "1696 1704 160" "classname" "light" } { "classname" "light" "origin" "2080 1712 160" "light" "150" } { "spawnflags" "768" "classname" "trigger_once" "target" "t269" "model" "*51" } { "spawnflags" "2064" "angle" "0" "classname" "func_door" "wait" "-1" "sounds" "1" "model" "*52" } { "spawnflags" "2056" "angle" "180" "classname" "func_door" "wait" "-1" "sounds" "3" "model" "*53" } { "spawnflags" "2056" "wait" "-1" "classname" "func_door" "angle" "0" "sounds" "3" "model" "*54" } { "angle" "180" "origin" "984 572 24" "classname" "monster_zombie" } { "angle" "180" "origin" "944 532 24" "classname" "monster_zombie" } { "angle" "45" "origin" "664 264 24" "classname" "monster_zombie" } { "angle" "135" "origin" "848 264 24" "classname" "monster_zombie" } { "target" "t51" "targetname" "t256" "origin" "-376 152 -96" "classname" "path_corner" } { "angle" "45" "origin" "1856 640 184" "classname" "monster_zombie" } { "spawnflags" "768" "angle" "180" "origin" "1416 -400 -232" "classname" "monster_ogre" } { "target" "t197" "health" "1" "wait" "-1" "lip" "4" "angle" "180" "classname" "func_door" "sounds" "1" "model" "*55" } { "classname" "trigger_changelevel" "map" "e4m6" "model" "*56" } { "classname" "info_null" "origin" "876 408 -856" "targetname" "t258" } { "classname" "light" "origin" "1032 304 -552" "light" "150" } { "light" "150" "origin" "1304 304 -552" "classname" "light" } { "classname" "light" "origin" "1304 528 -552" "light" "150" } { "light" "150" "origin" "1032 528 -552" "classname" "light" } { "origin" "1120 -480 -64" "classname" "light" } { "angle" "90" "origin" "1824 -1184 280" "classname" "monster_zombie" } { "spawnflags" "256" "classname" "monster_zombie" "origin" "1952 -1184 280" "angle" "90" } { "angle" "90" "origin" "2080 -1184 280" "classname" "monster_zombie" } { "spawnflags" "256" "angle" "225" "origin" "1312 -912 280" "classname" "monster_zombie" } { "spawnflags" "768" "classname" "monster_zombie" "origin" "1728 -1088 280" "angle" "180" } { "spawnflags" "768" "angle" "180" "origin" "1384 -960 280" "classname" "monster_zombie" } { "origin" "1504 -1088 320" "classname" "light" } { "classname" "light" "origin" "1120 -736 320" } { "classname" "light_torch_small_walltorch" "origin" "738 250 44" } { "classname" "func_plat" "sounds" "2" "height" "432" "model" "*57" } { "classname" "trigger_counter" "targetname" "t261" "count" "3" "target" "t270" "spawnflags" "1" "model" "*58" } { "spawnflags" "1792" "classname" "weapon_rocketlauncher" "origin" "1536 864 128" } { "classname" "item_artifact_super_damage" "origin" "856 464 360" } { "classname" "item_artifact_invulnerability" //Q-Man "origin" "608 352 -360" } { "spawnflags" "1792" "classname" "item_artifact_super_damage" "origin" "1476 808 152" } //{ //"classname" "item_artifact_invulnerability" //"origin" "1928 1184 28" //} { "classname" "monster_hell_knight" "origin" "896 960 -880" "angle" "0" } { "classname" "monster_hell_knight" "origin" "2272 32 24" "angle" "135" "spawnflags" "256" } { "classname" "monster_hell_knight" "origin" "1736 544 184" "angle" "0" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "2872 384 24" "angle" "135" "spawnflags" "768" } { "classname" "monster_hell_knight" "origin" "1312 1352 136" "angle" "270" "spawnflags" "257" } { "speed" "400" "angle" "45" "classname" "trigger_monsterjump" "model" "*59" } { "classname" "trigger_monsterjump" "angle" "135" "speed" "500" "model" "*60" } { "classname" "item_health" "origin" "-464 240 -128" "spawnflags" "2050" } { "classname" "monster_zombie" "origin" "2032 648 184" "angle" "90" } { "classname" "monster_zombie" "origin" "2432 256 24" "angle" "45" "spawnflags" "768" } { "classname" "trigger_secret" "model" "*61" } { "classname" "trigger_secret" "model" "*62" } { "classname" "trigger_secret" "model" "*63" } { "spawnflags" "768" "angle" "45" "origin" "1936 640 184" "classname" "monster_shalrath" } { "angle" "135" "spawnflags" "768" "targetname" "t217" "origin" "2568 1344 24" "classname" "monster_shalrath" } { "spawnflags" "256" "targetname" "t269" "angle" "45" "origin" "2816 928 192" "classname" "monster_shalrath" } { "spawnflags" "257" "angle" "135" "origin" "1856 -992 104" "classname" "monster_shalrath" } { "classname" "light" "origin" "1344 1632 -64" } { "origin" "1376 1376 176" "classname" "light" } { "light" "150" "origin" "1848 1200 96" "classname" "light" } { "targetname" "t197" "target" "t194" "classname" "trigger_once" "model" "*64" } { "classname" "info_intermission" "origin" "2440 1744 128" "mangle" "25 290 0" } { "mangle" "0 60 0" "origin" "1200 -2112 176" "classname" "info_intermission" } { "mangle" "0 200 0" "origin" "1648 1024 176" "classname" "info_intermission" } { "mangle" "0 180 0" "origin" "1488 416 -624" "classname" "info_intermission" } { "classname" "trigger_monsterjump" "angle" "45" "model" "*65" } { "classname" "trigger_once" "spawnflags" "1" "targetname" "t270" "target" "t271" "delay" "4" "model" "*66" } { "spawnflags" "1" "classname" "trigger_once" "targetname" "t271" "target" "t262" "delay" "4" "model" "*67" } { "classname" "trigger_once" "spawnflags" "1" "targetname" "t262" "target" "t265" "delay" "4" "model" "*68" } { "spawnflags" "1" "classname" "trigger_once" "targetname" "t265" "target" "t272" "delay" "4" "model" "*69" } { "classname" "trigger_once" "spawnflags" "1" "target" "t267" "targetname" "t272" "delay" "4" "model" "*70" } { "spawnflags" "769" "classname" "trigger_once" "targetname" "t267" "target" "t268" "delay" "4" "model" "*71" } { "origin" "1328 1584 -128" "classname" "weapon_lightning" } { "spawnflags" "1792" "origin" "2048 -1008 256" "classname" "weapon_lightning" //Q-Man } { "spawnflags" "1792" "origin" "1952 -960 80" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "2192 560 0" //Q-Man "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "classname" "func_wall" "model" "*72" } { "spawnflags" "1792" "origin" "2544 432 0" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "2128 936 0" //Q-Man "classname" "weapon_supernailgun" } { "spawnflags" "1793" "origin" "2064 1168 0" "classname" "item_cells" } { "spawnflags" "1792" "origin" "1696 1192 24" "classname" "item_artifact_invisibility" } { "spawnflags" "1792" "origin" "1888 1792 -128" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "1728 1696 112" "classname" "weapon_nailgun" //Q-Man } { "spawnflags" "1792" "origin" "904 672 0" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "2064 360 128" //Q-Man "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "1328 1232 112" //Q-Man "classname" "weapon_nailgun" } { "classname" "func_door" "angle" "180" "wait" "-1" "sounds" "3" "model" "*73" } { "sounds" "3" "wait" "-1" "angle" "0" "classname" "func_door" "model" "*74" } { "targetname" "t273" "origin" "-444 860 -12" "classname" "info_null" } { "classname" "trigger_teleport" "target" "t273" "model" "*75" } { "classname" "monster_ogre" "origin" "2568 1208 24" "angle" "135" "spawnflags" "1024" } { "classname" "info_null" "origin" "1808 640 40" "targetname" "t274" } { "origin" "2096 688 40" "classname" "info_null" "targetname" "t275" } { "classname" "light" "origin" "1872 640 40" "light" "100" } { "light" "100" "origin" "2032 688 40" "classname" "light" } { "classname" "trigger_multiple" "target" "t276" "wait" "3" "model" "*76" } { "classname" "trap_spikeshooter" "origin" "2096 696 40" "angle" "180" "targetname" "t276" } { "classname" "trap_spikeshooter" "origin" "1808 632 40" "angle" "0" "targetname" "t277" } { "classname" "monster_demon1" "origin" "2464 -16 24" "angle" "180" "spawnflags" "256" } { "classname" "monster_demon1" "origin" "2464 144 24" "spawnflags" "768" "angle" "180" } { "classname" "trigger_secret" "model" "*77" } { "classname" "monster_hell_knight" "origin" "1160 -352 -296" "angle" "0" } { "classname" "item_cells" "origin" "528 336 -384" } { "classname" "item_cells" "origin" "1280 384 0" } { "classname" "item_cells" "origin" "1600 8 -448" } { "classname" "item_cells" "origin" "1392 -312 -256" } { "classname" "item_cells" "origin" "1632 -832 80" "spawnflags" "1" } { "classname" "item_cells" "origin" "2240 -832 80" "spawnflags" "1" } { "classname" "item_cells" "origin" "1808 688 0" } { "classname" "item_cells" "origin" "1792 1216 0" "spawnflags" "1" } { "classname" "item_cells" "origin" "2064 1680 112" } { "classname" "item_cells" "origin" "1664 1680 112" } { "classname" "item_cells" "origin" "2320 656 96" } { "classname" "item_cells" "origin" "256 1120 0" "spawnflags" "1" } { "classname" "item_cells" "origin" "-464 176 -128" "spawnflags" "768" } { "classname" "item_cells" "origin" "1776 -2128 0" "spawnflags" "1" } { "classname" "item_rockets" "origin" "1952 1120 0" "spawnflags" "256" } { "classname" "weapon_rocketlauncher" "origin" "1056 -1440 0" //Q-Man "spawnflags" "1792" } { "classname" "monster_hell_knight" "origin" "1104 -784 -168" "angle" "90" } { "classname" "monster_hell_knight" "origin" "1472 1136 136" "angle" "270" "targetname" "t189" } { "classname" "item_rockets" "origin" "1456 1248 112" "spawnflags" "769" } { "classname" "item_cells" "origin" "2184 864 0" "spawnflags" "769" } { "classname" "light" "origin" "2480 64 40" "light" "200" } { "classname" "item_cells" "origin" "1456 -1824 0" "spawnflags" "1" } { "delay" "4" "classname" "trigger_once" "spawnflags" "1281" "targetname" "t262" "target" "t268" "model" "*78" } { "spawnflags" "1537" "classname" "trigger_once" "delay" "4" "targetname" "t270" "target" "t268" "model" "*79" } { "spawnflags" "1792" "classname" "func_wall" "model" "*80" } { "spawnflags" "1" "origin" "1680 -1512 0" "classname" "item_cells" } { "origin" "2272 -224 104" "classname" "item_artifact_super_damage" } { "origin" "2520 64 24" "classname" "item_artifact_invisibility" "spawnflags" "1792" } { "angle" "180" "spawnflags" "768" "origin" "552 416 -360" "classname" "monster_ogre" } { "classname" "item_health" "origin" "2032 816 0" } { "origin" "1840 496 0" "classname" "item_health" } { "classname" "trigger_relay" "origin" "1848 392 168" "targetname" "t276" "delay" "1.5" "target" "t277" } { "spawnflags" "2048" "classname" "func_wall" "model" "*81" } { "spawnflags" "2048" "classname" "func_wall" "model" "*82" } { "angle" "270" "origin" "-368 624 -104" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-592 752 -104" "angle" "270" } { "angle" "270" "origin" "-544 656 -104" "classname" "info_player_coop" } //Q-Man { "classname" "item_flag_team1" "origin" "-526 575 -104" } { "classname" "info_player_team1" "origin" "-526 700 220" } { "classname" "info_player_team1" "origin" "-526 400 220" } { "classname" "info_player_team1" "origin" "-526 150 220" } { "classname" "info_player_team1" "origin" "-250 150 220" } { "classname" "info_player_team1" "origin" "-250 400 220" } { "classname" "info_player_team1" "origin" "-250 700 220" } { "classname" "item_flag_team2" "origin" "1473 -1727 64" } { "classname" "info_player_team2" "origin" "1384 -1727 276" } { "classname" "info_player_team2" "origin" "1548 -1727 276" "angle" "180" } { "classname" "info_player_team2" "origin" "1476 -1650 200" "angle" "270" } { "classname" "info_player_team2" "origin" "1476 -1800 200" "angle" "90" } { "classname" "info_player_team2" "origin" "1759 -1376 40" "angle" "225" } { "classname" "info_player_team2" "origin" "1056 -1440 24" "angle" "315" } { "origin" "1952 -576 152" "classname" "item_armor2" } { "origin" "2961 945 192" "classname" "item_armor2" } { "classname" "item_health" "origin" "1666 -1900 24" } { "origin" "0 146 -104" "classname" "item_armor2" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/ctf/fcast.ent000066400000000000000000000346541475442401000255400ustar00rootroot00000000000000{ "classname" "worldspawn" "sounds" "1" "light" "50" "message" "Fast Castles v1.0\nby Night Hunter\nhttp://clan.sd.ru" "wad" "d:\games\quake\worldcraft\wads\ogro2.wad;d:\games\quake\worldcraft\wads\q3test.wad;d:\games\quake\worldcraft\wads\apocr" } { "classname" "light" "style" "0" "light" "1000" "origin" "-576 0 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-576 -512 896" } { "classname" "light" "style" "0" "light" "500" "origin" "-1104 -512 896" } { "classname" "light" "style" "0" "light" "500" "origin" "-1104 480 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-192 -512 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-192 0 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-192 480 896" } { "classname" "light" "style" "0" "light" "400" "origin" "-1552 656 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1552 912 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-2064 -848 488" } { "classname" "light" "style" "0" "light" "400" "origin" "-2288 784 824" } { "classname" "light" "style" "0" "light" "400" "origin" "-1936 784 824" } { "classname" "light" "style" "0" "light" "400" "origin" "-2288 -848 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-816 -944 218" } { "classname" "light" "style" "0" "light" "400" "origin" "-2224 496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1808 496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1392 496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1392 -816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1808 -816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-2224 -816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-2416 -528 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-2416 -144 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-2416 240 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-1200 656 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-1200 -912 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-2416 496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1936 496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1168 496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1168 48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-2416 48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1936 48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1936 -304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1936 -592 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 -304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1392 -304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 -688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 -1008 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1168 -1008 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1168 -688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1392 -688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1392 48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-2416 -304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-2352 -304 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-2352 48 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-1936 432 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 432 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-1168 -688 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-1392 -688 488" } { "classname" "light" "style" "0" "light" "300" "origin" "-2416 -592 136" } { "classname" "light" "style" "0" "light" "300" "origin" "-1680 -592 136" } { "classname" "light" "style" "0" "light" "400" "origin" "-1680 -304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1392 -304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1936 -304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1680 48 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1936 48 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1680 -592 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1936 -592 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1168 -304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "-1168 48 696" } { "classname" "light" "style" "0" "light" "500" "origin" "-1808 -128 696" } { "classname" "light" "style" "0" "light" "500" "origin" "-1168 -128 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-1200 912 696" } { "classname" "light" "style" "0" "light" "1000" "origin" "-576 960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-576 -960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-192 960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "-192 -960 896" } { "classname" "light" "style" "0" "light" "100" "origin" "-576 480 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "576 0 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "576 512 896" } { "classname" "light" "style" "0" "light" "500" "origin" "1104 512 896" } { "classname" "light" "style" "0" "light" "500" "origin" "1104 -480 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "192 512 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "192 0 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "192 -480 896" } { "classname" "light" "style" "0" "light" "400" "origin" "1552 -656 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1552 -912 696" } { "classname" "light" "style" "0" "light" "400" "origin" "2064 848 488" } { "classname" "light" "style" "0" "light" "400" "origin" "2288 -784 824" } { "classname" "light" "style" "0" "light" "400" "origin" "1936 -784 824" } { "classname" "light" "style" "0" "light" "400" "origin" "2288 848 488" } { "classname" "light" "style" "0" "light" "300" "origin" "816 944 218" } { "classname" "light" "style" "0" "light" "400" "origin" "2224 -496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1808 -496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1392 -496 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1392 816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1808 816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "2224 816 696" } { "classname" "light" "style" "0" "light" "400" "origin" "2416 528 696" } { "classname" "light" "style" "0" "light" "400" "origin" "2416 144 696" } { "classname" "light" "style" "0" "light" "400" "origin" "2416 -240 696" } { "classname" "light" "style" "0" "light" "300" "origin" "1200 -656 696" } { "classname" "light" "style" "0" "light" "300" "origin" "1200 912 696" } { "classname" "light" "style" "0" "light" "300" "origin" "2416 -496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1936 -496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 -496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1168 -496 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 -48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1168 -48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "2416 -48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1936 -48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1936 304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1936 592 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1392 304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 1008 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1168 1008 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1168 688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1392 688 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1392 -48 136" } { "classname" "light" "style" "0" "light" "300" "origin" "2416 304 136" } { "classname" "light" "style" "0" "light" "300" "origin" "2352 304 488" } { "classname" "light" "style" "0" "light" "300" "origin" "2352 -48 488" } { "classname" "light" "style" "0" "light" "300" "origin" "1936 -432 488" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 -432 488" } { "classname" "light" "style" "0" "light" "300" "origin" "1168 688 488" } { "classname" "light" "style" "0" "light" "300" "origin" "1392 688 488" } { "classname" "light" "style" "0" "light" "300" "origin" "2416 592 136" } { "classname" "light" "style" "0" "light" "300" "origin" "1680 592 136" } { "classname" "light" "style" "0" "light" "400" "origin" "1680 304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1392 304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1936 304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1680 -48 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1936 -48 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1680 592 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1936 592 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1168 304 696" } { "classname" "light" "style" "0" "light" "400" "origin" "1168 -48 696" } { "classname" "light" "style" "0" "light" "500" "origin" "1808 128 696" } { "classname" "light" "style" "0" "light" "500" "origin" "1168 128 696" } { "classname" "light" "style" "0" "light" "300" "origin" "1200 -912 696" } { "classname" "light" "style" "0" "light" "1000" "origin" "576 -960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "576 960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "192 -960 896" } { "classname" "light" "style" "0" "light" "1000" "origin" "192 960 896" } { "classname" "light" "style" "0" "light" "100" "origin" "576 -480 896" } { "classname" "light" "style" "0" "light" "300" "origin" "2256 976 696" } { "classname" "light" "style" "0" "light" "300" "origin" "1968 976 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-2256 -976 696" } { "classname" "light" "style" "0" "light" "300" "origin" "-1968 -976 696" } { "classname" "func_door" "angle" "180" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "1" "dmg" "0" "health" "0" "model" "*1" } { "classname" "func_door" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "1" "dmg" "0" "health" "0" "model" "*2" } { "classname" "func_door" "angle" "90" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "1" "dmg" "0" "health" "0" "model" "*3" } { "classname" "func_door" "angle" "270" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "1" "dmg" "0" "health" "0" "model" "*4" } { "classname" "func_door" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "2" "dmg" "0" "health" "0" "model" "*7" } { "classname" "func_door" "angle" "180" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "2" "dmg" "0" "health" "0" "model" "*8" } { "classname" "func_door" "angle" "270" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "2" "dmg" "0" "health" "0" "model" "*9" } { "classname" "func_door" "angle" "90" "speed" "500" "wait" "1" "lip" "0" "sounds" "2" "team_no" "2" "dmg" "0" "health" "0" "model" "*10" } { "classname" "info_player_start" "origin" "0 0 512" } // CTF adoption. { "classname" "item_flag_team1" "origin" "1800 730 528" "angle" "220" } { "classname" "item_flag_team2" "origin" "-1800 -730 528" "angle" "40" } { "classname" "info_player_team1" "origin" "417 951 732" "angle" "-90" } { "classname" "info_player_team2" "origin" "-417 -951 732" "angle" "90" } { "classname" "info_player_team1" "origin" "668 -1007 552" "angle" "-270" } { "classname" "info_player_team2" "origin" "-668 1007 552" "angle" "-90" } { "classname" "info_player_team1" "origin" "1775 -1007 552" "angle" "150" } { "classname" "info_player_team2" "origin" "-1775 1007 552" "angle" "-30" } { "classname" "info_player_team1" "origin" "1840 -1007 712" "angle" "40" } { "classname" "info_player_team2" "origin" "-1840 1007 712" "angle" "-140" } { "classname" "info_player_team1" "origin" "1936 1007 344" "angle" "-37" } { "classname" "info_player_team2" "origin" "-1936 -1007 344" "angle" "-217" } { "classname" "info_player_team1" "origin" "1103 815 552" "angle" "-140" } { "classname" "info_player_team2" "origin" "-1103 -815 552" "angle" "-320" } { "classname" "info_player_team1" "origin" "2415 1007 552" "angle" "-134" } { "classname" "info_player_team2" "origin" "-2415 -1007 552" "angle" "-314" } { "classname" "weapon_rocketlauncher" "origin" "1808 134 320" } { "classname" "weapon_rocketlauncher" "origin" "-1808 -134 320" } { "classname" "weapon_rocketlauncher" "origin" "971 66 528" } { "classname" "weapon_rocketlauncher" "origin" "-971 -66 528" } { "classname" "item_rockets" "origin" "971 129 320" } { "classname" "item_rockets" "origin" "-971 -129 320" } { "classname" "weapon_grenadelauncher" "origin" "323 986 528" } { "classname" "weapon_grenadelauncher" "origin" "-323 -986 528" } { "classname" "weapon_grenadelauncher" "origin" "1520 -622 528" } { "classname" "weapon_grenadelauncher" "origin" "-1520 622 528" } { "classname" "item_armor2" "origin" "410 846 128" } { "classname" "item_armor2" "origin" "-410 -846 128" } { "classname" "item_armorInv" "origin" "0 0 320" } { "classname" "item_health" "origin" "2360 -952 528" } { "classname" "item_health" "origin" "2354 953 320" } { "classname" "item_health" "origin" "1992 748 320" } { "classname" "item_health" "origin" "1702 -624 528" } { "classname" "item_health" "origin" "-2360 952 528" } { "classname" "item_health" "origin" "-2354 -953 320" } { "classname" "item_health" "origin" "-1992 -748 320" } { "classname" "item_health" "origin" "-1702 624 528" } { "classname" "weapon_supershotgun" "origin" "2112 914 528" } { "classname" "weapon_supershotgun" "origin" "-2112 -914 528" } { "classname" "weapon_lightning" "origin" "0 0 10" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/death6.ent000066400000000000000000000573361475442401000250410ustar00rootroot00000000000000{ "wad" "q.wad" "classname" "worldspawn" "message" "Chthons gone." } { "angle" "180" //"spawnflags" "2048" "origin" "60 128 408" "classname" "info_player_start" } { "classname" "func_plat" //"spawnflags" "1792" "sounds" "2" "height" "142" "speed" "100" "model" "*1" } { "classname" "item_artifact_super_damage" "origin" "0 -416 56" //"spawnflags" "1792" } { "classname" "info_player_deathmatch" "origin" "168 128 408" //"spawnflags" "1792" "angle" "270" } { "classname" "item_health" "origin" "-16 896 64" //"spawnflags" "1794" } { "classname" "item_artifact_invulnerability" "origin" "0 128 408" //"spawnflags" "1792" } { "classname" "func_illusionary" //"spawnflags" "1792" "model" "*2" } { "classname" "func_plat" //"spawnflags" "1792" "speed" "100" "sounds" "2" "height" "174" "model" "*3" } { //"spawnflags" "1792" "classname" "trigger_teleport" "target" "tele1" "model" "*4" } { //"spawnflags" "1792" "classname" "trigger_teleport" "target" "tele2" "model" "*5" } { //"spawnflags" "1792" "classname" "trigger_teleport" "target" "tele3" "model" "*6" } { //"spawnflags" "1792" "classname" "trigger_teleport" "target" "tele4" "model" "*7" } { //"spawnflags" "1792" "origin" "4 60 0" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "-36 60 0" //"spawnflags" "1792" } { //"spawnflags" "1792" "origin" "0 160 0" "classname" "weapon_supernailgun" } { //"spawnflags" "1792" "origin" "152 112 0" "classname" "item_health" } { "classname" "item_health" "origin" "-184 112 0" //"spawnflags" "1792" } { //"spawnflags" "1793" "origin" "-432 912 64" "classname" "item_health" } { "angle" "45" //"spawnflags" "1792" "origin" "-488 -744 536" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "origin" "488 -744 536" //"spawnflags" "1792" "angle" "135" } { "angle" "225" //"spawnflags" "1792" "origin" "488 1000 536" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "origin" "-488 1000 536" //"spawnflags" "1792" "angle" "315" } { //"spawnflags" "1792" "origin" "420 932 512" "classname" "weapon_supershotgun" } { //"spawnflags" "1792" "origin" "-420 932 512" "classname" "weapon_rocketlauncher" } { //"spawnflags" "1792" "origin" "-420 -676 512" "classname" "weapon_nailgun" } { //"spawnflags" "1792" "origin" "420 -676 512" "classname" "weapon_grenadelauncher" } { "angle" "90" //"spawnflags" "1792" "origin" "-168 128 408" "classname" "info_player_deathmatch" } { //"spawnflags" "1792" "origin" "0 968 384" "classname" "item_armor2" } { //"spawnflags" "1792" "origin" "432 944 384" "classname" "item_health" } { "classname" "item_health" "origin" "-464 944 384" //"spawnflags" "1792" } { //"spawnflags" "1792" "origin" "-464 -720 384" "classname" "item_health" } { "classname" "item_health" "origin" "432 -720 384" //"spawnflags" "1792" } { //"spawnflags" "1792" "angle" "270" "origin" "0 -312 408" "classname" "info_player_deathmatch" } { //"spawnflags" "1792" "origin" "0 -416 384" "classname" "item_armor1" } { "angle" "90" //"spawnflags" "1792" "origin" "0 568 408" "classname" "info_player_deathmatch" } { //"spawnflags" "1792" "origin" "-16 656 384" "classname" "item_rockets" } { "angle" "180" //"spawnflags" "1792" "origin" "468 128 232" "classname" "info_player_deathmatch" } { "angle" "360" //"spawnflags" "1792" "origin" "-468 128 232" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "origin" "280 -728 232" //"spawnflags" "1792" "angle" "180" } { "angle" "360" //"spawnflags" "1792" "origin" "-280 -728 232" "classname" "info_player_deathmatch" } { "classname" "item_spikes" "origin" "-496 80 384" //"spawnflags" "1792" } { "classname" "info_teleport_destination" "origin" "376 64 464" //"spawnflags" "1792" "angle" "270" "targetname" "tele2" } { "classname" "info_teleport_destination" "origin" "-80 -720 536" //"spawnflags" "1792" "targetname" "tele3" } { "classname" "item_armorInv" "origin" "64 -720 528" //"spawnflags" "1792" } { "classname" "item_rockets" "origin" "432 -480 64" //"spawnflags" "1792" } { "classname" "item_health" "origin" "432 -272 64" //"spawnflags" "1792" } { //"spawnflags" "1792" "origin" "-464 -272 64" "classname" "item_health" } { "classname" "item_spikes" "origin" "-464 -480 64" //"spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "-448 624 64" //"spawnflags" "1792" } { "classname" "weapon_supershotgun" "origin" "448 624 64" //"spawnflags" "1792" } { "classname" "item_health" "origin" "400 912 64" //"spawnflags" "1793" } { "classname" "item_shells" "origin" "-48 240 64" //"spawnflags" "1792" } { "classname" "item_spikes" "origin" "16 240 64" //"spawnflags" "1792" } { "classname" "weapon_lightning" "origin" "0 128 208" //"spawnflags" "1792" } { "classname" "item_cells" "origin" "432 -384 208" //"spawnflags" "1793" } { //"spawnflags" "1793" "origin" "-464 -384 208" "classname" "item_cells" } { "classname" "item_shells" "origin" "-232 888 208" //"spawnflags" "1792" } { "classname" "item_spikes" "origin" "200 888 208" //"spawnflags" "1792" } { "classname" "item_health" "origin" "200 952 208" //"spawnflags" "1792" } { "classname" "item_rockets" "origin" "-232 952 208" //"spawnflags" "1792" } { "classname" "info_teleport_destination" "origin" "-448 608 216" //"spawnflags" "1792" "angle" "90" "targetname" "tele1" } { "targetname" "tele4" "angle" "90" //"spawnflags" "1792" "origin" "-160 464 136" "classname" "info_teleport_destination" } { "classname" "item_health" "origin" "464 144 384" //"spawnflags" "1793" } { "classname" "item_spikes" "origin" "464 80 384" //"spawnflags" "1792" } { //"spawnflags" "1793" "origin" "-496 144 384" "classname" "item_health" } { "classname" "info_player_deathmatch" "origin" "-280 -968 88" //"spawnflags" "1792" "angle" "90" } { "angle" "90" //"spawnflags" "1792" "origin" "280 -968 88" "classname" "info_player_deathmatch" } { "classname" "func_door" "spawnflags" "1792" "angle" "-2" "speed" "190" "wait" "2" "sounds" "3" "lip" "2" "targetname" "door1" "model" "*8" } { "targetname" "door2" "lip" "2" "sounds" "3" "wait" "2" "speed" "190" "angle" "-2" "spawnflags" "1792" "classname" "func_door" "model" "*9" } { "classname" "trigger_multiple" //"spawnflags" "1792" "target" "door1" "model" "*10" } { "target" "door2" //"spawnflags" "1792" "classname" "trigger_multiple" "model" "*11" } { "classname" "func_illusionary" //"spawnflags" "1792" "model" "*12" } { //"spawnflags" "1792" "classname" "func_illusionary" "model" "*13" } { "style" "1" "light" "190" "origin" "0 -720 584" "classname" "light" } { //"spawnflags" "1792" "origin" "-152 -984 64" "classname" "weapon_supernailgun" } { //"spawnflags" "1792" "origin" "0 680 64" "classname" "weapon_rocketlauncher" } { "classname" "weapon_lightning" "origin" "152 -984 64" //"spawnflags" "1792" } { "classname" "item_cells" "origin" "96 -1000 64" //"spawnflags" "1793" } { //"spawnflags" "1793" "origin" "176 -1000 64" "classname" "item_cells" } { "classname" "trigger_multiple" //"spawnflags" "1792" "message" "(c) ben watson 1998." "sounds" "1" "health" "1" "model" "*14" } { "classname" "weapon_supershotgun" "origin" "392 128 384" //"spawnflags" "1792" } { "classname" "weapon_nailgun" "origin" "-392 128 384" //"spawnflags" "1792" } { "origin" "0 264 552" "classname" "light" } { "classname" "light" "origin" "0 -8 552" } { "origin" "136 128 552" "classname" "light" } { "classname" "light" "origin" "-136 128 552" } { "classname" "light" "origin" "0 576 544" } { "origin" "0 -352 544" "classname" "light" } { "origin" "502 128 460" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-502 128 460" } { "origin" "172 -758 468" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-172 -758 468" } { "origin" "238 1014 484" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-238 1014 484" } { "classname" "light_torch_small_walltorch" "origin" "502 586 460" } { "origin" "-502 586 460" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "0 -942 428" } { "classname" "light_torch_small_walltorch" "origin" "502 -342 460" } { "origin" "-502 -342 460" "classname" "light_torch_small_walltorch" } { "light" "190" "origin" "-384 -640 576" "classname" "light" } { "classname" "light" "origin" "384 -640 576" "light" "190" } { "classname" "light" "origin" "-384 896 576" "light" "190" } { "light" "190" "origin" "384 896 576" "classname" "light" } { "origin" "104 688 536" "classname" "light" } { "classname" "light" "origin" "-112 688 536" } { "classname" "light" "origin" "-152 -328 544" } { "origin" "152 -328 544" "classname" "light" } { "origin" "0 1198 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "0 1198 244" } { "origin" "256 1014 252" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-256 1014 252" } { "origin" "0 -942 260" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-224 -758 260" } { "origin" "224 -758 260" "classname" "light_torch_small_walltorch" } { "origin" "-503 -341 260" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "501 -341 260" } { "origin" "-502 128 252" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "502 128 252" } { "origin" "502 588 252" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-502 588 252" } { "origin" "0 296 280" "classname" "light" } { "classname" "light" "origin" "0 -40 280" } { "origin" "2 226 108" "classname" "light_torch_small_walltorch" } { "origin" "306 1014 108" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-278 1014 108" } { "origin" "-502 128 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "502 128 116" } { "origin" "0 -352 160" "classname" "light" } { "classname" "light" "origin" "176 -184 160" } { "origin" "-176 -184 160" "classname" "light" } { "origin" "144 592 200" "classname" "light" } { "classname" "light" "origin" "-144 592 200" } { "classname" "light" "origin" "0 736 208" } { "classname" "light" "origin" "144 440 200" } { "origin" "-144 440 200" "classname" "light" } { "origin" "-172 -758 108" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "172 -758 108" } { "origin" "280 -1006 100" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-280 -1006 100" } { "origin" "-502 -494 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "498 -494 116" } { "origin" "502 -182 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-502 -182 116" } { "origin" "500 588 116" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "-504 590 116" } { "origin" "216 128 72" "classname" "light" } { "classname" "light" "origin" "-216 128 72" } { "light" "190" "origin" "0 128 72" "classname" "light" } { //"spawnflags" "1792" "origin" "-128 -1000 64" "classname" "item_spikes" } { "classname" "item_spikes" "origin" "-208 -1000 64" //"spawnflags" "1792" } { //"spawnflags" "1793" "origin" "432 576 208" "classname" "item_rockets" } { //"spawnflags" "1793" "origin" "-464 576 208" "classname" "item_spikes" } { "classname" "info_monster_start" "origin" "185.125 124.375 24" } { "classname" "info_monster_start" "origin" "165.625 1 88" } { "classname" "info_monster_start" "origin" "209.125 250.375 88" } { "classname" "info_monster_start" "origin" "247.25 3.875 88" } { "classname" "info_monster_start" "origin" "310 251.125 88" } { "classname" "info_monster_start" "origin" "451.5 158.625 88" } { "classname" "info_monster_start" "origin" "452.5 54.625 88" } { "classname" "info_monster_start" "origin" "453.5 -32.875 88" } { "classname" "info_monster_start" "origin" "454.5 -135 88" } { "classname" "info_monster_start" "origin" "163.875 134 408" } { "classname" "info_monster_start" "origin" "51.875 133.25 408" } { "classname" "info_monster_start" "origin" "-119.375 -9 88" } { "classname" "info_monster_start" "origin" "-176.5 247.625 88" } { "classname" "info_monster_start" "origin" "-187.75 136.25 24" } { "classname" "info_monster_start" "origin" "-210.125 -12.25 88" } { "classname" "info_monster_start" "origin" "-167.5 132.5 232" } { "classname" "info_monster_start" "origin" "-155.25 132 408" } { "classname" "info_monster_start" "origin" "-53.625 132.625 408" } { "classname" "info_monster_start" "origin" "-58.125 131.625 232" } { "classname" "info_monster_start" "origin" "-374.875 178 408" } { "classname" "info_monster_start" "origin" "-374.5 73.5 408" } { "classname" "info_monster_start" "origin" "-375.125 276.875 408" } { "classname" "info_monster_start" "origin" "-456.5 263.875 232" } { "classname" "info_monster_start" "origin" "-455 366.875 232" } { "classname" "info_monster_start" "origin" "-456.75 123 88" } { "classname" "info_monster_start" "origin" "-460.75 202.125 88" } { "classname" "info_monster_start" "origin" "-459.125 282.375 88" } { "classname" "info_monster_start" "origin" "-457 377.875 88" } { "classname" "info_monster_start" "origin" "-454.75 475.5 88" } { "classname" "info_monster_start" "origin" "-452.875 562.125 88" } { "classname" "info_monster_start" "origin" "-451 645.375 88" } { "classname" "info_monster_start" "origin" "-448.75 745 88" } { "classname" "info_monster_start" "origin" "-447 824.125 88" } { "classname" "info_monster_start" "origin" "-170.75 941.25 88" } { "classname" "info_monster_start" "origin" "-75.875 939.125 88" } { "classname" "info_monster_start" "origin" "24 936.75 88" } { "classname" "info_monster_start" "origin" "115 934.625 88" } { "classname" "info_monster_start" "origin" "236.875 931.875 88" } { "classname" "info_monster_start" "origin" "332.75 929.625 88" } { "classname" "info_monster_start" "origin" "-444.625 927.25 88" } { "classname" "info_monster_start" "origin" "-444.5 21.75 88" } { "classname" "info_monster_start" "origin" "-446.75 -78.5 88" } { "classname" "info_monster_start" "origin" "-449.125 -181.375 88" } { "classname" "info_monster_start" "origin" "-451.125 -273 88" } { "classname" "info_monster_start" "origin" "-453.25 -365.25 88" } { "classname" "info_monster_start" "origin" "-455.75 -474.375 88" } { "classname" "info_monster_start" "origin" "-458 -580 88" } { "classname" "info_monster_start" "origin" "-446.25 -651.125 88" } { "classname" "info_monster_start" "origin" "-401.375 -653.75 88" } { "classname" "info_monster_start" "origin" "-314.25 -659.125 88" } { "classname" "info_monster_start" "origin" "-217.875 -665 88" } { "classname" "info_monster_start" "origin" "-113.125 -671.375 88" } { "classname" "info_monster_start" "origin" "193.875 -690.125 88" } { "classname" "info_monster_start" "origin" "298.25 -696.5 88" } { "classname" "info_monster_start" "origin" "369.5 -700.875 88" } { "classname" "info_monster_start" "origin" "447.5 -692.75 88" } { "classname" "info_monster_start" "origin" "447.625 -615.625 88" } { "classname" "info_monster_start" "origin" "458.25 -496.375 88" } { "classname" "info_monster_start" "origin" "457.5 -417.5 88" } { "classname" "info_monster_start" "origin" "456.5 -325.75 88" } { "classname" "info_monster_start" "origin" "455.5 -231.625 88" } { "classname" "info_monster_start" "origin" "450.375 254.875 88" } { "classname" "info_monster_start" "origin" "449.375 359.875 88" } { "classname" "info_monster_start" "origin" "448.375 450.875 88" } { "classname" "info_monster_start" "origin" "447.375 547.5 88" } { "classname" "info_monster_start" "origin" "446.375 648 88" } { "classname" "info_monster_start" "origin" "445.25 752.625 88" } { "classname" "info_monster_start" "origin" "444.125 855.875 88" } { "classname" "info_monster_start" "origin" "443.25 939.625 88" } { "classname" "info_monster_start" "origin" "461.875 933.5 232" } { "classname" "info_monster_start" "origin" "460 847.375 232" } { "classname" "info_monster_start" "origin" "349 920.25 232" } { "classname" "info_monster_start" "origin" "266.875 923.125 232" } { "classname" "info_monster_start" "origin" "185.875 925.875 232" } { "classname" "info_monster_start" "origin" "83.125 929.5 232" } { "classname" "info_monster_start" "origin" "-21.5 933.125 232" } { "classname" "info_monster_start" "origin" "-131 936.875 232" } { "classname" "info_monster_start" "origin" "-446.5 943 232" } { "classname" "info_monster_start" "origin" "-453.25 481.375 232" } { "classname" "info_monster_start" "origin" "-460.875 -40.25 232" } { "classname" "info_monster_start" "origin" "-462.375 -137.25 232" } { "classname" "info_monster_start" "origin" "-463.875 -239.875 232" } { "classname" "info_monster_start" "origin" "-465.625 -358.25 232" } { "classname" "info_monster_start" "origin" "-467.125 -464.25 232" } { "classname" "info_monster_start" "origin" "-468.5 -553.625 232" } { "classname" "info_monster_start" "origin" "-474.25 -660.875 232" } { "classname" "info_monster_start" "origin" "-365.25 -664.125 232" } { "classname" "info_monster_start" "origin" "-258.25 -667.25 232" } { "classname" "info_monster_start" "origin" "-153.5 -670.25 232" } { "classname" "info_monster_start" "origin" "168.75 -679.625 232" } { "classname" "info_monster_start" "origin" "281.125 -682.875 232" } { "classname" "info_monster_start" "origin" "387.875 -686 232" } { "classname" "info_monster_start" "origin" "454.875 -673.625 232" } { "classname" "info_monster_start" "origin" "457.875 -528.625 232" } { "classname" "info_monster_start" "origin" "459.75 -442.5 232" } { "classname" "info_monster_start" "origin" "461.75 -349.625 232" } { "classname" "info_monster_start" "origin" "463.75 -255.125 232" } { "classname" "info_monster_start" "origin" "466 -147.875 232" } { "classname" "info_monster_start" "origin" "468.125 -49.25 232" } { "classname" "info_monster_start" "origin" "470 51.625 232" } { "classname" "info_monster_start" "origin" "466.125 140.875 232" } { "classname" "info_monster_start" "origin" "447.25 243.625 232" } { "classname" "info_monster_start" "origin" "449.25 338.375 232" } { "classname" "info_monster_start" "origin" "451.375 437.125 232" } { "classname" "info_monster_start" "origin" "453.375 534 232" } { "classname" "info_monster_start" "origin" "455.5 632.25 232" } { "classname" "info_monster_start" "origin" "457.75 737.125 232" } { "classname" "info_monster_start" "origin" "352.125 922.5 408" } { "classname" "info_monster_start" "origin" "368.75 827.5 408" } { "classname" "info_monster_start" "origin" "368.125 727.875 408" } { "classname" "info_monster_start" "origin" "367.375 614.875 408" } { "classname" "info_monster_start" "origin" "366.75 507.375 408" } { "classname" "info_monster_start" "origin" "7 653.125 408" } { "classname" "info_monster_start" "origin" "0.375 537.375 408" } { "classname" "info_monster_start" "origin" "366.125 404.75 408" } { "classname" "info_monster_start" "origin" "365.5 302.25 408" } { "classname" "info_monster_start" "origin" "364.875 194.25 408" } { "classname" "info_monster_start" "origin" "364.25 79.75 408" } { "classname" "info_monster_start" "origin" "363.5 -32.125 408" } { "classname" "info_monster_start" "origin" "362.875 -147.125 408" } { "classname" "info_monster_start" "origin" "7.25 -275.875 408" } { "classname" "info_monster_start" "origin" "-156.375 -668.625 408" } { "classname" "info_monster_start" "origin" "361.625 -347.25 408" } { "classname" "info_monster_start" "origin" "360.75 -500.625 408" } { "classname" "info_monster_start" "origin" "362.25 -245.75 408" } { "classname" "info_monster_start" "origin" "238.625 921.25 408" } { "classname" "info_monster_start" "origin" "145 920.25 408" } { "classname" "info_monster_start" "origin" "41.375 919.125 408" } { "classname" "info_monster_start" "origin" "-66 918 408" } { "classname" "info_monster_start" "origin" "-377.125 914.625 408" } { "classname" "info_monster_start" "origin" "-372.625 -561.625 408" } { "classname" "info_monster_start" "origin" "-356.625 -662.25 408" } { "classname" "info_monster_start" "origin" "-260.25 -665.25 408" } { "classname" "info_monster_start" "origin" "375.625 -685.5 408" } { "classname" "info_monster_start" "origin" "269 -682.125 408" } { "classname" "info_monster_start" "origin" "173.125 -679.125 408" } { "classname" "info_monster_start" "origin" "66.25 -675.625 408" } { "classname" "info_monster_start" "origin" "-44.875 -672.125 408" } { "classname" "info_monster_start" "origin" "55.25 -676.375 232" } { "classname" "info_monster_start" "origin" "-43.375 -673.5 232" } { "classname" "info_monster_start" "origin" "88.125 -683.75 88" } { "classname" "info_monster_start" "origin" "-10.25 -677.625 88" } { "classname" "info_monster_start" "origin" "-0.125 -516.75 56" } { "classname" "info_monster_start" "origin" "2.875 -415.375 56" } { "classname" "info_monster_start" "origin" "4.25 -385.375 408" } { "classname" "info_monster_start" "origin" "-372.875 -450 408" } { "classname" "info_monster_start" "origin" "-373.25 -345.125 408" } { "classname" "info_monster_start" "origin" "-373.625 -237.625 408" } { "classname" "info_monster_start" "origin" "-373.875 -125.25 408" } { "classname" "info_monster_start" "origin" "-374.25 -28.375 408" } { "classname" "info_monster_start" "origin" "-459.5 60.625 232" } { "classname" "info_monster_start" "origin" "-457.875 164.75 232" } { "classname" "info_monster_start" "origin" "-351.25 134 232" } { "classname" "info_monster_start" "origin" "333.875 128.5 232" } { "classname" "info_monster_start" "origin" "40.875 130.875 232" } { "classname" "info_monster_start" "origin" "-268.125 133.375 232" } { "classname" "info_monster_start" "origin" "226.25 129.375 232" } { "classname" "info_monster_start" "origin" "71.125 -2.25 88" } { "classname" "info_monster_start" "origin" "-26.125 -5.75 88" } { "classname" "info_monster_start" "origin" "-306.625 -15.75 88" } { "classname" "info_monster_start" "origin" "129.75 130.125 232" } { "classname" "info_monster_start" "origin" "-83.375 248.25 88" } { "classname" "info_monster_start" "origin" "-253.375 247 88" } { "classname" "info_monster_start" "origin" "-375.5 378.125 408" } { "classname" "info_monster_start" "origin" "-375.75 484.5 408" } { "classname" "info_monster_start" "origin" "-376.125 585 408" } { "classname" "info_monster_start" "origin" "-376.375 673.375 408" } { "classname" "info_monster_start" "origin" "-376.625 772.875 408" } { "classname" "info_monster_start" "origin" "-289.25 915.625 408" } { "classname" "info_monster_start" "origin" "-178.125 916.75 408" } { "classname" "info_monster_start" "origin" "-451.75 583.625 232" } { "classname" "info_monster_start" "origin" "-450.375 679 232" } { "classname" "info_monster_start" "origin" "-448.875 780 232" } { "classname" "info_monster_start" "origin" "-353.75 944.625 232" } { "classname" "info_monster_start" "origin" "-254.625 941.25 232" } { "classname" "info_monster_start" "origin" "-356.375 945.625 88" } { "classname" "info_monster_start" "origin" "-275.5 943.75 88" } { "classname" "info_monster_start" "origin" "-232.125 794.875 88" } { "classname" "info_monster_start" "origin" "-208.375 731.625 88" } { "classname" "info_monster_start" "origin" "-171.625 633.625 88" } { "classname" "info_monster_start" "origin" "-141.375 552.75 88" } { "classname" "info_monster_start" "origin" "-107.125 461.25 88" } { "classname" "info_monster_start" "origin" "-69.5 360.5 88" } { "classname" "info_monster_start" "origin" "19.375 249 88" } { "classname" "info_monster_start" "origin" "116.25 249.75 88" } { "classname" "info_monster_start" "origin" "79 373.125 88" } { "classname" "info_monster_start" "origin" "107.625 447.25 88" } { "classname" "info_monster_start" "origin" "144.125 541.375 88" } { "classname" "info_monster_start" "origin" "245.5 803.125 88" } { "classname" "info_monster_start" "origin" "208 706.125 88" } { "classname" "info_monster_start" "origin" "177.875 628.5 88" } { "classname" "info_monster_start" "origin" "4.5 681 88" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/dm4ish.ent000066400000000000000000000372571475442401000250560ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "D:\Qoole\work\dm4ishc.wad" "message" "DM4-ish by Aardappel" "worldtype" "0" "light" "15" } { "classname" "weapon_rocketlauncher" "origin" "-704 -320 32" } { "classname" "item_health" "origin" "-560 -816 48" "angle" "90" "spawnflags" "2" } { "classname" "item_rockets" "origin" "-664 -704 112" "angle" "90" "spawnflags" "1" } { "classname" "item_armor1" "origin" "480 -800 32" } { "classname" "item_health" "origin" "336 -648 32" "angle" "90" } { "classname" "light" "origin" "-168 -192 -8" "light" "300" } { "classname" "light" "origin" "8 -192 -8" "light" "300" } { "classname" "light" "origin" "184 -192 -8" "light" "300" } { "classname" "light" "origin" "-184 104 -8" "light" "300" } { "classname" "light" "origin" "-40 104 -8" "light" "300" } { "classname" "light" "origin" "248 104 -8" "light" "300" } { "classname" "light" "origin" "-712 -440 -8" "light" "300" } { "classname" "light" "origin" "-712 -576 -8" "light" "300" } { "classname" "light" "origin" "-432 -584 -8" "light" "300" } { "classname" "light" "origin" "-432 -440 -8" "light" "300" } { "classname" "light" "origin" "-576 -800 56" "light" "200" } { "classname" "light" "origin" "-448 -320 40" "light" "200" } { "classname" "light" "origin" "-344 -64 40" "light" "200" } { "classname" "light" "origin" "360 -64 40" "light" "200" } { "classname" "light" "origin" "128 208 40" "light" "200" } { "classname" "light" "origin" "480 -800 40" "light" "200" } { "classname" "light" "origin" "120 -56 80" "light" "200" } { "classname" "light" "origin" "-600 -472 80" "light" "200" } { "classname" "light" "origin" "352 -720 176" "light" "200" } { "classname" "light" "origin" "-560 -64 56" "light" "150" } { "classname" "light" "origin" "464 -208 56" "light" "150" } { "classname" "light" "origin" "432 -424 56" "light" "150" } { "classname" "light" "origin" "480 -624 128" "light" "150" } { "classname" "light" "origin" "128 408 128" "light" "150" } { "classname" "light" "origin" "-248 -96 240" "light" "200" } { "classname" "light" "origin" "-32 280 216" "light" "300" } { "classname" "light" "origin" "464 -160 256" "light" "250" } { "classname" "light" "origin" "128 -672 240" "light" "300" } { "classname" "light" "origin" "408 112 200" "light" "200" } { "classname" "light" "origin" "408 -144 200" "light" "200" } { "classname" "light" "origin" "-16 -368 200" "light" "250" } { "classname" "light" "origin" "-184 -688 248" "light" "250" } { "classname" "info_player_start" "origin" "128 -64 64" "angle" "90" } { "classname" "weapon_lightning" "origin" "400 -144 192" } { "classname" "weapon_grenadelauncher" "origin" "-16 -368 208" } { "classname" "item_cells" "origin" "147 -379 200" "angle" "90" "spawnflags" "1" } { "classname" "item_armor1" "origin" "400 112 200" } { "classname" "item_artifact_super_damage" "origin" "-64 288 208" } { "classname" "weapon_supernailgun" "origin" "8 272 200" } { "classname" "item_spikes" "origin" "-156 348 368" "angle" "90" } { "classname" "item_health" "origin" "-80 400 400" "angle" "90" } { "classname" "item_health" "origin" "-16 400 400" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "-368 80 400" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "-576 -736 48" "angle" "90" } { "origin" "-14 257 184" "angle" "-90" "classname" "info_player_deathmatch" } { "origin" "59 -80 24" "angle" "180" "classname" "info_player_deathmatch" } { "origin" "-587 -670 24" "angle" "90" "classname" "info_player_deathmatch" } { "origin" "45 -683 184" "angle" "90" "classname" "info_player_deathmatch" } { "classname" "item_shells" "origin" "140 28 56" "angle" "90" } { "classname" "weapon_nailgun" "origin" "128 248 64" } { "classname" "item_shells" "origin" "172 652 160" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "256 600 152" "angle" "0" } { "classname" "item_spikes" "origin" "868 564 344" "angle" "90" } { "classname" "item_health" "origin" "904 496 352" "angle" "90" "spawnflags" "1" } { "classname" "item_health" "origin" "904 448 352" "angle" "90" "spawnflags" "1" } { "classname" "item_spikes" "origin" "908 76 368" "angle" "90" } { "classname" "item_cells" "origin" "811 -51 384" "angle" "90" "spawnflags" "1" } { "classname" "item_spikes" "origin" "-36 -636 384" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "-40 -840 384" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "-200 -1048 232" "angle" "45" } { "classname" "item_rockets" "origin" "-176 -512 232" "angle" "90" } { "classname" "item_shells" "origin" "-180 -556 232" "angle" "90" } { "classname" "item_spikes" "origin" "-180 -604 232" "angle" "90" } { "classname" "weapon_supershotgun" "origin" "-40 -840 232" } { "classname" "item_rockets" "origin" "176 -608 232" "angle" "90" } { "classname" "item_rockets" "origin" "176 -560 232" "angle" "90" } { "classname" "item_health" "origin" "160 -832 232" "angle" "90" "spawnflags" "1" } { "classname" "item_health" "origin" "112 -832 232" "angle" "90" "spawnflags" "1" } { "classname" "item_health" "origin" "160 -784 232" "angle" "90" "spawnflags" "1" } { "classname" "light" "origin" "400 -736 496" "light" "350" } { "classname" "light" "origin" "56 -120 448" "light" "300" } { "classname" "item_armor2" "origin" "672 384 384" } { "classname" "light" "origin" "736 416 424" "light" "400" } { "classname" "item_armorInv" "origin" "256 624 136" } { "classname" "weapon_rocketlauncher" "origin" "64 592 136" } { "classname" "light" "origin" "-392 96 392" "light" "200" } { "classname" "light" "origin" "-392 -168 392" "light" "200" } { "classname" "light" "origin" "256 -528 392" "light" "300" } { "classname" "light" "origin" "608 -160 392" "light" "250" } { "classname" "light" "origin" "-32 304 392" "light" "150" } { "classname" "light" "origin" "296 192 392" "light" "250" } { "classname" "light" "origin" "-96 424 392" "light" "200" } { "classname" "light" "origin" "224 320 392" "light" "200" } { "classname" "light" "origin" "608 240 392" "light" "200" } { "classname" "light" "origin" "816 -40 392" "light" "250" } { "classname" "light" "origin" "256 624 160" "light" "200" } { "classname" "light" "origin" "64 592 160" "light" "200" } { "classname" "light" "origin" "-56 -736 392" "light" "250" } { "classname" "light" "origin" "-152 -1048 384" "light" "250" } { "classname" "light" "origin" "480 592 216" "light" "150" } { "classname" "light" "origin" "656 544 296" "light" "150" } { "classname" "item_health" "origin" "464 -416 376" "angle" "90" } { "classname" "info_monster_start" "origin" "63.125 -437.5 184" } { "classname" "info_monster_start" "origin" "73.25 -368 184" } { "classname" "info_monster_start" "origin" "8 -363.125 184" } { "classname" "info_monster_start" "origin" "-90.5 -355.75 184" } { "classname" "info_monster_start" "origin" "180.5 -376.125 184" } { "classname" "info_monster_start" "origin" "249.125 -376.375 184" } { "classname" "info_monster_start" "origin" "340.75 -298.25 184" } { "classname" "info_monster_start" "origin" "409.875 -213.25 184" } { "classname" "info_monster_start" "origin" "444.375 -113.375 184" } { "classname" "info_monster_start" "origin" "427.125 -48.875 184" } { "classname" "info_monster_start" "origin" "441 52.875 184" } { "classname" "info_monster_start" "origin" "443.125 157.875 184" } { "classname" "info_monster_start" "origin" "507.125 252.375 344" } { "classname" "info_monster_start" "origin" "457.625 291.25 344" } { "classname" "info_monster_start" "origin" "349.625 296.375 344" } { "classname" "info_monster_start" "origin" "348.25 -53.625 24" } { "classname" "info_monster_start" "origin" "455.75 -83.25 24" } { "classname" "info_monster_start" "origin" "600 65.625 344" } { "classname" "info_monster_start" "origin" "220.25 299.875 344" } { "classname" "info_monster_start" "origin" "600.75 -125.75 344" } { "classname" "info_monster_start" "origin" "601 -209.125 344" } { "classname" "info_monster_start" "origin" "528.125 -333.625 344" } { "classname" "info_monster_start" "origin" "464.5 -394.125 344" } { "classname" "info_monster_start" "origin" "400.375 -454.875 344" } { "classname" "info_monster_start" "origin" "353.375 -499.5 344" } { "classname" "info_monster_start" "origin" "274 -501 344" } { "classname" "info_monster_start" "origin" "195 -502.5 344" } { "classname" "info_monster_start" "origin" "96.625 -504.375 344" } { "classname" "info_monster_start" "origin" "44 -592.625 344" } { "classname" "info_monster_start" "origin" "-8.875 -719.5 344" } { "classname" "info_monster_start" "origin" "-79.875 -719.125 344" } { "classname" "info_monster_start" "origin" "-61.625 -833.25 344" } { "classname" "info_monster_start" "origin" "31 -833.75 344" } { "classname" "info_monster_start" "origin" "116.625 -834.125 344" } { "classname" "info_monster_start" "origin" "196.5 -834.5 344" } { "classname" "info_monster_start" "origin" "207.875 -720.5 344" } { "classname" "info_monster_start" "origin" "310.25 -716.375 24" } { "classname" "info_monster_start" "origin" "312.125 -621.875 24" } { "classname" "info_monster_start" "origin" "446.25 -530.125 24" } { "classname" "info_monster_start" "origin" "448.125 -445.625 24" } { "classname" "info_monster_start" "origin" "450.125 -348 24" } { "classname" "info_monster_start" "origin" "452.125 -256 24" } { "classname" "info_monster_start" "origin" "453.75 -177.5 24" } { "classname" "info_monster_start" "origin" "259.5 -55 24" } { "classname" "info_monster_start" "origin" "161 -56.75 24" } { "classname" "info_monster_start" "origin" "128.5 49.875 24" } { "classname" "info_monster_start" "origin" "66.625 -58.375 24" } { "classname" "info_monster_start" "origin" "-29.5 -60 24" } { "classname" "info_monster_start" "origin" "-135.125 -61.75 24" } { "classname" "info_monster_start" "origin" "-236.25 -63.375 24" } { "classname" "info_monster_start" "origin" "-332.25 -65 24" } { "classname" "info_monster_start" "origin" "-413.5 -66.375 24" } { "classname" "info_monster_start" "origin" "-485.75 -67.625 24" } { "classname" "info_monster_start" "origin" "-579 -69.25 24" } { "classname" "info_monster_start" "origin" "-574.25 -196.5 24" } { "classname" "info_monster_start" "origin" "-575.125 -276.875 24" } { "classname" "info_monster_start" "origin" "-576.375 -378 24" } { "classname" "info_monster_start" "origin" "-577.5 -480.125 24" } { "classname" "info_monster_start" "origin" "-578.75 -586.625 24" } { "classname" "info_monster_start" "origin" "-580 -692.375 24" } { "classname" "info_monster_start" "origin" "-715.625 -682.5 24" } { "classname" "info_monster_start" "origin" "-427.25 -685.875 24" } { "classname" "info_monster_start" "origin" "-173.5 -675.875 184" } { "classname" "info_monster_start" "origin" "-78.625 -671.625 184" } { "classname" "info_monster_start" "origin" "-71.5 -818.5 184" } { "classname" "info_monster_start" "origin" "-180.5 -820.375 184" } { "classname" "info_monster_start" "origin" "-184.875 -1034.38 184" } { "classname" "info_monster_start" "origin" "65.75 -1027.88 280" } { "classname" "info_monster_start" "origin" "51 -812.875 184" } { "classname" "info_monster_start" "origin" "164.75 -807.625 184" } { "classname" "info_monster_start" "origin" "52.125 -685.75 184" } { "classname" "info_monster_start" "origin" "152.625 -681.125 184" } { "classname" "info_monster_start" "origin" "-188.5 -406.25 344" } { "classname" "info_monster_start" "origin" "-251.375 -347.5 344" } { "classname" "info_monster_start" "origin" "-314.875 -288.125 344" } { "classname" "info_monster_start" "origin" "-358 -243.875 344" } { "classname" "info_monster_start" "origin" "-359.5 -190.375 344" } { "classname" "info_monster_start" "origin" "-361.875 -105.125 344" } { "classname" "info_monster_start" "origin" "600.375 -28.25 344" } { "classname" "info_monster_start" "origin" "-363.875 -36.25 344" } { "classname" "info_monster_start" "origin" "-366.375 53.625 344" } { "classname" "info_monster_start" "origin" "-368.375 124.125 344" } { "classname" "info_monster_start" "origin" "-360.75 126.125 344" } { "classname" "info_monster_start" "origin" "-255.25 256.125 344" } { "classname" "info_monster_start" "origin" "-162.375 365.75 344" } { "classname" "info_monster_start" "origin" "-71.375 413.875 344" } { "classname" "info_monster_start" "origin" "8.5 416.375 344" } { "classname" "info_monster_start" "origin" "-108 291.875 184" } { "classname" "info_monster_start" "origin" "-23 287.5 184" } { "classname" "info_monster_start" "origin" "102.875 359.125 344" } { "classname" "info_monster_start" "origin" "623 218.125 344" } { "classname" "info_monster_start" "origin" "732.125 221.625 344" } { "classname" "info_monster_start" "origin" "732.5 109 344" } { "classname" "info_monster_start" "origin" "730.875 3.375 344" } { "classname" "info_monster_start" "origin" "887.5 4 344" } { "classname" "info_monster_start" "origin" "885.75 135.625 344" } { "classname" "info_monster_start" "origin" "883.125 276.375 344" } { "classname" "info_monster_start" "origin" "881.25 374.875 344" } { "classname" "info_monster_start" "origin" "877.75 562.875 344" } { "classname" "info_monster_start" "origin" "879.75 457.625 344" } { "classname" "info_monster_start" "origin" "754.375 343.875 344" } { "classname" "info_monster_start" "origin" "653.625 333.25 344" } { "classname" "info_monster_start" "origin" "659.5 432.875 344" } { "classname" "info_monster_start" "origin" "760 439 344" } { "classname" "info_monster_start" "origin" "719.875 573.125 296" } { "classname" "info_monster_start" "origin" "602.125 572.375 248" } { "classname" "info_monster_start" "origin" "484.125 571.625 184" } { "classname" "info_monster_start" "origin" "340.5 570.75 136" } { "classname" "info_monster_start" "origin" "223.375 570 136" } { "classname" "info_monster_start" "origin" "36.25 568.75 136" } { "classname" "info_monster_start" "origin" "88.875 674.125 136" } { "classname" "info_monster_start" "origin" "273.25 675.375 136" } { "classname" "info_monster_start" "origin" "176.125 674.75 136" } { "classname" "info_monster_start" "origin" "121.875 569.25 136" } { "classname" "info_monster_start" "origin" "53 282.875 184" } { "classname" "info_monster_start" "origin" "136.5 344.625 72" } { "classname" "info_monster_start" "origin" "596 -269.375 344" } { "classname" "info_monster_start" "origin" "451.625 -812.125 24" } { "classname" "info_monster_start" "origin" "329.25 -809.625 24" } { "classname" "info_monster_start" "origin" "453.375 -723.75 24" } { "classname" "info_monster_start" "origin" "489.75 -617.5 24" } { "classname" "info_monster_start" "origin" "132.75 207.5 24" } { "classname" "info_monster_start" "origin" "-581.25 -799.375 24" } { "classname" "info_monster_start" "origin" "-729 -336 24" } { "classname" "info_monster_start" "origin" "-442.375 -333.375 24" } { "classname" "info_monster_start" "origin" "-126.5 -464.125 344" } { "classname" "info_monster_start" "origin" "-157.625 -532.5 184" } { "classname" "info_monster_start" "origin" "-69 -535.375 184" } { "classname" "info_monster_start" "origin" "35 -538.75 184" } { "classname" "info_monster_start" "origin" "142.25 -542.25 184" } { "classname" "info_monster_start" "origin" "92 -720 344" } { "classname" "info_monster_start" "origin" "-72.125 -507.5 344" } { "classname" "info_monster_start" "origin" "-79.875 -592 344" } { "classname" "info_monster_start" "origin" "7.625 -506 344" } { "classname" "info_monster_start" "origin" "124.75 -593 344" } { "classname" "info_monster_start" "origin" "207.875 -593.375 344" } { "classname" "info_teleport_destination" "targetname" "tunnel_exit1" "origin" "726 5 344" "angle" "-90" } { "classname" "trigger_custom_teleport" "origin" "728 102 344" "size" "32 32 32" "target" "tunnel_exit2" } { "classname" "info_teleport_destination" "targetname" "tunnel_exit2" "origin" "-357 103 344" "angle" "-90" } { "classname" "trigger_custom_teleport" "origin" "-336 188 344" "size" "32 32 32" "target" "tunnel_exit1" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/e1m7.ent000066400000000000000000000537171475442401000244360ustar00rootroot00000000000000{ "wad" "gfx/metal.wad" "classname" "worldspawn" "worldtype" "1" "sounds" "7" "message" "The House of Chthon" } { "angle" "0" "origin" "-448 64 56" "classname" "info_player_start" } { "origin" "256 256 80" "classname" "light" } { "classname" "light" "origin" "480 448 256" } { "origin" "488 -320 256" "classname" "light" } { "classname" "light" "origin" "1024 -320 256" } { "origin" "1024 448 256" "classname" "light" } { "classname" "light" "origin" "-280 408 312" } { "origin" "-256 -256 320" "classname" "light" } { "classname" "light" "origin" "832 256 80" } { "origin" "-256 64 120" "classname" "light" } { "classname" "light" "origin" "-512 64 120" } { "origin" "832 -128 80" "classname" "light" } { "classname" "light" "origin" "576 -128 80" } { "origin" "256 -128 80" "classname" "light" } { "classname" "light" "origin" "64 -128 80" } { "origin" "64 256 80" "classname" "light" } { "classname" "light" "origin" "-64 208 80" } { "origin" "-64 -80 80" "classname" "light" } { "origin" "360 -56 80" "classname" "light" } { "classname" "light" "origin" "360 184 80" } { "origin" "864 64 232" "classname" "light" } { "classname" "light" "origin" "-320 64 224" "light" "200" } { "origin" "1024 88 -56" "classname" "light" } { "origin" "0 328 256" "classname" "light" } { "classname" "light" "origin" "0 -200 256" } { "light" "200" "origin" "-128 64 224" "classname" "light" } { "classname" "light" "origin" "64 64 288" "light" "200" } { "classname" "monster_boss" "origin" "304 64 -48" "angle" "180" "targetname" "t4" "target" "t10" } { "light" "300" "origin" "352 64 472" "classname" "light" } { "origin" "-158 354 116" "classname" "light_torch_small_walltorch" } { "light" "150" "origin" "-192 384 112" "classname" "light" } { "classname" "light" "origin" "-96 416 112" "light" "150" } { "classname" "light_torch_small_walltorch" "origin" "-158 -222 116" } { "classname" "light" "origin" "-192 -256 112" "light" "150" } { "light" "150" "origin" "-96 -288 112" "classname" "light" } { "origin" "1216 64 184" "classname" "light" } { "origin" "930 -222 52" "classname" "light_torch_small_walltorch" } { "classname" "light_torch_small_walltorch" "origin" "922 346 52" } { "classname" "light" "origin" "984 408 56" "light" "150" } { "light" "150" "origin" "984 -280 56" "classname" "light" } { "classname" "light" "origin" "872 -304 56" "light" "150" } { "light" "150" "origin" "872 424 56" "classname" "light" } { "classname" "light" "origin" "1024 40 -56" } { "classname" "light" "origin" "1024 64 -24" "light" "150" } { "classname" "func_plat" "height" "176" "model" "*1" } { "light" "150" "origin" "1024 288 56" "classname" "light" } { "classname" "light" "origin" "1024 -160 56" "light" "150" } { "classname" "light" "origin" "768 352 88" "light" "150" } { "light" "150" "origin" "512 352 88" "classname" "light" } { "classname" "light" "origin" "192 352 88" "light" "150" } { "light" "150" "origin" "64 352 88" "classname" "light" } { "light" "150" "origin" "768 -224 88" "classname" "light" } { "classname" "light" "origin" "512 -224 88" "light" "150" } { "light" "150" "origin" "192 -224 88" "classname" "light" } { "classname" "light" "origin" "64 -224 88" "light" "150" } { "classname" "light" "origin" "80 64 448" } { "origin" "768 64 448" "classname" "light" } { "classname" "light" "origin" "640 64 448" } { "origin" "448 64 448" "classname" "light" } { "classname" "light" "origin" "256 64 448" } { "classname" "weapon_supershotgun" "origin" "-160 64 208" "spawnflags" "1792" } { "classname" "item_health" "origin" "-312 -312 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-312 -280 208" "classname" "item_health" } { "classname" "item_health" "origin" "-280 -312 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-312 408 208" "classname" "item_health" } { "classname" "item_health" "origin" "-312 376 208" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "-280 408 208" "classname" "item_health" } { "classname" "item_health" "origin" "1048 472 192" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "1048 440 192" "classname" "item_health" } { "classname" "item_health" "origin" "1048 -376 192" "spawnflags" "1792" } { "spawnflags" "1792" "origin" "1048 -344 192" "classname" "item_health" } { "classname" "item_shells" "origin" "48 432 32" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "752 432 32" "classname" "item_shells" } { "classname" "item_shells" "origin" "48 -336 32" "spawnflags" "1793" } { "classname" "item_shells" "origin" "752 -336 32" "spawnflags" "1793" } { "classname" "item_rockets" "origin" "1008 -272 192" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "1008 368 192" "classname" "item_rockets" } { "classname" "weapon_supernailgun" "origin" "1120 64 -32" "spawnflags" "1792" } { "classname" "item_spikes" "origin" "344 392 32" "spawnflags" "1793" } { "spawnflags" "1793" "origin" "344 -296 32" "classname" "item_spikes" } { "classname" "weapon_grenadelauncher" "origin" "-392 64 32" "spawnflags" "1792" } { "classname" "func_wall" "spawnflags" "1792" "model" "*2" } { "classname" "info_player_deathmatch" "origin" "704 -360 280" "angle" "90" } { "spawnflags" "1792" "classname" "func_wall" "model" "*3" } { "angle" "90" "origin" "128 -360 280" "classname" "info_player_deathmatch" } { "classname" "func_wall" "spawnflags" "1792" "model" "*4" } { "spawnflags" "1792" "classname" "func_wall" "model" "*5" } { "classname" "info_player_deathmatch" "origin" "128 488 280" "angle" "270" } { "angle" "270" "origin" "704 488 280" "classname" "info_player_deathmatch" } { "classname" "info_player_deathmatch" "origin" "-256 64 64" } { "classname" "info_player_deathmatch" "origin" "-256 64 240" "angle" "0" } { "origin" "-275 -315 56" "angle" "0" "classname" "info_player_deathmatch" } { "spawnflags" "1792" "classname" "func_wall" "model" "*6" } { "classname" "func_wall" "spawnflags" "1792" "model" "*7" } { "angle" "180" "origin" "1024 64 176" "classname" "info_player_deathmatch" } { "origin" "-480 208 120" "classname" "light" } { "classname" "info_teleport_destination" "origin" "-256 64 224" "targetname" "t8" "angle" "0" "spawnflags" "1792" } { "light" "250" "origin" "712 64 16" "classname" "light" } { "origin" "560 -48 0" "targetname" "t10" "target" "t9" "classname" "trigger_relay" } { "wait" "-1" "spawnflags" "1" "targetname" "t9" "angle" "270" "classname" "func_door" "model" "*8" } { "wait" "-1" "spawnflags" "1" "targetname" "t9" "angle" "90" "classname" "func_door" "model" "*9" } { "light" "200" "classname" "light" "origin" "840 64 -976" } { "classname" "light" "origin" "832 64 -704" } { "classname" "light" "origin" "840 80 -576" } { "classname" "light" "origin" "824 48 -448" } { "classname" "light" "origin" "840 56 -288" } { "classname" "light" "origin" "816 72 -160" } { "light" "150" "origin" "720 112 -920" "classname" "light" } { "classname" "light" "origin" "720 16 -920" "light" "150" } { "target" "t4" "spawnflags" "2049" "origin" "8 64 24" "classname" "item_sigil" } { "light" "200" "origin" "576 184 0" "classname" "light" } { "classname" "light" "origin" "576 -8 0" "light" "200" } { "mangle" "20 315 0" "origin" "-16 384 368" "classname" "info_intermission" } { "classname" "func_door" "spawnflags" "1" "targetname" "t12" "angle" "-1" "lip" "64" "wait" "20" "target" "lightning" "model" "*10" } { "classname" "func_door" "spawnflags" "1" "targetname" "t13" "angle" "-1" "lip" "64" "wait" "20" "target" "lightning" "model" "*11" } { "angle" "-2" "classname" "func_button" "target" "t13" "spawnflags" "2816" "model" "*12" } { "classname" "func_button" "angle" "-2" "target" "t14" "model" "*13" } { "classname" "event_lightning" "origin" "768 -40 224" "targetname" "t14" } { "spawnflags" "1026" "origin" "976 48 -32" "classname" "item_health" } { "light" "250" "origin" "1064 56 -1008" "classname" "light" } { "light" "250" "origin" "662 160 -1044" "classname" "light_flame_large_yellow" } { "classname" "light_flame_large_yellow" "origin" "670 -32 -1044" "light" "250" } { "light" "150" "origin" "896 56 -816" "classname" "light" } { "classname" "light" "origin" "760 64 -816" "light" "150" } { "map" "start" "classname" "trigger_changelevel" "target" "t18" "model" "*14" } { "target" "t15" "classname" "trigger_teleport" "model" "*15" } { "targetname" "t15" "angle" "180" "origin" "944 56 -952" "classname" "info_teleport_destination" } { "angle" "0" "origin" "-472 136 56" "classname" "info_player_coop" } { "classname" "info_player_coop" "origin" "-480 -8 56" "angle" "0" } { "angle" "270" "origin" "-256 208 56" "classname" "info_player_coop" } { "classname" "light" "origin" "224 -320 200" "light" "150" } { "light" "150" "origin" "224 448 200" "classname" "light" } { "spawnflags" "1792" "target" "t9" "wait" "-1" "angle" "270" "classname" "func_button" "model" "*16" } { "classname" "func_button" "angle" "-2" "target" "t13" "spawnflags" "1024" "model" "*17" } { "classname" "func_wall" "spawnflags" "1024" "model" "*18" } { "classname" "func_wall" "spawnflags" "2816" "model" "*19" } { "classname" "item_spikes" "origin" "328 392 32" "spawnflags" "1793" } { "spawnflags" "2816" "classname" "func_button" "angle" "-2" "target" "t12" "model" "*20" } { "spawnflags" "1024" "angle" "-2" "classname" "func_button" "target" "t12" "model" "*21" } { "spawnflags" "1024" "classname" "func_wall" "model" "*22" } { "spawnflags" "2816" "classname" "func_wall" "model" "*23" } { "classname" "monster_shambler" "origin" "1544 344 24" } { "origin" "1632 344 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1848 344 24" } { "origin" "1760 344 24" "classname" "monster_shambler" } { "classname" "trigger_teleport" "targetname" "t17" "target" "t19" "model" "*24" } { "classname" "trigger_teleport" "targetname" "t17" "target" "t20" "model" "*25" } { "classname" "trigger_once" "targetname" "t16" "target" "t27" "delay" "4.8" "model" "*26" } { "classname" "trigger_once" "targetname" "t16" "target" "t22" "delay" "2.8" "model" "*27" } { "classname" "trigger_once" "targetname" "t16" "target" "t17" "delay" "0.2" "model" "*28" } { "classname" "trigger_once" "targetname" "t16" "target" "t21" "delay" "2" "model" "*29" } { "classname" "trigger_relay" "origin" "1512 128 32" "target" "t16" "targetname" "t18" } { "classname" "info_teleport_destination" "origin" "128 192 320" "targetname" "t19" } { "origin" "128 -64 320" "classname" "info_teleport_destination" "targetname" "t20" } { "origin" "1848 224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1760 224 24" } { "origin" "1632 224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1544 224 24" } { "origin" "1848 -224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1760 -224 24" } { "origin" "1632 -224 24" "classname" "monster_shambler" } { "classname" "monster_shambler" "origin" "1544 -224 24" } { "classname" "trigger_teleport" "targetname" "t21" "target" "t25" "model" "*30" } { "classname" "trigger_teleport" "targetname" "t21" "target" "t26" "model" "*31" } { "classname" "trigger_teleport" "targetname" "t22" "target" "t24" "model" "*32" } { "classname" "trigger_teleport" "targetname" "t22" "target" "t23" "model" "*33" } { "classname" "info_teleport_destination" "origin" "352 128 224" "angle" "180" "targetname" "t23" } { "origin" "352 -32 224" "classname" "info_teleport_destination" "angle" "180" "targetname" "t24" } { "classname" "info_teleport_destination" "origin" "576 -96 312" "angle" "180" "targetname" "t26" } { "origin" "672 88 312" "classname" "info_teleport_destination" "angle" "180" "targetname" "t25" } { "classname" "monster_zombie" "origin" "1760 128 24" } { "origin" "1824 128 24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1568 128 24" } { "origin" "1632 128 24" "classname" "monster_zombie" } { "classname" "trigger_teleport" "targetname" "t27" "target" "t29" "model" "*34" } { "classname" "trigger_teleport" "targetname" "t27" "target" "t28" "model" "*35" } { "classname" "info_teleport_destination" "origin" "248 352 216" "angle" "180" "targetname" "t29" } { "classname" "info_teleport_destination" "origin" "560 -224 216" "angle" "180" "targetname" "t28" } { "classname" "monster_zombie" "origin" "1824 64 24" } { "origin" "1760 64 24" "classname" "monster_zombie" } { "classname" "monster_zombie" "origin" "1632 64 24" } { "origin" "1568 64 24" "classname" "monster_zombie" } { "classname" "trigger_teleport" "targetname" "t30" "target" "t32" "model" "*36" } { "classname" "trigger_teleport" "targetname" "t30" "target" "t31" "model" "*37" } { "classname" "trigger_once" "targetname" "t16" "target" "t30" "delay" "6.3" "model" "*38" } { "classname" "info_teleport_destination" "origin" "688 352 200" "angle" "180" "targetname" "t31" } { "classname" "info_teleport_destination" "origin" "128 -224 200" "angle" "180" "targetname" "t32" } { "classname" "func_door" "angle" "-2" "wait" "-1" "sounds" "3" "targetname" "t9" "spawnflags" "2048" "model" "*39" } { "spawnflags" "1792" "origin" "984 -328 192" "classname" "weapon_rocketlauncher" } { "spawnflags" "1792" "origin" "984 440 192" "classname" "weapon_grenadelauncher" } { "spawnflags" "1792" "origin" "-224 376 192" "classname" "weapon_supernailgun" } { "spawnflags" "1792" "origin" "-216 -288 192" "classname" "weapon_supershotgun" } { "spawnflags" "1792" "origin" "352 456 32" "classname" "weapon_nailgun" } { "spawnflags" "1792" "origin" "0 64 24" "classname" "item_artifact_super_damage" } { "classname" "info_monster_start" "origin" "1133.5 66.75 -7.875" } { "classname" "info_monster_start" "origin" "1022.5 81.875 -7.875" } { "classname" "info_monster_start" "origin" "1024.12 -11.25 -7.875" } { "classname" "info_monster_start" "origin" "1025.75 -104.25 -7.875" } { "classname" "info_monster_start" "origin" "930.25 -110.375 216" } { "classname" "info_monster_start" "origin" "952.625 -209.125 216" } { "classname" "info_monster_start" "origin" "893 -232.75 216" } { "classname" "info_monster_start" "origin" "1045.75 -212.625 216" } { "classname" "info_monster_start" "origin" "1042.5 -347.25 216" } { "classname" "info_monster_start" "origin" "936.875 -340.375 216" } { "classname" "info_monster_start" "origin" "800.125 -226.625 216" } { "classname" "info_monster_start" "origin" "665.625 -322.75 56" } { "classname" "info_monster_start" "origin" "569 -323.5 56" } { "classname" "info_monster_start" "origin" "461.375 -324.375 56" } { "classname" "info_monster_start" "origin" "403.375 -356 216" } { "classname" "info_monster_start" "origin" "302.25 -347.125 216" } { "classname" "info_monster_start" "origin" "304.125 -230.625 220" } { "classname" "info_monster_start" "origin" "350.375 -325.25 56" } { "classname" "info_monster_start" "origin" "901.125 356.875 216" } { "classname" "info_monster_start" "origin" "532.875 454.625 56" } { "classname" "info_monster_start" "origin" "243.625 454.25 56" } { "classname" "info_monster_start" "origin" "142.125 454.125 56" } { "classname" "info_monster_start" "origin" "-138.5 453.875 56" } { "classname" "info_monster_start" "origin" "1016.25 446 -7.875" } { "classname" "info_monster_start" "origin" "1017.62 361.75 -7.875" } { "classname" "info_monster_start" "origin" "1019.12 277.125 -7.875" } { "classname" "info_monster_start" "origin" "1027.25 -189.625 -7.875" } { "classname" "info_monster_start" "origin" "1029 -286.25 -7.875" } { "classname" "info_monster_start" "origin" "17 -328 56" } { "classname" "info_monster_start" "origin" "-92.625 -328.875 56" } { "classname" "info_monster_start" "origin" "-183.75 -329.625 56" } { "classname" "info_monster_start" "origin" "-264.375 201.375 56" } { "classname" "info_monster_start" "origin" "-262.75 313.75 56" } { "classname" "info_monster_start" "origin" "-274.125 364.25 232" } { "classname" "info_monster_start" "origin" "-264.125 263.375 232" } { "classname" "info_monster_start" "origin" "-420.875 175.875 56" } { "classname" "info_monster_start" "origin" "-527.875 175.875 56" } { "classname" "info_monster_start" "origin" "-527 -30.125 56" } { "classname" "info_monster_start" "origin" "-260.5 -24 232" } { "classname" "info_monster_start" "origin" "-259 -132.75 232" } { "classname" "info_monster_start" "origin" "-257.625 -241.5 232" } { "classname" "info_monster_start" "origin" "-135.875 -251.5 232" } { "classname" "info_monster_start" "origin" "-19 -209.5 216" } { "classname" "info_monster_start" "origin" "1055.38 358 216" } { "classname" "info_monster_start" "origin" "979.75 357.5 216" } { "classname" "info_monster_start" "origin" "392.375 466 216" } { "classname" "info_monster_start" "origin" "1058.38 467.375 216" } { "classname" "info_monster_start" "origin" "973.125 466.75 216" } { "classname" "info_monster_start" "origin" "626.5 354.875 216" } { "classname" "info_monster_start" "origin" "676.5 495.75 280" } { "classname" "info_monster_start" "origin" "751.625 495.75 280" } { "classname" "info_monster_start" "origin" "734.75 -365.125 280" } { "classname" "info_monster_start" "origin" "667 -365.5 280" } { "classname" "info_monster_start" "origin" "149.25 -366.5 280" } { "classname" "info_monster_start" "origin" "84.375 -367.875 280" } { "classname" "info_monster_start" "origin" "61.625 -214.75 216" } { "classname" "info_monster_start" "origin" "161.625 491.375 280" } { "classname" "info_monster_start" "origin" "95.75 488.75 280" } { "classname" "info_monster_start" "origin" "234.375 352.125 216" } { "classname" "info_monster_start" "origin" "135.5 351.375 216" } { "classname" "info_monster_start" "origin" "52 454.125 56" } { "classname" "info_monster_start" "origin" "109.625 350 56" } { "classname" "info_monster_start" "origin" "206.875 345 56" } { "classname" "info_monster_start" "origin" "296.875 466.125 216" } { "classname" "info_monster_start" "origin" "324.5 352.75 220" } { "classname" "info_monster_start" "origin" "533.375 354.25 216" } { "classname" "info_monster_start" "origin" "429.75 353.5 216" } { "classname" "info_monster_start" "origin" "342 454.375 56" } { "classname" "info_monster_start" "origin" "434 454.5 56" } { "classname" "info_monster_start" "origin" "466.75 369.75 56" } { "classname" "info_monster_start" "origin" "544 365.75 56" } { "classname" "info_monster_start" "origin" "626 454.75 56" } { "classname" "info_monster_start" "origin" "642.625 360.625 56" } { "classname" "info_monster_start" "origin" "722.375 454.875 56" } { "classname" "info_monster_start" "origin" "795.25 454.875 56" } { "classname" "info_monster_start" "origin" "448.125 -203.625 216" } { "classname" "info_monster_start" "origin" "527.75 -208.875 216" } { "classname" "info_monster_start" "origin" "615.625 -214.625 216" } { "classname" "info_monster_start" "origin" "713.875 -221 216" } { "classname" "info_monster_start" "origin" "761.5 -322 56" } { "classname" "info_monster_start" "origin" "824.75 -321.5 56" } { "classname" "info_monster_start" "origin" "144.125 -220.25 216" } { "classname" "info_monster_start" "origin" "226.375 -225.625 216" } { "classname" "info_monster_start" "origin" "232 -326.25 56" } { "classname" "info_monster_start" "origin" "119.625 -327.125 56" } { "classname" "info_monster_start" "origin" "734.5 -230.5 56" } { "classname" "info_monster_start" "origin" "815.375 -232.25 56" } { "classname" "info_monster_start" "origin" "778.75 353.5 56" } { "classname" "info_monster_start" "origin" "815.875 351.625 56" } { "classname" "info_monster_start" "origin" "1020.75 182 -7.875" } { "classname" "info_monster_start" "origin" "818.25 356.25 216" } { "classname" "info_monster_start" "origin" "1126.88 63.375 168" } { "classname" "info_monster_start" "origin" "1033.62 64.5 172" } { "classname" "info_monster_start" "origin" "933 222.375 216" } { "classname" "info_monster_start" "origin" "894.875 66.375 168" } { "classname" "info_monster_start" "origin" "808.375 71.375 172" } { "classname" "info_monster_start" "origin" "722.25 355.625 216" } { "classname" "info_monster_start" "origin" "645.375 -228.5 56" } { "classname" "info_monster_start" "origin" "548.625 -226.375 56" } { "classname" "info_monster_start" "origin" "464 -224.375 56" } { "classname" "info_monster_start" "origin" "237.375 -220.875 56" } { "classname" "info_monster_start" "origin" "121.75 -218.25 56" } { "classname" "info_monster_start" "origin" "30.25 -216.25 56" } { "classname" "info_monster_start" "origin" "16.5 354.875 56" } { "classname" "info_monster_start" "origin" "42.25 350.75 216" } { "classname" "info_monster_start" "origin" "-29.25 350.25 216" } { "classname" "info_monster_start" "origin" "-121.25 368.75 232" } { "classname" "info_monster_start" "origin" "-360.375 55.875 232" } { "classname" "info_monster_start" "origin" "-261.875 84.875 236" } { "classname" "info_monster_start" "origin" "-156.75 63.125 232" } { "classname" "info_monster_start" "origin" "-12.375 64.25 8" } { "classname" "info_monster_start" "origin" "-164.75 57.25 40" } { "classname" "info_monster_start" "origin" "-535.875 73 56" } { "classname" "info_monster_start" "origin" "-431.5 67.875 56" } { "classname" "info_monster_start" "origin" "-421.125 -35.25 56" } { "classname" "info_monster_start" "origin" "-267.5 -318.625 56" } { "classname" "info_monster_start" "origin" "-184.125 -231.875 56" } { "classname" "info_monster_start" "origin" "-266.125 -221.5 56" } { "classname" "info_monster_start" "origin" "-264.875 -128.375 56" } { "classname" "info_monster_start" "origin" "-264 -59.875 56" } { "classname" "info_monster_start" "origin" "-339.5 80.25 56" } { "classname" "info_monster_start" "origin" "-238.375 75.375 56" } { "classname" "info_monster_start" "origin" "-263 170.125 232" } { "classname" "info_monster_start" "origin" "-207.125 366.25 232" } { "classname" "info_monster_start" "origin" "-42.875 454 56" } { "classname" "info_monster_start" "origin" "-267.125 465.125 56" } { "classname" "info_monster_start" "origin" "-262 390.625 56" } { "classname" "info_monster_start" "origin" "-180 363.875 56" } { "classname" "info_teleport_destination" "targetname" "rune_spot" "origin" "-10.75 62.5 8" } { "classname" "trigger_custom_teleport" "origin" "826 62 24" "size" "32 32 32" "target" "rune_spot" } { "classname" "trigger_custom_monsterjump" "origin" "120 -205 33" "size" "100 1 1" "angle" "90" "speed" "1400" "height" "200" } { "classname" "trigger_custom_monsterjump" "origin" "120 336 33" "size" "100 1 1" "angle" "-90" "speed" "1400" "height" "200" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/fragyard.ent000066400000000000000000000552331475442401000254570ustar00rootroot00000000000000{ "classname" "worldspawn" "worldtype" "0" "sounds" "1" "light" "0" "message" "The Fragyard" } { "classname" "info_player_start" "angle" "135" "origin" "912 -496 -792" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "90 -378 -768" } { "classname" "light" "light" "200" "style" "0" "origin" "952 -480 -696" } { "classname" "light" "light" "200" "style" "0" "origin" "-272 728 -700" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-22 -374 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "518 -378 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "634 -378 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "790 -90 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "790 -190 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-166 -86 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-170 -186 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-170 366 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-170 478 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "90 634 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-22 634 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "518 634 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "634 634 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "794 362 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "790 470 -764" } { "classname" "item_artifact_super_damage" "origin" "320 136 -742" } { "classname" "misc_fireball" "speed" "40" "origin" "320 80 -788" } { "classname" "weapon_lightning" "origin" "-316 -519 -574" } { "classname" "weapon_lightning" "origin" "944 784 -576" } { "classname" "weapon_grenadelauncher" "origin" "-316 784 -568" } { "classname" "weapon_grenadelauncher" "origin" "938 -508 -566" } { "classname" "misc_fireball" "speed" "40" "origin" "320 194 -788" } { "classname" "misc_fireball" "speed" "40" "origin" "372 136 -788" } { "classname" "misc_fireball" "speed" "40" "origin" "272 136 -788" } { "classname" "weapon_rocketlauncher" "origin" "80 383 -777" } { "classname" "weapon_supernailgun" "origin" "544 -120 -774" } { "classname" "weapon_supershotgun" "origin" "88 -120 -766" } { "classname" "weapon_nailgun" "origin" "547 383 -763" } { "classname" "item_cells" "origin" "576 -384 -819" } { "classname" "item_cells" "origin" "32 592 -832" } { "classname" "weapon_supershotgun" "origin" "747 -336 -802" } { "classname" "weapon_supershotgun" "origin" "-122 576 -792" } { "classname" "weapon_supernailgun" "origin" "-124 -324 -792" } { "classname" "weapon_supernailgun" "origin" "752 592 -786" } { "classname" "weapon_grenadelauncher" "origin" "324 591 -683" } { "classname" "weapon_supernailgun" "origin" "324 -336 -680" } { "classname" "weapon_rocketlauncher" "origin" "938 -519 -797" } { "classname" "weapon_supernailgun" "angle" "315" "origin" "-320 784 -802" } { "classname" "weapon_nailgun" "angle" "45" "origin" "-322 -516 -791" } { "classname" "weapon_supershotgun" "origin" "944 784 -783" } { "classname" "item_rockets" "origin" "848 686 -832" } { "classname" "item_rockets" "origin" "-240 672 -832" } { "classname" "item_rockets" "origin" "-240 -448 -832" } { "classname" "item_rockets" "origin" "832 -448 -832" } { "classname" "info_player_deathmatch" "angle" "270" "origin" "320 803 -648" } { "classname" "info_player_deathmatch" "origin" "-352 116 -648" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "322 -543 -653" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "939 776 -792" } { "classname" "info_player_deathmatch" "angle" "315" "origin" "-323 777 -789" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "-323 -512 -794" } { "classname" "info_player_deathmatch" "angle" "135" "origin" "746 -329 -806" } { "classname" "info_player_deathmatch" "angle" "45" "origin" "-126 -334 -783" } { "classname" "info_player_deathmatch" "angle" "315" "origin" "-127 589 -790" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "746 593 -798" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "961 117 -655" } { "classname" "info_intermission" "angle" "135" "origin" "760 -334 -662" } { "classname" "info_intermission" "angle" "135" "origin" "417 37 -781" } { "classname" "info_intermission" "angle" "225" "origin" "221 237 -786" } { "classname" "info_intermission" "angle" "180" "origin" "742 139 -671" } { "classname" "info_intermission" "origin" "-130 159 -665" } { "classname" "light" "light" "600" "style" "0" "origin" "320 136 -524" } { "classname" "light" "light" "450" "style" "0" "origin" "552 376 -488" } { "classname" "light" "light" "450" "style" "0" "origin" "552 -120 -504" } { "classname" "light" "light" "450" "style" "0" "origin" "72 376 -504" } { "classname" "light" "light" "450" "style" "0" "origin" "72 -120 -488" } { "classname" "light" "light" "400" "style" "0" "origin" "872 136 -440" } { "classname" "light" "light" "400" "style" "0" "origin" "312 728 -456" } { "classname" "light" "light" "500" "style" "0" "origin" "-280 104 -488" } { "classname" "light" "light" "500" "style" "0" "origin" "312 -472 -456" } { "classname" "light" "light" "400" "style" "0" "origin" "828 -424 -476" } { "classname" "light" "light" "400" "style" "0" "origin" "824 664 -472" } { "classname" "light" "light" "400" "style" "0" "origin" "-232 680 -456" } { "classname" "light" "light" "400" "style" "0" "origin" "-232 -424 -456" } { "classname" "light_flame_large_yellow" "light" "400" "style" "0" "origin" "-326 772 -658" } { "classname" "light_flame_large_yellow" "light" "400" "style" "0" "origin" "922 772 -658" } { "classname" "light_flame_large_yellow" "light" "400" "style" "0" "origin" "922 -508 -658" } { "classname" "light_flame_large_yellow" "light" "400" "style" "0" "origin" "-326 -508 -658" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "162 662 -764" } { "classname" "light_torch_small_walltorch" "origin" "474 662 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "162 826 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "474 826 -764" } { "classname" "light" "light" "200" "style" "0" "origin" "320 80 -800" } { "classname" "light" "light" "200" "style" "0" "origin" "373 135 -800" } { "classname" "light" "light" "200" "style" "0" "origin" "320 194 -800" } { "classname" "light" "light" "200" "style" "0" "origin" "272 135 -800" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "162 -570 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "162 -406 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "474 -406 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "474 -570 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-378 -46 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-198 -46 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-378 310 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "-198 310 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "822 -46 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "822 310 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "986 310 -764" } { "classname" "light_torch_small_walltorch" "light" "200" "style" "0" "origin" "986 -46 -764" } { "classname" "info_monster_start" "origin" "160.875 -84.625 -791.875" } { "classname" "info_monster_start" "origin" "259.125 -125 -807.875" } { "classname" "info_monster_start" "origin" "334.875 -126.625 -807.875" } { "classname" "info_monster_start" "origin" "409.25 -128.25 -807.875" } { "classname" "info_monster_start" "origin" "537.25 9.5 -807.875" } { "classname" "info_monster_start" "origin" "544.75 106.25 -807.875" } { "classname" "info_monster_start" "origin" "551.5 192.625 -807.875" } { "classname" "info_monster_start" "origin" "557.25 267.25 -807.875" } { "classname" "info_monster_start" "origin" "443.625 385.5 -807.875" } { "classname" "info_monster_start" "origin" "342.25 386.5 -807.875" } { "classname" "info_monster_start" "origin" "273.375 387.125 -807.875" } { "classname" "info_monster_start" "origin" "196 387.875 -807.875" } { "classname" "info_monster_start" "origin" "112.125 290.125 -807.875" } { "classname" "info_monster_start" "origin" "108.25 197 -807.875" } { "classname" "info_monster_start" "origin" "103.875 95.625 -807.875" } { "classname" "info_monster_start" "origin" "100.625 17.375 -807.875" } { "classname" "info_monster_start" "origin" "-133.5 64.375 -807.875" } { "classname" "info_monster_start" "origin" "-133 -33.375 -807.875" } { "classname" "info_monster_start" "origin" "-118.875 12.75 -679.875" } { "classname" "info_monster_start" "origin" "-119.375 -75.625 -679.875" } { "classname" "info_monster_start" "origin" "-120 -169.375 -679.875" } { "classname" "info_monster_start" "origin" "-345.625 31.5 -640.625" } { "classname" "info_monster_start" "origin" "-345.5 -58.375 -626.375" } { "classname" "info_monster_start" "origin" "-345.5 -166.375 -609.375" } { "classname" "info_monster_start" "origin" "-345.375 -258.75 -594.75" } { "classname" "info_monster_start" "origin" "-345.25 -353.625 -579.75" } { "classname" "info_monster_start" "origin" "-345.75 125.625 -647.875" } { "classname" "info_monster_start" "origin" "-345.875 214 -638.625" } { "classname" "info_monster_start" "origin" "-345.875 289 -627.375" } { "classname" "info_monster_start" "origin" "-346 369.625 -615.375" } { "classname" "info_monster_start" "origin" "-346.125 460.125 -601.75" } { "classname" "info_monster_start" "origin" "-346.25 539.25 -589.875" } { "classname" "info_monster_start" "origin" "-346.25 613.875 -578.75" } { "classname" "info_monster_start" "origin" "-346.375 667 -570.75" } { "classname" "info_monster_start" "origin" "-324.5 777.375 -568" } { "classname" "info_monster_start" "origin" "-199.5 803.5 -576.25" } { "classname" "info_monster_start" "origin" "-152.75 803.875 -583.25" } { "classname" "info_monster_start" "origin" "-76.75 804.375 -594.625" } { "classname" "info_monster_start" "origin" "-25.75 804.75 -602.25" } { "classname" "info_monster_start" "origin" "38.375 805.875 -611.875" } { "classname" "info_monster_start" "origin" "119.125 806.375 -624" } { "classname" "info_monster_start" "origin" "204.375 806.875 -636.75" } { "classname" "info_monster_start" "origin" "291.875 807.5 -647.875" } { "classname" "info_monster_start" "origin" "374.5 808 -643.125" } { "classname" "info_monster_start" "origin" "465.875 808.625 -628.625" } { "classname" "info_monster_start" "origin" "546.625 809.125 -615.875" } { "classname" "info_monster_start" "origin" "627.625 809.75 -603.125" } { "classname" "info_monster_start" "origin" "714.625 810.25 -589.375" } { "classname" "info_monster_start" "origin" "798.75 810.875 -576.125" } { "classname" "info_monster_start" "origin" "950.875 783.125 -567.875" } { "classname" "info_monster_start" "origin" "975.75 681.75 -568.5" } { "classname" "info_monster_start" "origin" "975.625 627.375 -576.75" } { "classname" "info_monster_start" "origin" "975.375 539.875 -589.75" } { "classname" "info_monster_start" "origin" "975.25 447.625 -603.625" } { "classname" "info_monster_start" "origin" "975.125 358.375 -617" } { "classname" "info_monster_start" "origin" "974.875 269.625 -630.375" } { "classname" "info_monster_start" "origin" "974.75 179.25 -643.875" } { "classname" "info_monster_start" "origin" "974.625 113 -647.875" } { "classname" "info_monster_start" "origin" "974.375 24.625 -639.5" } { "classname" "info_monster_start" "origin" "974.25 -73.875 -624" } { "classname" "info_monster_start" "origin" "974 -173.25 -608.25" } { "classname" "info_monster_start" "origin" "973.875 -257.75 -594.875" } { "classname" "info_monster_start" "origin" "973.75 -342.75 -581.5" } { "classname" "info_monster_start" "origin" "973.625 -413 -570.375" } { "classname" "info_monster_start" "origin" "934.625 -513.875 -568" } { "classname" "info_monster_start" "origin" "829.875 -560 -572.75" } { "classname" "info_monster_start" "origin" "758.5 -559.25 -584.125" } { "classname" "info_monster_start" "origin" "660.25 -558.375 -599.625" } { "classname" "info_monster_start" "origin" "562.875 -557.5 -615" } { "classname" "info_monster_start" "origin" "475.5 -556.75 -628.75" } { "classname" "info_monster_start" "origin" "379.75 -555.875 -643.875" } { "classname" "info_monster_start" "origin" "297.25 -555.125 -647.875" } { "classname" "info_monster_start" "origin" "203.375 -554.25 -636.5" } { "classname" "info_monster_start" "origin" "109.375 -553.5 -622.375" } { "classname" "info_monster_start" "origin" "22.25 -552.625 -609.375" } { "classname" "info_monster_start" "origin" "-68 -551.875 -595.75" } { "classname" "info_monster_start" "origin" "-146.125 -551.125 -584" } { "classname" "info_monster_start" "origin" "-118.25 109.25 -679.875" } { "classname" "info_monster_start" "origin" "-117.5 208.375 -679.875" } { "classname" "info_monster_start" "origin" "-116.875 307.375 -679.875" } { "classname" "info_monster_start" "origin" "-116.25 399.25 -679.875" } { "classname" "info_monster_start" "origin" "-115.75 484.875 -679.875" } { "classname" "info_monster_start" "origin" "-115.125 589 -683.875" } { "classname" "info_monster_start" "origin" "-36.5 588.5 -679.875" } { "classname" "info_monster_start" "origin" "44.125 587.75 -679.875" } { "classname" "info_monster_start" "origin" "141.875 586.875 -679.875" } { "classname" "info_monster_start" "origin" "231.125 586.125 -679.875" } { "classname" "info_monster_start" "origin" "315.625 585.375 -679.875" } { "classname" "info_monster_start" "origin" "402.25 584.5 -679.875" } { "classname" "info_monster_start" "origin" "482.5 583.875 -679.875" } { "classname" "info_monster_start" "origin" "570 583 -679.875" } { "classname" "info_monster_start" "origin" "692.125 582 -679.875" } { "classname" "info_monster_start" "origin" "756.875 581.375 -683.875" } { "classname" "info_monster_start" "origin" "760.75 532.625 -679.875" } { "classname" "info_monster_start" "origin" "760.25 457.625 -679.875" } { "classname" "info_monster_start" "origin" "759.625 361.75 -679.875" } { "classname" "info_monster_start" "origin" "759 268.5 -679.875" } { "classname" "info_monster_start" "origin" "758.375 172.5 -679.875" } { "classname" "info_monster_start" "origin" "757.75 78.5 -679.875" } { "classname" "info_monster_start" "origin" "757 -16 -679.875" } { "classname" "info_monster_start" "origin" "756.375 -107.75 -679.875" } { "classname" "info_monster_start" "origin" "755.875 -192 -679.875" } { "classname" "info_monster_start" "origin" "755.5 -251.625 -679.875" } { "classname" "info_monster_start" "origin" "754.875 -335.125 -683.875" } { "classname" "info_monster_start" "origin" "654.25 -344.875 -679.875" } { "classname" "info_monster_start" "origin" "576.75 -343 -679.875" } { "classname" "info_monster_start" "origin" "479.25 -340.625 -679.875" } { "classname" "info_monster_start" "origin" "383.375 -338.375 -679.875" } { "classname" "info_monster_start" "origin" "288.5 -336.125 -679.875" } { "classname" "info_monster_start" "origin" "195.25 -333.875 -679.875" } { "classname" "info_monster_start" "origin" "104.125 -331.75 -679.875" } { "classname" "info_monster_start" "origin" "22.375 -329.75 -679.875" } { "classname" "info_monster_start" "origin" "-40.625 -328.25 -679.875" } { "classname" "info_monster_start" "origin" "-120.5 -247.25 -679.875" } { "classname" "info_monster_start" "origin" "-217 -550.5 -573.5" } { "classname" "info_monster_start" "origin" "-345.125 -412.375 -570.5" } { "classname" "info_monster_start" "origin" "-328.25 -522.75 -567.875" } { "classname" "info_monster_start" "origin" "-317.125 -417.75 -807.875" } { "classname" "info_monster_start" "origin" "-310.625 -125.5 -807.875" } { "classname" "info_monster_start" "origin" "-308.5 -28.875 -807.875" } { "classname" "info_monster_start" "origin" "-306.375 63.875 -807.875" } { "classname" "info_monster_start" "origin" "-304.125 166.625 -807.875" } { "classname" "info_monster_start" "origin" "-302 258.375 -807.875" } { "classname" "info_monster_start" "origin" "-300 350 -807.875" } { "classname" "info_monster_start" "origin" "-297.875 446.625 -807.875" } { "classname" "info_monster_start" "origin" "-295.875 536.25 -807.875" } { "classname" "info_monster_start" "origin" "-293.625 632.75 -807.875" } { "classname" "info_monster_start" "origin" "-291.875 712.625 -807.875" } { "classname" "info_monster_start" "origin" "-290.375 782.25 -807.875" } { "classname" "info_monster_start" "origin" "-214.5 775 -807.875" } { "classname" "info_monster_start" "origin" "-126.5 772.75 -807.875" } { "classname" "info_monster_start" "origin" "-27.875 770.375 -807.875" } { "classname" "info_monster_start" "origin" "58 768.125 -807.875" } { "classname" "info_monster_start" "origin" "156 765.75 -807.875" } { "classname" "info_monster_start" "origin" "252.25 763.25 -807.875" } { "classname" "info_monster_start" "origin" "341.5 761.125 -807.875" } { "classname" "info_monster_start" "origin" "435.625 758.75 -807.875" } { "classname" "info_monster_start" "origin" "532.625 756.25 -807.875" } { "classname" "info_monster_start" "origin" "613.625 776.75 -807.875" } { "classname" "info_monster_start" "origin" "687.25 778.125 -807.875" } { "classname" "info_monster_start" "origin" "775.125 776 -807.875" } { "classname" "info_monster_start" "origin" "848 774.125 -807.875" } { "classname" "info_monster_start" "origin" "933 772 -807.875" } { "classname" "info_monster_start" "origin" "946.125 688.875 -807.875" } { "classname" "info_monster_start" "origin" "944.125 599.375 -807.875" } { "classname" "info_monster_start" "origin" "942 505.25 -807.875" } { "classname" "info_monster_start" "origin" "940 414.875 -807.875" } { "classname" "info_monster_start" "origin" "937.75 315.625 -807.875" } { "classname" "info_monster_start" "origin" "935.625 219.5 -807.875" } { "classname" "info_monster_start" "origin" "933.5 122.25 -807.875" } { "classname" "info_monster_start" "origin" "931.25 23.75 -807.875" } { "classname" "info_monster_start" "origin" "929.125 -73.375 -807.875" } { "classname" "info_monster_start" "origin" "927 -165.5 -807.875" } { "classname" "info_monster_start" "origin" "924.875 -260.25 -807.875" } { "classname" "info_monster_start" "origin" "923 -344.125 -807.875" } { "classname" "info_monster_start" "origin" "921.125 -427.625 -807.875" } { "classname" "info_monster_start" "origin" "919.25 -515.375 -807.875" } { "classname" "info_monster_start" "origin" "848.5 -515.625 -807.875" } { "classname" "info_monster_start" "origin" "755.875 -515.5 -807.875" } { "classname" "info_monster_start" "origin" "656.75 -515.375 -807.875" } { "classname" "info_monster_start" "origin" "560.125 -515.25 -807.875" } { "classname" "info_monster_start" "origin" "472.125 -515.25 -807.875" } { "classname" "info_monster_start" "origin" "383.375 -515.125 -807.875" } { "classname" "info_monster_start" "origin" "285.375 -515 -807.875" } { "classname" "info_monster_start" "origin" "194 -514.875 -807.875" } { "classname" "info_monster_start" "origin" "107.75 -514.75 -807.875" } { "classname" "info_monster_start" "origin" "25 -514.625 -807.875" } { "classname" "info_monster_start" "origin" "-65.25 -514.5 -807.875" } { "classname" "info_monster_start" "origin" "-318.75 -486.875 -807.875" } { "classname" "info_monster_start" "origin" "-251.625 -514.25 -807.875" } { "classname" "info_monster_start" "origin" "-150.75 -514.375 -807.875" } { "classname" "info_monster_start" "origin" "-312.75 -218.625 -807.875" } { "classname" "info_monster_start" "origin" "-314.875 -317.75 -807.875" } { "classname" "info_monster_start" "origin" "-121.125 -336.75 -683.875" } { "classname" "info_monster_start" "origin" "-131.875 -292.25 -807.875" } { "classname" "info_monster_start" "origin" "-132.25 -225 -807.875" } { "classname" "info_monster_start" "origin" "-132.625 -124.625 -807.875" } { "classname" "info_monster_start" "origin" "-133.875 156.875 -807.875" } { "classname" "info_monster_start" "origin" "-134.25 243.875 -807.875" } { "classname" "info_monster_start" "origin" "-134.75 331.625 -807.875" } { "classname" "info_monster_start" "origin" "-135.125 420.125 -807.875" } { "classname" "info_monster_start" "origin" "-135.5 515 -807.875" } { "classname" "info_monster_start" "origin" "-101.25 593 -807.875" } { "classname" "info_monster_start" "origin" "-58 606.375 -807.875" } { "classname" "info_monster_start" "origin" "20.75 604.5 -807.875" } { "classname" "info_monster_start" "origin" "123.25 602.125 -807.875" } { "classname" "info_monster_start" "origin" "225.5 599.75 -807.875" } { "classname" "info_monster_start" "origin" "317 597.625 -807.875" } { "classname" "info_monster_start" "origin" "401.75 595.625 -807.875" } { "classname" "info_monster_start" "origin" "493.625 593.5 -807.875" } { "classname" "info_monster_start" "origin" "574.75 591.625 -807.875" } { "classname" "info_monster_start" "origin" "668.75 589.375 -807.875" } { "classname" "info_monster_start" "origin" "746.625 587.625 -807.875" } { "classname" "info_monster_start" "origin" "745.875 506.625 -807.875" } { "classname" "info_monster_start" "origin" "745.25 427.125 -807.875" } { "classname" "info_monster_start" "origin" "744.375 324 -807.875" } { "classname" "info_monster_start" "origin" "743.625 235.75 -807.875" } { "classname" "info_monster_start" "origin" "742.75 147.125 -807.875" } { "classname" "info_monster_start" "origin" "742 58 -807.875" } { "classname" "info_monster_start" "origin" "741.25 -32.25 -807.875" } { "classname" "info_monster_start" "origin" "740.5 -123.25 -807.875" } { "classname" "info_monster_start" "origin" "739.75 -213.125 -807.875" } { "classname" "info_monster_start" "origin" "738.75 -314.75 -807.875" } { "classname" "info_monster_start" "origin" "676.375 -338.5 -807.875" } { "classname" "info_monster_start" "origin" "609.25 -337.875 -807.875" } { "classname" "info_monster_start" "origin" "511.125 -337.125 -807.875" } { "classname" "info_monster_start" "origin" "420.75 -336.375 -807.875" } { "classname" "info_monster_start" "origin" "334.375 -335.625 -807.875" } { "classname" "info_monster_start" "origin" "241.25 -335 -807.875" } { "classname" "info_monster_start" "origin" "153.125 -334.25 -807.875" } { "classname" "info_monster_start" "origin" "62.625 -333.625 -807.875" } { "classname" "info_monster_start" "origin" "-31.375 -332.875 -807.875" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/genocide.ent000066400000000000000000000360441475442401000254340ustar00rootroot00000000000000{ "classname" "worldspawn" "message" "XL Genocide Crush" "sounds" "3" } { "classname" "light" "origin" "-64 64 -256" } { "classname" "light" "origin" "-64 -256 -256" } { "classname" "light" "origin" "-464 -256 64" } { "classname" "light" "origin" "-464 -96 -224" } { "classname" "light" "origin" "-560 -512 -80" } { "classname" "light" "origin" "224 -96 -128" } { "classname" "info_player_start" "origin" "-192 -96 -192" } { "classname" "light" "origin" "32 -96 -64" } { "classname" "light" "origin" "-176 -512 -192" } { "classname" "light" "origin" "-192 192 -80" } { "classname" "light" "origin" "128 -928 -64" } { "classname" "light" "origin" "336 -928 -64" } { "classname" "light" "origin" "544 -768 -64" } { "classname" "light" "origin" "544 -544 -64" } { "classname" "light" "origin" "112 -528 -160" } { "classname" "trigger_push" "angle" "-1" "speed" "80" "style" "32" "delay" "2" "model" "*1" } { "classname" "light" "origin" "96 784 -256" } { "classname" "light" "origin" "-64 976 -368" } { "classname" "light" "origin" "256 976 -368" } { "classname" "light" "origin" "-64 608 -288" } { "classname" "light" "origin" "-256 416 -80" } { "classname" "light" "origin" "176 608 -224" } { "classname" "light" "origin" "112 336 -112" } { "classname" "light" "origin" "-64 1136 -128" } { "classname" "light" "origin" "-320 864 -128" } { "classname" "light" "origin" "-272 1104 -320" } { "classname" "light" "origin" "-96 1136 -320" } { "classname" "light" "origin" "-320 816 -336" } { "classname" "light" "origin" "-1152 -256 -272" } { "classname" "light" "origin" "-1104 208 -288" } { "classname" "light" "origin" "-880 192 -288" } { "classname" "light" "origin" "-800 416 -80" } { "classname" "light" "origin" "-544 432 -96" } { "classname" "light" "origin" "-768 -128 -80" } { "classname" "light" "origin" "-880 -176 -240" } { "classname" "light" "origin" "-912 -480 -64" } { "classname" "light" "origin" "-1168 -512 -80" } { "classname" "trigger_push" "angle" "-1" "speed" "80" "style" "32" "delay" "2" "model" "*2" } { "classname" "light" "origin" "-1408 272 -128" } { "classname" "light" "origin" "-1216 0 -144" } { "classname" "light" "origin" "-1056 384 -128" } { "classname" "light" "origin" "-1488 -80 -320" } { "classname" "light" "origin" "-1488 -304 -320" } { "classname" "light" "origin" "-1376 -224 -64" } { "classname" "light" "origin" "-1408 -512 -64" } { "classname" "item_armorInv" "origin" "96 864 -352" } { "classname" "weapon_rocketlauncher" "origin" "64 -96 -176" } { "classname" "item_artifact_invisibility" "origin" "448 -656 -160" } { "classname" "weapon_supernailgun" "origin" "-1008 128 -304" } { "classname" "weapon_grenadelauncher" "origin" "-1440 -432 -112" } { "classname" "weapon_lightning" "origin" "48 1152 -368" } { "classname" "weapon_rocketlauncher" "origin" "96 1152 -160" } { "classname" "item_health" "spawnflags" "2" "origin" "-1360 176 -240" } { "classname" "item_rockets" "origin" "-872 536 -160" } { "classname" "item_rockets" "origin" "-824 536 -160" } { "classname" "item_health" "origin" "-784 528 -192" } { "classname" "item_shells" "origin" "-736 528 -160" } { "classname" "weapon_supershotgun" "origin" "240 -656 -240" } { "classname" "item_shells" "origin" "-16 -880 -176" } { "classname" "item_shells" "origin" "-16 -848 -176" } { "classname" "item_cells" "origin" "336 -464 -176" } { "classname" "item_shells" "origin" "384 -464 -176" } { "classname" "item_rockets" "origin" "440 -456 -176" } { "classname" "item_rockets" "origin" "248 72 -176" } { "classname" "item_rockets" "origin" "248 24 -176" } { "classname" "item_health" "origin" "240 -240 -192" } { "classname" "item_health" "origin" "240 -304 -192" } { "classname" "item_spikes" "origin" "-336 736 -176" } { "classname" "item_spikes" "origin" "-336 928 -176" } { "classname" "item_artifact_super_damage" "origin" "256 832 0" } { "classname" "item_spikes" "origin" "-1104 -368 -304" } { "classname" "item_spikes" "origin" "-1056 -368 -304" } { "classname" "item_rockets" "origin" "-24 504 -368" } { "classname" "item_rockets" "origin" "-72 504 -368" } { "classname" "item_health" "origin" "-752 -144 -128" } { "classname" "item_health" "origin" "-752 -192 -128" } { "classname" "info_player_deathmatch" "angle" "317" "origin" "-352 848 -352" } { "classname" "item_health" "origin" "240 560 -384" } { "classname" "item_cells" "origin" "-16 1136 -368" } { "classname" "item_cells" "origin" "80 1136 -368" } { "classname" "item_armor2" "origin" "-368 -384 -112" } { "classname" "info_player_deathmatch" "angle" "271" "origin" "-768 0 -288" } { "classname" "item_cells" "origin" "-1376 -368 -304" } { "classname" "item_cells" "origin" "-1376 -320 -304" } { "classname" "info_player_deathmatch" "angle" "43" "origin" "-1488 -560 -96" } { "classname" "item_spikes" "origin" "-544 -304 -304" } { "classname" "item_spikes" "origin" "-496 -304 -304" } { "classname" "item_rockets" "origin" "-328 840 -176" } { "classname" "info_player_deathmatch" "angle" "88" "origin" "-160 -592 -224" } { "classname" "item_cells" "origin" "-352 192 -176" } { "classname" "item_cells" "origin" "-304 192 -176" } { "classname" "info_player_deathmatch" "angle" "89" "origin" "240 -832 -160" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "96 320 -160" } { "classname" "info_player_deathmatch" "angle" "339" "origin" "-592 32 -288" } { "classname" "info_player_deathmatch" "angle" "323" "origin" "-1456 384 -224" } { "classname" "trigger_push" "angle" "271" "speed" "15" "style" "32" "delay" "2" "model" "*3" } { "classname" "trigger_push" "angle" "273" "speed" "15" "style" "32" "delay" "2" "model" "*4" } { "classname" "info_monster_start" "origin" "110.75 813.125 -359.875" } { "classname" "info_monster_start" "origin" "65.375 664.5 -359.875" } { "classname" "info_monster_start" "origin" "149.625 661 -359.875" } { "classname" "info_monster_start" "origin" "233.875 657.5 -359.875" } { "classname" "info_monster_start" "origin" "208.5 536.125 -359.875" } { "classname" "info_monster_start" "origin" "-57.75 669.625 -359.875" } { "classname" "info_monster_start" "origin" "-66.25 556.25 -359.875" } { "classname" "info_monster_start" "origin" "-164 560.25 -359.875" } { "classname" "info_monster_start" "origin" "-175.625 720.375 -359.875" } { "classname" "info_monster_start" "origin" "-325.75 709.125 -359.875" } { "classname" "info_monster_start" "origin" "-327.25 853.25 -359.875" } { "classname" "info_monster_start" "origin" "-328.25 959.5 -359.875" } { "classname" "info_monster_start" "origin" "-329.25 1054.75 -359.875" } { "classname" "info_monster_start" "origin" "-292.875 1138.62 -359.875" } { "classname" "info_monster_start" "origin" "-204.625 1143.62 -359.875" } { "classname" "info_monster_start" "origin" "-97.5 1149.75 -359.875" } { "classname" "info_monster_start" "origin" "3.375 1155.38 -359.875" } { "classname" "info_monster_start" "origin" "105.125 1161.12 -359.875" } { "classname" "info_monster_start" "origin" "133.625 1160.88 -167.875" } { "classname" "info_monster_start" "origin" "200.75 1160.88 -167.875" } { "classname" "info_monster_start" "origin" "249 829.375 -7.875" } { "classname" "info_monster_start" "origin" "-83.625 829 -7.875" } { "classname" "info_monster_start" "origin" "-320.125 813.625 -167.875" } { "classname" "info_monster_start" "origin" "-320.25 903.875 -167.875" } { "classname" "info_monster_start" "origin" "220.75 345.875 -167.875" } { "classname" "info_monster_start" "origin" "231.875 305.5 -167.875" } { "classname" "info_monster_start" "origin" "227.625 202.125 -167.875" } { "classname" "info_monster_start" "origin" "233.75 75.75 -167.875" } { "classname" "info_monster_start" "origin" "-484.625 439.75 -167.875" } { "classname" "info_monster_start" "origin" "-647.625 437.75 -167.875" } { "classname" "info_monster_start" "origin" "-765.875 432.5 -167.875" } { "classname" "info_monster_start" "origin" "-765.875 342.5 -167.875" } { "classname" "info_monster_start" "origin" "-766 165.25 -167.875" } { "classname" "info_monster_start" "origin" "-766 -75.875 -103.875" } { "classname" "info_monster_start" "origin" "-779.75 -28.125 -295.875" } { "classname" "info_monster_start" "origin" "-876.625 -23.625 -295.875" } { "classname" "info_monster_start" "origin" "-1004 59.375 -295.875" } { "classname" "info_monster_start" "origin" "-984.75 -18.75 -295.875" } { "classname" "info_monster_start" "origin" "-1088.25 -14 -295.875" } { "classname" "info_monster_start" "origin" "-1331 -337 -295.875" } { "classname" "info_monster_start" "origin" "-1036.88 360.5 -167.875" } { "classname" "info_monster_start" "origin" "-1328.12 135.25 -231.875" } { "classname" "info_monster_start" "origin" "-1447.75 125.75 -231.875" } { "classname" "info_monster_start" "origin" "-1447.25 327.875 -231.875" } { "classname" "info_monster_start" "origin" "-1316.38 338.25 -231.875" } { "classname" "info_monster_start" "origin" "-1114.88 354.375 -167.875" } { "classname" "info_monster_start" "origin" "-952.125 367.25 -167.875" } { "classname" "info_monster_start" "origin" "-765.875 522.25 -167.875" } { "classname" "info_monster_start" "origin" "-765.875 257.375 -167.875" } { "classname" "info_monster_start" "origin" "-766 -174.125 -103.875" } { "classname" "info_monster_start" "origin" "-766 -279.375 -103.875" } { "classname" "info_monster_start" "origin" "-766.125 -363.875 -103.875" } { "classname" "info_monster_start" "origin" "-779.625 -506 -103.875" } { "classname" "info_monster_start" "origin" "-1189.25 -512.5 -103.875" } { "classname" "info_monster_start" "origin" "-1300.38 -501 -103.875" } { "classname" "info_monster_start" "origin" "-1380.12 -506 -103.875" } { "classname" "info_monster_start" "origin" "-1491.5 -487.625 -103.875" } { "classname" "info_monster_start" "origin" "-579.5 -493.375 -103.875" } { "classname" "info_monster_start" "origin" "-205.75 11.125 -231.875" } { "classname" "info_monster_start" "origin" "-208.375 103.875 -231.875" } { "classname" "info_monster_start" "origin" "-109.125 -530.375 -231.875" } { "classname" "info_monster_start" "origin" "-15.375 -536.875 -231.875" } { "classname" "info_monster_start" "origin" "74.5 -544 -231.875" } { "classname" "info_monster_start" "origin" "169.875 -622.5 -231.875" } { "classname" "info_monster_start" "origin" "252.75 -628.25 -231.875" } { "classname" "info_monster_start" "origin" "328.875 -633.375 -231.875" } { "classname" "info_monster_start" "origin" "453.125 -660.125 -167.875" } { "classname" "info_monster_start" "origin" "450.25 -721.25 -167.875" } { "classname" "info_monster_start" "origin" "273.75 -816.125 -167.875" } { "classname" "info_monster_start" "origin" "170.5 -809 -167.875" } { "classname" "info_monster_start" "origin" "68.125 -802 -167.875" } { "classname" "info_monster_start" "origin" "368.125 -822.625 -167.875" } { "classname" "info_monster_start" "origin" "445.625 -816.25 -167.875" } { "classname" "info_monster_start" "origin" "456.625 -586.375 -167.875" } { "classname" "info_monster_start" "origin" "421.25 -509.75 -167.875" } { "classname" "info_monster_start" "origin" "327 -505.25 -167.875" } { "classname" "info_monster_start" "origin" "237.125 -500.375 -167.875" } { "classname" "info_monster_start" "origin" "239.125 -450.875 -167.875" } { "classname" "info_monster_start" "origin" "211.75 -384.375 -167.875" } { "classname" "info_monster_start" "origin" "216.25 -290 -167.875" } { "classname" "info_monster_start" "origin" "220.625 -197 -167.875" } { "classname" "info_monster_start" "origin" "225.375 -98.875 -167.875" } { "classname" "info_monster_start" "origin" "229.75 -7 -167.875" } { "classname" "info_monster_start" "origin" "113 191.75 -167.875" } { "classname" "info_monster_start" "origin" "10.375 195.125 -167.875" } { "classname" "info_monster_start" "origin" "-91 198.375 -167.875" } { "classname" "info_monster_start" "origin" "-187 201.5 -167.875" } { "classname" "info_monster_start" "origin" "-280 204.625 -167.875" } { "classname" "info_monster_start" "origin" "127.375 353.875 -167.875" } { "classname" "info_monster_start" "origin" "41.875 361.125 -167.875" } { "classname" "info_monster_start" "origin" "-50 369 -167.875" } { "classname" "info_monster_start" "origin" "-142.875 376.875 -167.875" } { "classname" "info_monster_start" "origin" "-233.875 384.625 -167.875" } { "classname" "info_monster_start" "origin" "-280.375 1160.62 -167.875" } { "classname" "info_monster_start" "origin" "47.875 1160.75 -167.875" } { "classname" "info_monster_start" "origin" "-45 1160.75 -167.875" } { "classname" "info_monster_start" "origin" "-129.125 1160.75 -167.875" } { "classname" "info_monster_start" "origin" "-208.875 1160.75 -167.875" } { "classname" "info_monster_start" "origin" "-363.625 1160.62 -167.875" } { "classname" "info_monster_start" "origin" "-320.625 1080.62 -167.875" } { "classname" "info_monster_start" "origin" "-320.5 1002.25 -167.875" } { "classname" "info_monster_start" "origin" "-320 722.625 -167.875" } { "classname" "info_monster_start" "origin" "-319.875 632.75 -167.875" } { "classname" "info_monster_start" "origin" "-319.625 552.125 -167.875" } { "classname" "info_monster_start" "origin" "-319.5 469.25 -167.875" } { "classname" "info_monster_start" "origin" "-319.375 394.375 -167.875" } { "classname" "info_monster_start" "origin" "-365.625 207.375 -167.875" } { "classname" "info_monster_start" "origin" "-190.625 -524.75 -231.875" } { "classname" "info_monster_start" "origin" "-190 -430.5 -231.875" } { "classname" "info_monster_start" "origin" "-573.125 -388.125 -103.875" } { "classname" "info_monster_start" "origin" "-668.5 -499 -103.875" } { "classname" "info_monster_start" "origin" "-1075.75 -505.375 -103.875" } { "classname" "info_monster_start" "origin" "-969 -498.625 -103.875" } { "classname" "info_monster_start" "origin" "-884.5 -493.75 -103.875" } { "classname" "info_monster_start" "origin" "-931.125 -338.75 -295.875" } { "classname" "info_monster_start" "origin" "-1097.88 -321.75 -295.875" } { "classname" "info_monster_start" "origin" "-1339.5 -151.375 -295.875" } { "classname" "info_monster_start" "origin" "-1235.88 -154.5 -295.875" } { "classname" "info_monster_start" "origin" "-1122 -158 -295.875" } { "classname" "info_monster_start" "origin" "-1003.88 -161.5 -295.875" } { "classname" "info_monster_start" "origin" "-888.625 -165 -295.875" } { "classname" "info_monster_start" "origin" "-766 -168.75 -295.875" } { "classname" "info_monster_start" "origin" "-189.125 -332.125 -231.875" } { "classname" "info_monster_start" "origin" "-187.125 -111.25 -231.875" } { "classname" "info_monster_start" "origin" "-188.125 -220 -231.875" } { "classname" "info_monster_start" "origin" "-317 -372 -103.875" } { "classname" "info_monster_start" "origin" "-398.375 -377.125 -103.875" } { "classname" "info_monster_start" "origin" "-495.875 -383.25 -103.875" } { "classname" "info_monster_start" "origin" "-660.5 -171.875 -295.875" } { "classname" "info_monster_start" "origin" "-544 -285.625 -295.875" } { "classname" "info_monster_start" "origin" "-542.5 -183.875 -295.875" } { "classname" "info_monster_start" "origin" "-538.5 73.875 -295.875" } { "classname" "info_monster_start" "origin" "-540.25 -42.875 -295.875" } { "classname" "info_monster_start" "origin" "-383.75 -27.75 -295.875" } { "classname" "info_monster_start" "origin" "-385.5 -139.625 -295.875" } { "classname" "info_monster_start" "origin" "-387.625 -279.5 -295.875" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/hohoho.ent000066400000000000000000000347141475442401000251450ustar00rootroot00000000000000{ "classname" "worldspawn" "message" "Merry Fraggin' X-Mas" } { "classname" "info_player_start" "origin" "-256 512 192" } { "classname" "light" "light" "150" "origin" "272 656 64" } { "classname" "light" "light" "150" "origin" "272 400 64" } { "classname" "light" "light" "150" "origin" "400 528 64" } { "classname" "light" "light" "150" "origin" "144 528 64" } { "classname" "light" "light" "700" "origin" "272 528 656" } { "classname" "item_artifact_invulnerability" "origin" "272 528 672" } { "classname" "light" "light" "300" "style" "0" "wait" "0.1" "origin" "608 0 224" } { "classname" "light_globe" "light" "600" "wait" "0.9" "origin" "344 -440 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "384 -440 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "304 -440 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "344 -480 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "344 -400 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "372 -468 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "316 -412 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "316 -468 336" } { "classname" "light" "light" "200" "wait" "0.5" "origin" "372 -412 336" } { "classname" "light" "light" "120" "style" "0" "wait" "0.05" "origin" "624 48 256" } { "classname" "info_teleport_destination" "angle" "225" "targetname" "treetop" "origin" "320 576 704" } { "classname" "trigger_push" "angle" "225" "style" "32" "delay" "2" "model" "*1" } { "classname" "item_artifact_super_damage" "origin" "-448 -80 352" } { "classname" "light_flame_large_yellow" "light" "400" "wait" "4" "style" "7" "origin" "592 32 240" } { "classname" "light_flame_large_yellow" "light" "400" "wait" "4" "style" "7" "origin" "560 66 222" } { "classname" "light_flame_large_yellow" "light" "400" "wait" "4" "style" "7" "origin" "552 16 152" } { "classname" "light_flame_large_yellow" "light" "400" "wait" "4" "style" "7" "origin" "544 -30 206" } { "classname" "light_flame_large_yellow" "light" "400" "wait" "4" "style" "7" "origin" "640 -48 200" } { "classname" "func_wall" "model" "*2" } { "classname" "trigger_hurt" "dmg" "4" "style" "32" "delay" "1" "model" "*3" } { "classname" "item_armorInv" "origin" "640 32 160" } { "classname" "info_teleport_destination" "angle" "90" "targetname" "jesus" "origin" "480 -128 688" } { "classname" "light" "light" "300" "wait" "0.7" "origin" "-152 416 48" } { "classname" "func_wall" "model" "*4" } { "classname" "trigger_teleport" "target" "treetop" "model" "*5" } { "classname" "light" "light" "300" "wait" "0.7" "origin" "-152 608 48" } { "classname" "trigger_teleport" "target" "jesus" "model" "*6" } { "classname" "func_wall" "model" "*7" } { "classname" "trigger_push" "angle" "-1" "speed" "120" "style" "32" "delay" "2" "model" "*8" } { "classname" "weapon_lightning" "origin" "432 180 464" } { "classname" "item_cells" "spawnflags" "1" "origin" "456 -16 464" } { "classname" "item_cells" "spawnflags" "1" "origin" "456 112 464" } { "classname" "item_cells" "spawnflags" "1" "origin" "456 -144 464" } { "classname" "weapon_grenadelauncher" "origin" "464 288 32" } { "classname" "light" "light" "500" "wait" "8" "origin" "464 288 24" } { "classname" "light" "light" "500" "wait" "8" "origin" "432 180 456" } { "classname" "light" "light" "500" "wait" "8" "origin" "-448 -80 344" } { "classname" "item_artifact_invisibility" "origin" "160 -736 352" } { "classname" "func_wall" "model" "*9" } { "classname" "weapon_supershotgun" "origin" "-356 -272 32" } { "classname" "light" "light" "500" "wait" "8" "origin" "-356 -272 24" } { "classname" "item_armor2" "origin" "-256 512 192" } { "classname" "weapon_rocketlauncher" "origin" "160 -656 160" } { "classname" "light" "light" "500" "wait" "8" "origin" "160 -656 152" } { "classname" "item_armor1" "origin" "-16 -104 16" } { "classname" "light" "light" "500" "wait" "8" "origin" "-16 -104 8" } { "classname" "weapon_supershotgun" "origin" "344 -440 32" } { "classname" "light" "light" "500" "wait" "8" "origin" "344 -440 24" } { "classname" "weapon_rocketlauncher" "origin" "-480 736 48" } { "classname" "light" "light" "500" "wait" "8" "origin" "-480 736 40" } { "classname" "item_rockets" "origin" "392 -504 240" } { "classname" "item_rockets" "origin" "320 576 32" } { "classname" "item_shells" "origin" "-372 96 16" } { "classname" "light" "light" "500" "wait" "8" "origin" "-356 112 24" } { "classname" "item_health" "spawnflags" "2" "origin" "-392 -808 16" } { "classname" "light" "light" "500" "wait" "8" "origin" "160 -704 24" } { "classname" "item_shells" "origin" "144 -720 16" } { "classname" "item_shells" "origin" "-192 464 32" } { "classname" "item_shells" "origin" "-192 528 32" } { "classname" "item_health" "origin" "192 448 32" } { "classname" "trigger_push" "angle" "225" "speed" "20" "style" "32" "delay" "2" "model" "*10" } { "classname" "item_shells" "origin" "192 576 32" } { "classname" "item_shells" "origin" "320 448 32" } { "classname" "info_player_deathmatch" "angle" "225" "origin" "480 736 32" } { "classname" "info_player_deathmatch" "angle" "135" "origin" "480 -736 32" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "-128 -800 32" } { "classname" "info_player_deathmatch" "angle" "213" "origin" "480 -288 32" } { "classname" "info_player_deathmatch" "angle" "95" "origin" "480 -224 576" } { "classname" "info_player_deathmatch" "angle" "90" "origin" "64 -656 224" } { "classname" "info_player_deathmatch" "origin" "-384 144 224" } { "classname" "item_health" "origin" "20 -336 160" } { "classname" "item_health" "origin" "-20 -340 160" } { "classname" "item_health" "origin" "20 -336 160" } { "classname" "item_health" "origin" "-20 -340 160" } { "classname" "item_health" "origin" "20 -336 160" } { "classname" "item_health" "origin" "-20 -340 160" } { "classname" "item_health" "origin" "20 -336 160" } { "classname" "item_health" "origin" "-20 -340 160" } { "classname" "info_player_deathmatch" "origin" "-368 -224 160" } { "classname" "info_player_deathmatch" "angle" "180" "origin" "-160 512 208" } { "classname" "info_intermission" "mangle" "10 55 0" "origin" "-416 -672 512" } { "classname" "info_intermission" "mangle" "-15 145 0" "origin" "64 -64 64" } { "classname" "info_intermission" "mangle" "35 320 0" "origin" "-448 -224 736" } { "classname" "info_monster_start" "origin" "-447.625 -237.75 344" } { "classname" "info_monster_start" "origin" "-446.375 -154.625 344" } { "classname" "info_monster_start" "origin" "-445.25 -71.25 344" } { "classname" "info_monster_start" "origin" "-444.125 11.625 344" } { "classname" "info_monster_start" "origin" "-443 95.375 344" } { "classname" "info_monster_start" "origin" "-338.625 95.75 152" } { "classname" "info_monster_start" "origin" "-474.25 61 24" } { "classname" "info_monster_start" "origin" "-474.25 -38.875 24" } { "classname" "info_monster_start" "origin" "-474.125 -139.5 24" } { "classname" "info_monster_start" "origin" "23.75 115.5 24" } { "classname" "info_monster_start" "origin" "25.75 205.375 24" } { "classname" "info_monster_start" "origin" "28.125 302.375 24" } { "classname" "info_monster_start" "origin" "30.125 391.75 24" } { "classname" "info_monster_start" "origin" "32.25 484.625 24" } { "classname" "info_monster_start" "origin" "202.375 138.125 24" } { "classname" "info_monster_start" "origin" "205 21.5 24" } { "classname" "info_monster_start" "origin" "220.25 -78.75 24" } { "classname" "info_monster_start" "origin" "214.25 -171.875 24" } { "classname" "info_monster_start" "origin" "206 -265.625 24" } { "classname" "info_monster_start" "origin" "197.625 -360.75 24" } { "classname" "info_monster_start" "origin" "200.375 -472.75 24" } { "classname" "info_monster_start" "origin" "154.875 -606.375 152" } { "classname" "info_monster_start" "origin" "153.375 -679.875 152" } { "classname" "info_monster_start" "origin" "364.75 -563.75 24" } { "classname" "info_monster_start" "origin" "375 -653 24" } { "classname" "info_monster_start" "origin" "383.125 -723.375 24" } { "classname" "info_monster_start" "origin" "211.125 238.25 24" } { "classname" "info_monster_start" "origin" "219.875 337.25 24" } { "classname" "info_monster_start" "origin" "313.375 336.125 24" } { "classname" "info_monster_start" "origin" "320.5 417.75 24" } { "classname" "info_monster_start" "origin" "443.5 436.75 24" } { "classname" "info_monster_start" "origin" "445.25 507 24" } { "classname" "info_monster_start" "origin" "447 577.375 24" } { "classname" "info_monster_start" "origin" "443.125 692 24" } { "classname" "info_monster_start" "origin" "359.25 699.25 24" } { "classname" "info_monster_start" "origin" "262.125 707.625 24" } { "classname" "info_monster_start" "origin" "181.375 714.625 24" } { "classname" "info_monster_start" "origin" "38.5 748.875 24" } { "classname" "info_monster_start" "origin" "36.75 674.875 24" } { "classname" "info_monster_start" "origin" "34.375 575.875 24" } { "classname" "info_monster_start" "origin" "21.5 20.375 24" } { "classname" "info_monster_start" "origin" "19.25 -73.25 24" } { "classname" "info_monster_start" "origin" "17.25 -161.875 24" } { "classname" "info_monster_start" "origin" "15 -257.625 24" } { "classname" "info_monster_start" "origin" "12.75 -355.375 24" } { "classname" "info_monster_start" "origin" "10.375 -455.25 24" } { "classname" "info_monster_start" "origin" "8.375 -540.5 24" } { "classname" "info_monster_start" "origin" "6.25 -635 24" } { "classname" "info_monster_start" "origin" "4.375 -712.375 24" } { "classname" "info_monster_start" "origin" "-129.75 -765.25 24" } { "classname" "info_monster_start" "origin" "-365.25 -778.75 24" } { "classname" "info_monster_start" "origin" "-474.25 164.125 24" } { "classname" "info_monster_start" "origin" "-474.25 265 24" } { "classname" "info_monster_start" "origin" "-474.25 368 24" } { "classname" "info_monster_start" "origin" "-474.25 452.75 24" } { "classname" "info_monster_start" "origin" "-474.25 551.625 24" } { "classname" "info_monster_start" "origin" "-474.25 640.25 24" } { "classname" "info_monster_start" "origin" "-468.25 743.25 24" } { "classname" "info_monster_start" "origin" "-388.5 740.5 24" } { "classname" "info_monster_start" "origin" "-293.25 737.25 24" } { "classname" "info_monster_start" "origin" "-199.5 734 24" } { "classname" "info_monster_start" "origin" "-118.625 731.25 24" } { "classname" "info_monster_start" "origin" "-236.75 648.75 176" } { "classname" "info_monster_start" "origin" "-241.125 555.375 176" } { "classname" "info_monster_start" "origin" "-245.25 467.875 176" } { "classname" "info_monster_start" "origin" "-248.875 391.875 176" } { "classname" "info_monster_start" "origin" "-339.875 14 152" } { "classname" "info_monster_start" "origin" "-341 -60.375 152" } { "classname" "info_monster_start" "origin" "91.125 92 168" } { "classname" "info_monster_start" "origin" "91.875 20.625 168" } { "classname" "info_monster_start" "origin" "95.125 -262.25 168" } { "classname" "info_monster_start" "origin" "96.125 -345.5 168" } { "classname" "info_monster_start" "origin" "94.125 -166.375 168" } { "classname" "info_monster_start" "origin" "13.5 -132.125 168" } { "classname" "info_monster_start" "origin" "11.5 -180.125 168" } { "classname" "info_monster_start" "origin" "8.5 -250.625 168" } { "classname" "info_monster_start" "origin" "-134 663.875 176" } { "classname" "info_monster_start" "origin" "-133.625 602 176" } { "classname" "info_monster_start" "origin" "-133.125 514.875 176" } { "classname" "info_monster_start" "origin" "-132.5 411.375 176" } { "classname" "info_monster_start" "origin" "-132.125 351.5 176" } { "classname" "info_monster_start" "origin" "-71.875 39.75 168" } { "classname" "info_monster_start" "origin" "-71.125 134.875 168" } { "classname" "info_monster_start" "origin" "24.25 125.625 168" } { "classname" "info_monster_start" "origin" "90.375 149.125 168" } { "classname" "info_monster_start" "origin" "403.75 -102.25 152" } { "classname" "info_monster_start" "origin" "403.625 -3.625 152" } { "classname" "info_monster_start" "origin" "403.5 75.625 152" } { "classname" "info_monster_start" "origin" "403.375 151.875 152" } { "classname" "info_monster_start" "origin" "403.25 218.375 152" } { "classname" "info_monster_start" "origin" "272 528 664" } { "classname" "info_monster_start" "origin" "474.25 237.125 472" } { "classname" "info_monster_start" "origin" "474.75 172.375 472" } { "classname" "info_monster_start" "origin" "475.75 68.625 472" } { "classname" "info_monster_start" "origin" "476.5 -15.125 472" } { "classname" "info_monster_start" "origin" "476.875 -110.5 472" } { "classname" "info_monster_start" "origin" "476.875 -205.625 472" } { "classname" "info_monster_start" "origin" "345.875 -444.625 392" } { "classname" "info_monster_start" "origin" "289.375 -484.375 232" } { "classname" "info_monster_start" "origin" "386.125 -491.875 232" } { "classname" "info_monster_start" "origin" "402.5 -382.625 232" } { "classname" "info_monster_start" "origin" "294.375 -374.375 232" } { "classname" "info_monster_start" "origin" "21.25 53.875 168" } { "classname" "info_monster_start" "origin" "93 -71.25 168" } { "classname" "info_monster_start" "origin" "17.5 -36.5 168" } { "classname" "info_monster_start" "origin" "-74.875 -294.25 168" } { "classname" "info_monster_start" "origin" "-74.125 -218.125 168" } { "classname" "info_monster_start" "origin" "-75.5 -368.625 168" } { "classname" "info_monster_start" "origin" "-344 -259.875 152" } { "classname" "info_monster_start" "origin" "-343.125 -201.375 152" } { "classname" "info_monster_start" "origin" "-342 -127.25 152" } { "classname" "info_monster_start" "origin" "-73.375 -131.625 168" } { "classname" "info_monster_start" "origin" "-72.625 -47.375 168" } { "classname" "info_monster_start" "origin" "-195.125 -56.875 24" } { "classname" "info_monster_start" "origin" "-201 -153 24" } { "classname" "info_monster_start" "origin" "-277.875 -773.75 24" } { "classname" "info_monster_start" "origin" "-208.5 -769.75 24" } { "classname" "info_monster_start" "origin" "-195 -593 24" } { "classname" "info_monster_start" "origin" "-474.125 -242.5 24" } { "classname" "info_monster_start" "origin" "-219.875 -464.75 24" } { "classname" "info_monster_start" "origin" "-474.125 -440.5 24" } { "classname" "info_monster_start" "origin" "-474.125 -338.875 24" } { "classname" "info_monster_start" "origin" "-206.875 -251 24" } { "classname" "info_monster_start" "origin" "-213.75 -363.625 24" } { "classname" "info_monster_start" "origin" "-344.125 -363 24" } { "classname" "info_monster_start" "origin" "-359.625 -434 24" } { "classname" "info_monster_start" "origin" "-474.125 -545.125 24" } { "classname" "info_monster_start" "origin" "-384.75 -548.75 24" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/kenya.ent000066400000000000000000000414771475442401000247740ustar00rootroot00000000000000{ "classname" "worldspawn" "message" "Kenya map by Milton" "wad" "gfx/QuArK.wad" } { "classname" "light" "origin" "-16 208 648" "light" "2000" } { "classname" "info_player_start" "origin" "-8 224 288" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "1120 -728 8" "angle" "178" } { "classname" "weapon_rocketlauncher" "origin" "-112 600 896" } { "classname" "light" "origin" "-752 624 576" "light" "700" } { "classname" "light" "origin" "1032 -672 48" "light" "300" } { "classname" "light" "origin" "-128 576 976" "light" "600" } { "classname" "weapon_nailgun" "origin" "-1248 -544 -136" } { "classname" "weapon_grenadelauncher" "origin" "-652 1044 808" } { "classname" "item_rockets" "origin" "-744 1040 800" } { "classname" "item_shells" "origin" "-592 1040 808" } { "classname" "weapon_lightning" "origin" "-1184 864 16" } { "classname" "item_shells" "origin" "-1048 980 0" "spawnflags" "1" } { "classname" "weapon_supershotgun" "origin" "600 -552 0" } { "classname" "weapon_supernailgun" "origin" "976 840 16" } { "classname" "item_spikes" "origin" "804 896 0" } { "classname" "item_spikes" "origin" "972 692 0" } { "classname" "item_spikes" "origin" "840 768 0" } { "classname" "info_player_deathmatch" "origin" "-1224 596 0" "angle" "0" } { "classname" "info_player_deathmatch" "origin" "1144 1036 420" "angle" "269" } { "classname" "info_player_deathmatch" "origin" "176 -732 -12" "angle" "89" } { "classname" "info_player_deathmatch" "origin" "640 892 0" "angle" "0" } { "origin" "678 -360 -32" "angle" "145" "classname" "info_player_deathmatch" } { "origin" "952 270 -32" "angle" "180" "classname" "info_player_deathmatch" } { "classname" "trigger_multiple" "origin" "0 0 0" "angle" "360" "message" "Kenyan flag" "sounds" "2" "wait" "2" "model" "*1" } { "classname" "light" "origin" "412 -196 564" "light" "150" } { "classname" "item_armor2" "origin" "-1240 -680 -140" } { "classname" "info_intermission" "origin" "416 172 560" "mangle" "0 -91.47 0" } { "classname" "item_shells" "origin" "-272 592 0" } { "classname" "item_shells" "origin" "8 572 0" } { "classname" "item_artifact_super_damage" "origin" "672 256 -64" } { "classname" "info_player_deathmatch" "origin" "-1256 -352 -120" "angle" "269" } { "classname" "item_artifact_invisibility" "origin" "848 -536 200" } { "classname" "item_health" "origin" "-128 768 -8" } { "classname" "item_health" "origin" "-128 432 24" } { "classname" "item_health" "origin" "312 -256 0" "spawnflags" "1" } { "classname" "item_health" "origin" "312 -72 0" "spawnflags" "1" } { "classname" "item_health" "origin" "432 -176 0" "spawnflags" "1" } { "classname" "item_health" "origin" "200 -176 0" "spawnflags" "1" } { "classname" "light" "origin" "1440 712 152" "light" "300" } { "classname" "light" "origin" "1160 744 56" "light" "300" } { "classname" "light" "origin" "952 736 112" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "1264 368 88" } { "classname" "light" "origin" "1264 368 88" "light" "300" } { "classname" "light" "origin" "1304 400 16" "light" "200" } { "classname" "light" "origin" "1600 392 16" "light" "200" } { "classname" "light_torch_small_walltorch" "origin" "1648 360 88" } { "classname" "light" "origin" "1648 360 88" "light" "300" } { "classname" "item_health" "origin" "1456 392 -16" "spawnflags" "2" } { "classname" "info_monster_start" "origin" "77.375 452.25 -31.875" } { "classname" "info_monster_start" "origin" "53.375 303.5 -31.875" } { "classname" "info_monster_start" "origin" "156.375 293.75 -31.875" } { "classname" "info_monster_start" "origin" "258.5 284.125 -31.875" } { "classname" "info_monster_start" "origin" "328.75 447.125 -31.875" } { "classname" "info_monster_start" "origin" "388.25 271.875 -31.875" } { "classname" "info_monster_start" "origin" "339 653.75 -31.875" } { "classname" "info_monster_start" "origin" "465.25 652.375 -31.875" } { "classname" "info_monster_start" "origin" "544.625 651.5 -31.875" } { "classname" "info_monster_start" "origin" "108 656.125 -31.875" } { "classname" "info_monster_start" "origin" "219.5 655 -31.875" } { "classname" "info_monster_start" "origin" "692.875 243.125 -87.875" } { "classname" "info_monster_start" "origin" "935 495.875 -31.875" } { "classname" "info_monster_start" "origin" "941.125 607.125 -31.875" } { "classname" "info_monster_start" "origin" "946.5 705.75 -31.875" } { "classname" "info_monster_start" "origin" "1147 676.5 -31.875" } { "classname" "info_monster_start" "origin" "1145.88 778 -31.875" } { "classname" "info_monster_start" "origin" "1286.75 713.375 -31.875" } { "classname" "info_monster_start" "origin" "1284.62 811.875 -31.875" } { "classname" "info_monster_start" "origin" "929.375 391.75 -31.875" } { "classname" "info_monster_start" "origin" "923.25 279.625 -31.875" } { "classname" "info_monster_start" "origin" "917.5 174 -31.875" } { "classname" "info_monster_start" "origin" "910.375 42.5 -31.875" } { "classname" "info_monster_start" "origin" "902.5 -101.125 -31.875" } { "classname" "info_monster_start" "origin" "1156.38 -219.375 74.375" } { "classname" "info_monster_start" "origin" "897.625 -190.375 -31.875" } { "classname" "info_monster_start" "origin" "892.125 -291.875 -31.875" } { "classname" "info_monster_start" "origin" "698.625 -308.375 -31.875" } { "classname" "info_monster_start" "origin" "593.25 -305.375 -31.875" } { "classname" "info_monster_start" "origin" "495.75 -302.625 -31.875" } { "classname" "info_monster_start" "origin" "386.375 -299.5 -31.875" } { "classname" "info_monster_start" "origin" "504 -11.375 -31.875" } { "classname" "info_monster_start" "origin" "644.375 -12.125 -31.875" } { "classname" "info_monster_start" "origin" "720.5 -12.5 -31.875" } { "classname" "info_monster_start" "origin" "1155.38 -114.75 101.875" } { "classname" "info_monster_start" "origin" "1294 373.375 -31.875" } { "classname" "info_monster_start" "origin" "1292.25 455.25 -31.875" } { "classname" "info_monster_start" "origin" "1445.38 398.5 -31.875" } { "classname" "info_monster_start" "origin" "1596.38 393.625 -31.875" } { "classname" "info_monster_start" "origin" "1600.5 471.875 -31.875" } { "classname" "info_monster_start" "origin" "1605 557.375 -31.875" } { "classname" "info_monster_start" "origin" "1610 650.375 -31.875" } { "classname" "info_monster_start" "origin" "1614.62 739.375 -31.875" } { "classname" "info_monster_start" "origin" "1619.62 833.625 -31.875" } { "classname" "info_monster_start" "origin" "1623.38 903.875 -31.875" } { "classname" "info_monster_start" "origin" "1446 466.25 -31.875" } { "classname" "info_monster_start" "origin" "1446.75 554 -31.875" } { "classname" "info_monster_start" "origin" "1447.38 629.125 -31.875" } { "classname" "info_monster_start" "origin" "1448.25 718.25 -31.875" } { "classname" "info_monster_start" "origin" "1448.75 786 -31.875" } { "classname" "info_monster_start" "origin" "1449.62 884.125 -31.875" } { "classname" "info_monster_start" "origin" "1282.88 893.5 -31.875" } { "classname" "info_monster_start" "origin" "1289 611.875 -31.875" } { "classname" "info_monster_start" "origin" "1290.88 524.125 -31.875" } { "classname" "info_monster_start" "origin" "837.125 -532.875 160" } { "classname" "info_monster_start" "origin" "580.5 -741.125 -31.875" } { "classname" "info_monster_start" "origin" "479.875 -738.125 -31.875" } { "classname" "info_monster_start" "origin" "389.125 -735.5 -31.875" } { "classname" "info_monster_start" "origin" "290.5 -732.5 -31.875" } { "classname" "info_monster_start" "origin" "184.5 -729.375 -31.875" } { "classname" "info_monster_start" "origin" "91.375 -726.5 -31.875" } { "classname" "info_monster_start" "origin" "-6.75 -723.625 -31.875" } { "classname" "info_monster_start" "origin" "-116.125 -720.375 -31.875" } { "classname" "info_monster_start" "origin" "-204.5 -717.625 -31.875" } { "classname" "info_monster_start" "origin" "879.375 -750.125 -31.875" } { "classname" "info_monster_start" "origin" "971.375 -752.875 -31.875" } { "classname" "info_monster_start" "origin" "1067.88 -755.75 -31.875" } { "classname" "info_monster_start" "origin" "1134.38 -757.75 -31.875" } { "classname" "info_monster_start" "origin" "1160.75 -657.125 -31.875" } { "classname" "info_monster_start" "origin" "1154.25 -0.25 132" } { "classname" "info_monster_start" "origin" "1153.12 108 160.375" } { "classname" "info_monster_start" "origin" "1152.12 213.375 188.125" } { "classname" "info_monster_start" "origin" "1150.88 334.125 219.875" } { "classname" "info_monster_start" "origin" "1149.88 444.125 248.875" } { "classname" "info_monster_start" "origin" "1148.75 549.75 276.625" } { "classname" "info_monster_start" "origin" "1147.62 659 305.25" } { "classname" "info_monster_start" "origin" "1143.88 1042 384" } { "classname" "info_monster_start" "origin" "754 1044.38 514.25" } { "classname" "info_monster_start" "origin" "-93.625 1043.38 837.5" } { "classname" "info_monster_start" "origin" "-733.375 1060.62 793.25" } { "classname" "info_monster_start" "origin" "-646.125 1060 793" } { "classname" "info_monster_start" "origin" "-577 1059.5 792.75" } { "classname" "info_monster_start" "origin" "-295.375 1043.12 896" } { "classname" "info_monster_start" "origin" "-182.875 1043.25 871.5" } { "classname" "info_monster_start" "origin" "-209.75 825.375 880" } { "classname" "info_monster_start" "origin" "-209.625 760.375 880" } { "classname" "info_monster_start" "origin" "-209.375 665.5 880" } { "classname" "info_monster_start" "origin" "-209 581.125 880" } { "classname" "info_monster_start" "origin" "-208.75 498.75 880" } { "classname" "info_monster_start" "origin" "-37.875 819 880" } { "classname" "info_monster_start" "origin" "-37.625 731.125 880" } { "classname" "info_monster_start" "origin" "26.25 1043.5 791.75" } { "classname" "info_monster_start" "origin" "127.25 1043.62 753.25" } { "classname" "info_monster_start" "origin" "231.25 1043.75 713.625" } { "classname" "info_monster_start" "origin" "338.5 1043.88 672.75" } { "classname" "info_monster_start" "origin" "438 1044 634.75" } { "classname" "info_monster_start" "origin" "548.875 1044.12 592.5" } { "classname" "info_monster_start" "origin" "648.375 1044.25 554.625" } { "classname" "info_monster_start" "origin" "774.625 -747 -31.875" } { "classname" "info_monster_start" "origin" "674.375 -744 -31.875" } { "classname" "info_monster_start" "origin" "582.25 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "487.125 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "383.625 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "277.375 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "164.625 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "51.625 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "-70 -453.875 351.375" } { "classname" "info_monster_start" "origin" "631.375 635.625 351.375" } { "classname" "info_monster_start" "origin" "859.75 1044.5 474" } { "classname" "info_monster_start" "origin" "972.25 1044.62 431.125" } { "classname" "info_monster_start" "origin" "1070.88 1044.75 393.5" } { "classname" "info_monster_start" "origin" "1144.75 955.625 383.25" } { "classname" "info_monster_start" "origin" "1145.62 859.25 358" } { "classname" "info_monster_start" "origin" "1146.62 765.125 333.25" } { "classname" "info_monster_start" "origin" "1157.5 -328.375 45.625" } { "classname" "info_monster_start" "origin" "671.25 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "-37.375 646.625 880" } { "classname" "info_monster_start" "origin" "-37.125 572 880" } { "classname" "info_monster_start" "origin" "-36.75 481.375 880" } { "classname" "info_monster_start" "origin" "-36.625 414.125 880" } { "classname" "info_monster_start" "origin" "-208.5 415.25 880" } { "classname" "info_monster_start" "origin" "-894.5 272.375 351.375" } { "classname" "info_monster_start" "origin" "-1265.88 44.5 -31.875" } { "classname" "info_monster_start" "origin" "-1256.25 136.875 -31.875" } { "classname" "info_monster_start" "origin" "-1245.88 237.875 -31.875" } { "classname" "info_monster_start" "origin" "-1184.75 828.25 -31.875" } { "classname" "info_monster_start" "origin" "-1193.12 938.5 -31.875" } { "classname" "info_monster_start" "origin" "-1101.75 937 -31.875" } { "classname" "info_monster_start" "origin" "-959.625 934.875 -31.875" } { "classname" "info_monster_start" "origin" "-821.75 932.625 -31.875" } { "classname" "info_monster_start" "origin" "-698 930.75 -31.875" } { "classname" "info_monster_start" "origin" "-582.625 928.875 -31.875" } { "classname" "info_monster_start" "origin" "-463.375 927 -31.875" } { "classname" "info_monster_start" "origin" "-337.125 925 -31.875" } { "classname" "info_monster_start" "origin" "-207.375 923 -31.875" } { "classname" "info_monster_start" "origin" "-82.875 921 -31.875" } { "classname" "info_monster_start" "origin" "39.625 919.125 -31.875" } { "classname" "info_monster_start" "origin" "164 917.125 -31.875" } { "classname" "info_monster_start" "origin" "275.625 915.375 -31.875" } { "classname" "info_monster_start" "origin" "380.375 913.75 -31.875" } { "classname" "info_monster_start" "origin" "493.125 912 -31.875" } { "classname" "info_monster_start" "origin" "952.5 816.875 -31.875" } { "classname" "info_monster_start" "origin" "956.125 883.875 -31.875" } { "classname" "info_monster_start" "origin" "709.75 908.625 -31.875" } { "classname" "info_monster_start" "origin" "591.625 910.375 -31.875" } { "classname" "info_monster_start" "origin" "-1.875 657.25 -31.875" } { "classname" "info_monster_start" "origin" "-221.125 641.875 -31.875" } { "classname" "info_monster_start" "origin" "-329.25 643 -31.875" } { "classname" "info_monster_start" "origin" "-468.875 644.5 -24.25" } { "classname" "info_monster_start" "origin" "-610.375 646 -9.625" } { "classname" "info_monster_start" "origin" "-739.125 647.25 -9.875" } { "classname" "info_monster_start" "origin" "-845.75 648.375 -17.375" } { "classname" "info_monster_start" "origin" "-946.375 649.5 -25.5" } { "classname" "info_monster_start" "origin" "-1196.38 715.5 -31.875" } { "classname" "info_monster_start" "origin" "-1103.12 651.125 -31.875" } { "classname" "info_monster_start" "origin" "-1209 594 -31.875" } { "classname" "info_monster_start" "origin" "-1221.88 469.625 -31.875" } { "classname" "info_monster_start" "origin" "-1234.25 349.375 -31.875" } { "classname" "info_monster_start" "origin" "-1063.38 387.25 -28.375" } { "classname" "info_monster_start" "origin" "-991.5 380.375 -22.5" } { "classname" "info_monster_start" "origin" "-873.125 369.25 -18" } { "classname" "info_monster_start" "origin" "-750.375 357.625 -17.375" } { "classname" "info_monster_start" "origin" "-617.5 345.125 -16.75" } { "classname" "info_monster_start" "origin" "-493.875 333.375 -16.25" } { "classname" "info_monster_start" "origin" "-377 322.375 -27.375" } { "classname" "info_monster_start" "origin" "-284.375 314 -31.875" } { "classname" "info_monster_start" "origin" "-151.625 321.375 -31.875" } { "classname" "info_monster_start" "origin" "-56.875 313.75 -31.875" } { "classname" "info_monster_start" "origin" "373.75 -10.625 -31.875" } { "classname" "info_monster_start" "origin" "234 -9.875 -31.875" } { "classname" "info_monster_start" "origin" "117.75 -9.375 -31.875" } { "classname" "info_monster_start" "origin" "-0.75 -8.75 -31.875" } { "classname" "info_monster_start" "origin" "-101.75 -8.125 -31.875" } { "classname" "info_monster_start" "origin" "-210.5 -7.625 -31.875" } { "classname" "info_monster_start" "origin" "-54.625 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "-169.75 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "-444.75 -6.375 -31.875" } { "classname" "info_monster_start" "origin" "-306.5 -7.125 -31.875" } { "classname" "info_monster_start" "origin" "-249 -507.375 -31.875" } { "classname" "info_monster_start" "origin" "-352.25 -278.5 -31.875" } { "classname" "info_monster_start" "origin" "-268.625 -280.875 -31.875" } { "classname" "info_monster_start" "origin" "-152.125 -284.125 -31.875" } { "classname" "info_monster_start" "origin" "-36.625 -287.5 -31.875" } { "classname" "info_monster_start" "origin" "72.125 -290.625 -31.875" } { "classname" "info_monster_start" "origin" "185.625 -293.75 -31.875" } { "classname" "info_monster_start" "origin" "310 -297.375 -31.875" } { "classname" "info_monster_start" "origin" "821.5 -311.875 -31.875" } { "classname" "info_monster_start" "origin" "888.625 -354.375 -31.875" } { "classname" "info_monster_start" "origin" "1024.62 -658.875 -31.875" } { "classname" "info_monster_start" "origin" "1158.62 -443 15.5" } { "classname" "info_monster_start" "origin" "1159.88 -566.125 -16.75" } { "classname" "info_monster_start" "origin" "1028.25 -503.375 -31.875" } { "classname" "trigger_custom_teleport" "origin" "172 1034 736" "size" "50 50 50" "target" "lame_place" } { "classname" "trigger_custom_teleport" "origin" "1200 736 -32" "size" "100 100 100" "target" "lame_place" } { "classname" "info_teleport_destination" "targetname" "lame_place" "angle" "0" "origin" "314 -166 656" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/pillar.ent000066400000000000000000000407151475442401000251420ustar00rootroot00000000000000{ "message" "Entering Pillar - Go for that Rocket !!" "wad" "MYWAD.WAD" "classname" "worldspawn" } { "classname" "info_player_start" "origin" "368 -36 -185" } { "classname" "light_flame_large_yellow" "origin" "-121 97 -202" "light" "450" } { "classname" "light_flame_large_yellow" "origin" "130 96 -202" "light" "450" } { "classname" "light_flame_large_yellow" "origin" "130 -156 -202" "light" "450" } { "classname" "light_flame_large_yellow" "origin" "-121 -157 -202" "light" "450" } { "classname" "weapon_rocketlauncher" "origin" "0 -29 -122" } { "classname" "light_torch_small_walltorch" "origin" "-482 -94 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-477 -492 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-288 -548 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-35 -546 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "228 -551 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "484 -540 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "481 -284 1" "light" "390" } { "classname" "light_torch_small_walltorch" "origin" "480 87 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "482 491 1" "light" "400" } { "classname" "light_torch_small_walltorch" "origin" "160 549 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-96 546 1" "light" "370" } { "classname" "light_torch_small_walltorch" "origin" "-352 546 1" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-480 287 1" "light" "450" } { "classname" "light_torch_small_walltorch" "origin" "-547 161 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-545 420 87" "light" "400" } { "classname" "light_torch_small_walltorch" "origin" "-469 620 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-222 619 87" "light" "280" } { "classname" "light_torch_small_walltorch" "origin" "29 621 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "285 621 87" "light" "600" } { "classname" "light_torch_small_walltorch" "origin" "547 -32 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "547 -287 87" "light" "380" } { "classname" "light_torch_small_walltorch" "origin" "546 -559 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "227 -621 87" "light" "330" } { "classname" "light_torch_small_walltorch" "origin" "-34 -622 87" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-288 -622 87" "light" "356" } { "classname" "light_torch_small_walltorch" "origin" "-5 -291 -43" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-4 -291 196" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "245 0 196" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-250 1 196" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-6 297 196" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-7 298 -42" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-253 2 -42" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "245 0 -42" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-398 -549 -191" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "-374 546 -191" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "332 550 -191" "light" "300" } { "classname" "light_torch_small_walltorch" "origin" "339 -551 -191" "light" "300" } { "classname" "item_artifact_super_damage" "origin" "2 0 20" } { "classname" "light" "origin" "0 -1 43" "light" "220" } { "classname" "item_armorInv" "origin" "462 489 -99" } { "classname" "item_armorInv" "origin" "-451 -492 -99" } { "classname" "item_health" "origin" "-134 -93 -214" } { "classname" "item_health" "origin" "-102 -96 -214" } { "classname" "item_health" "origin" "-623 190 -119" } { "classname" "item_health" "origin" "418 521 -223" } { "classname" "item_health" "origin" "384 522 -223" } { "classname" "item_armor2" "origin" "71 42 -210" } { "classname" "item_armor2" "origin" "606 279 -115" } { "classname" "light_fluoro" "origin" "621 242 -50" "light" "400" } { "classname" "ambient_drone" "origin" "582 310 -112" } { "classname" "weapon_supershotgun" "origin" "617 23 -113" } { "classname" "weapon_grenadelauncher" "origin" "276 -476 -115" } { "classname" "item_rockets" "origin" "142 -92 -217" } { "classname" "item_rockets" "origin" "111 -93 -217" } { "classname" "weapon_nailgun" "origin" "-76 48 -209" } { "classname" "item_armor1" "origin" "415 758 -69" } { "classname" "light_fluorospark" "origin" "-591 -256 11" "light" "400" } { "classname" "item_shells" "origin" "-622 -191 -99" } { "classname" "item_shells" "origin" "-621 -220 -99" } { "classname" "item_spikes" "origin" "-165 -792 -104" } { "classname" "item_spikes" "origin" "422 -791 -104" } { "classname" "info_player_deathmatch" "origin" "-183 -217 15" } { "classname" "info_player_deathmatch" "origin" "-185 223 15" } { "classname" "info_player_deathmatch" "origin" "168 214 15" } { "classname" "info_player_deathmatch" "origin" "171 -216 15" } { "classname" "info_player_deathmatch" "origin" "412 -480 -217" } { "classname" "info_player_deathmatch" "origin" "412 -480 -80" } { "classname" "info_player_deathmatch" "origin" "593 -480 -80" } { "classname" "info_player_deathmatch" "origin" "365 475 -80" } { "classname" "info_player_deathmatch" "origin" "220 733 -100" } { "classname" "info_player_deathmatch" "origin" "-392 488 -100" } { "classname" "info_player_deathmatch" "origin" "-429 163 -218" } { "classname" "info_player_deathmatch" "origin" "-597 339 -98" } { "classname" "info_null" "targetname" "spot" } { "classname" "info_monster_start" "origin" "-178.375 -123.875 -219.875" } { "classname" "info_monster_start" "origin" "-169.375 -255.5 -219.875" } { "classname" "info_monster_start" "origin" "-108.625 -253.625 -219.875" } { "classname" "info_monster_start" "origin" "-182.875 30.875 -219.875" } { "classname" "info_monster_start" "origin" "-189.75 141.25 -219.875" } { "classname" "info_monster_start" "origin" "-185.875 233.875 -219.875" } { "classname" "info_monster_start" "origin" "-39.875 242.625 -219.875" } { "classname" "info_monster_start" "origin" "50.25 248 -219.875" } { "classname" "info_monster_start" "origin" "141 253.5 -219.875" } { "classname" "info_monster_start" "origin" "211.875 257.75 -219.875" } { "classname" "info_monster_start" "origin" "214.125 465.125 -227.875" } { "classname" "info_monster_start" "origin" "174.25 50.875 -219.875" } { "classname" "info_monster_start" "origin" "168.375 -94.625 -219.875" } { "classname" "info_monster_start" "origin" "195.125 -243.875 -219.875" } { "classname" "info_monster_start" "origin" "133.25 -245.875 -219.875" } { "classname" "info_monster_start" "origin" "52.625 -248.5 -219.875" } { "classname" "info_monster_start" "origin" "-39.375 -251.375 -219.875" } { "classname" "info_monster_start" "origin" "-147.5 -491.625 -227.875" } { "classname" "info_monster_start" "origin" "-184.25 -221.75 16" } { "classname" "info_monster_start" "origin" "-182.25 -148.375 16" } { "classname" "info_monster_start" "origin" "-254.625 -495.125 -112.875" } { "classname" "info_monster_start" "origin" "-333.25 -495.875 -112.875" } { "classname" "info_monster_start" "origin" "-413.75 -496.625 -112.875" } { "classname" "info_monster_start" "origin" "-452.25 -497 -112.875" } { "classname" "info_monster_start" "origin" "-591.625 -289.75 -124.875" } { "classname" "info_monster_start" "origin" "-592.75 -208 -124.875" } { "classname" "info_monster_start" "origin" "-593.625 -139.875 -124.875" } { "classname" "info_monster_start" "origin" "-594.5 -68 -124.875" } { "classname" "info_monster_start" "origin" "-595.375 3.625 -124.875" } { "classname" "info_monster_start" "origin" "-596.5 86.5 -124.875" } { "classname" "info_monster_start" "origin" "-603 593.125 -124.875" } { "classname" "info_monster_start" "origin" "-152.625 716.5 -125.875" } { "classname" "info_monster_start" "origin" "-75.5 716 -125.875" } { "classname" "info_monster_start" "origin" "-11 715.625 -125.875" } { "classname" "info_monster_start" "origin" "49.125 715.25 -125.875" } { "classname" "info_monster_start" "origin" "99.25 714.875 -125.875" } { "classname" "info_monster_start" "origin" "171.125 714.375 -125.875" } { "classname" "info_monster_start" "origin" "242.5 714 -125.875" } { "classname" "info_monster_start" "origin" "312.75 713.5 -125.875" } { "classname" "info_monster_start" "origin" "-523.875 718.875 -127.875" } { "classname" "info_monster_start" "origin" "-603.125 719.375 -124.875" } { "classname" "info_monster_start" "origin" "-603.75 651.625 -124.875" } { "classname" "info_monster_start" "origin" "362 -728.625 -125.875" } { "classname" "info_monster_start" "origin" "445 -728.875 -125.875" } { "classname" "info_monster_start" "origin" "506.125 -729.25 -126.25" } { "classname" "info_monster_start" "origin" "591.625 -729.5 -125.875" } { "classname" "info_monster_start" "origin" "591.125 -658 -125.875" } { "classname" "info_monster_start" "origin" "591.5 -575.75 -125.875" } { "classname" "info_monster_start" "origin" "591.75 -488.125 -125.875" } { "classname" "info_monster_start" "origin" "592.125 -394.375 -125.875" } { "classname" "info_monster_start" "origin" "592.5 -298.375 -125.875" } { "classname" "info_monster_start" "origin" "592.75 -229.125 -125.875" } { "classname" "info_monster_start" "origin" "593 -155.375 -125.875" } { "classname" "info_monster_start" "origin" "593.375 -71.25 -125.875" } { "classname" "info_monster_start" "origin" "593.625 9.375 -125.875" } { "classname" "info_monster_start" "origin" "386.875 713 -125.875" } { "classname" "info_monster_start" "origin" "436.25 712.75 -125.875" } { "classname" "info_monster_start" "origin" "390.25 487.875 -112.875" } { "classname" "info_monster_start" "origin" "308.375 488.875 -112.875" } { "classname" "info_monster_start" "origin" "249.375 489.5 -112.875" } { "classname" "info_monster_start" "origin" "-602 516.375 -124.875" } { "classname" "info_monster_start" "origin" "-482.625 718.625 -125.875" } { "classname" "info_monster_start" "origin" "-422.625 718.25 -125.875" } { "classname" "info_monster_start" "origin" "-364.5 717.875 -125.875" } { "classname" "info_monster_start" "origin" "-303.375 717.5 -125.875" } { "classname" "info_monster_start" "origin" "-237.875 717 -125.875" } { "classname" "info_monster_start" "origin" "-230.75 -726.125 -125.875" } { "classname" "info_monster_start" "origin" "-284.75 -725.875 -125.875" } { "classname" "info_monster_start" "origin" "-354.75 -725.625 -125.875" } { "classname" "info_monster_start" "origin" "-416.25 -725.25 -125.875" } { "classname" "info_monster_start" "origin" "-177.5 -726.25 -125.875" } { "classname" "info_monster_start" "origin" "-126.25 -726.5 -125.875" } { "classname" "info_monster_start" "origin" "-62.75 -726.75 -125.875" } { "classname" "info_monster_start" "origin" "1.625 -727.125 -125.875" } { "classname" "info_monster_start" "origin" "64.625 -727.375 -125.875" } { "classname" "info_monster_start" "origin" "131 -727.625 -125.875" } { "classname" "info_monster_start" "origin" "287.875 -728.25 -125.875" } { "classname" "info_monster_start" "origin" "206.5 -727.875 -125.875" } { "classname" "info_monster_start" "origin" "480.875 -498 -112.875" } { "classname" "info_monster_start" "origin" "419.625 -498.625 -112.875" } { "classname" "info_monster_start" "origin" "345.875 -499.25 -112.875" } { "classname" "info_monster_start" "origin" "287.5 -499.875 -112.875" } { "classname" "info_monster_start" "origin" "-179.875 -59.25 16" } { "classname" "info_monster_start" "origin" "-175.375 107.5 16" } { "classname" "info_monster_start" "origin" "55.625 209.625 16" } { "classname" "info_monster_start" "origin" "150.375 206.625 16" } { "classname" "info_monster_start" "origin" "174.625 153 16" } { "classname" "info_monster_start" "origin" "152.625 -225.625 16" } { "classname" "info_monster_start" "origin" "85.875 -210.5 16" } { "classname" "info_monster_start" "origin" "-115.25 -207.375 16" } { "classname" "info_monster_start" "origin" "-51.875 -208.375 16" } { "classname" "info_monster_start" "origin" "22.375 -209.5 16" } { "classname" "info_monster_start" "origin" "-3.875 -101.625 16" } { "classname" "info_monster_start" "origin" "-8.75 105.375 16" } { "classname" "info_monster_start" "origin" "83.75 12.25 16" } { "classname" "info_monster_start" "origin" "-6.125 -6.375 16" } { "classname" "info_monster_start" "origin" "-109.125 7.625 16" } { "classname" "info_monster_start" "origin" "-177.75 18.5 16" } { "classname" "info_monster_start" "origin" "-34 212.375 16" } { "classname" "info_monster_start" "origin" "-105.875 214.625 16" } { "classname" "info_monster_start" "origin" "-172.75 202.5 16" } { "classname" "info_monster_start" "origin" "-597.375 160.5 -124.875" } { "classname" "info_monster_start" "origin" "-598.625 251.375 -124.875" } { "classname" "info_monster_start" "origin" "-599.75 339.125 -124.875" } { "classname" "info_monster_start" "origin" "-600.875 431.375 -124.875" } { "classname" "info_monster_start" "origin" "-453.125 501 -112.875" } { "classname" "info_monster_start" "origin" "-369.875 500 -112.875" } { "classname" "info_monster_start" "origin" "-433.25 -51 -227.875" } { "classname" "info_monster_start" "origin" "-434.875 29 -227.875" } { "classname" "info_monster_start" "origin" "-435.75 110 -227.875" } { "classname" "info_monster_start" "origin" "-425.125 184 -227.875" } { "classname" "info_monster_start" "origin" "-395.375 276.625 -227.875" } { "classname" "info_monster_start" "origin" "-396.875 350.125 -227.875" } { "classname" "info_monster_start" "origin" "-398.625 430.625 -227.875" } { "classname" "info_monster_start" "origin" "-400 492.5 -227.875" } { "classname" "info_monster_start" "origin" "-311.625 499.375 -112.875" } { "classname" "info_monster_start" "origin" "-261.125 498.75 -112.875" } { "classname" "info_monster_start" "origin" "-172.625 495.25 -227.875" } { "classname" "info_monster_start" "origin" "-101 489.75 -227.875" } { "classname" "info_monster_start" "origin" "-13.75 482.875 -227.875" } { "classname" "info_monster_start" "origin" "66.625 476.625 -227.875" } { "classname" "info_monster_start" "origin" "150.875 470 -227.875" } { "classname" "info_monster_start" "origin" "314.875 454.75 -227.875" } { "classname" "info_monster_start" "origin" "441.75 487.25 -112.875" } { "classname" "info_monster_start" "origin" "451.125 444.125 -227.875" } { "classname" "info_monster_start" "origin" "180.75 -103.5 16" } { "classname" "info_monster_start" "origin" "177.625 -37 16" } { "classname" "info_monster_start" "origin" "177.375 73.375 16" } { "classname" "info_monster_start" "origin" "594.625 288.875 -125.875" } { "classname" "info_monster_start" "origin" "594.5 231.5 -125.875" } { "classname" "info_monster_start" "origin" "594.25 167.375 -125.875" } { "classname" "info_monster_start" "origin" "593.875 82.625 -125.875" } { "classname" "info_monster_start" "origin" "420.375 57.625 -227.875" } { "classname" "info_monster_start" "origin" "415.75 -11 -227.875" } { "classname" "info_monster_start" "origin" "409.25 -106.25 -227.875" } { "classname" "info_monster_start" "origin" "403.875 -187 -227.875" } { "classname" "info_monster_start" "origin" "398.375 -267.75 -227.875" } { "classname" "info_monster_start" "origin" "393 -347.875 -227.875" } { "classname" "info_monster_start" "origin" "388.375 -414.75 -227.875" } { "classname" "info_monster_start" "origin" "382.625 -501.25 -227.875" } { "classname" "info_monster_start" "origin" "233 -500.375 -112.875" } { "classname" "info_monster_start" "origin" "195.875 -491 -227.875" } { "classname" "info_monster_start" "origin" "137.25 -491.125 -227.875" } { "classname" "info_monster_start" "origin" "68.25 -491.25 -227.875" } { "classname" "info_monster_start" "origin" "-4.125 -491.375 -227.875" } { "classname" "info_monster_start" "origin" "-85.375 -491.5 -227.875" } { "classname" "info_monster_start" "origin" "-208.875 -491.75 -227.875" } { "classname" "info_monster_start" "origin" "-288.625 -464 -227.875" } { "classname" "info_monster_start" "origin" "-360.125 -463.75 -227.875" } { "classname" "info_monster_start" "origin" "-457.625 -463.875 -227.875" } { "classname" "trigger_custom_teleport" "origin" "445 709 -126" "size" "25 90 50" "target" "lame_place" } { "classname" "trigger_custom_teleport" "origin" "-445 -702 -126" "size" "25 90 50" "target" "lame_place" } { "classname" "info_teleport_destination" "targetname" "lame_place" "angle" "0" "origin" "-21 -28 -114" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/q1dm17.ent000066400000000000000000000512171475442401000246700ustar00rootroot00000000000000{ "classname" "worldspawn" "wad" "DM17_43.wad" "light" "150" "message" "The Longest Yard" "worldtype" "1" } { "classname" "trigger_teleport" "target" "redarmor" "model" "*1" } { "classname" "light" "origin" "-864 64 704" "light" "300" } { "classname" "light" "light" "550" "origin" "-704 256 848" } { "classname" "light" "origin" "-704 -128 848" "light" "550" } { "classname" "light" "origin" "416 64 1312" "light" "400" } { "classname" "light" "light" "400" "origin" "416 288 1312" } { "classname" "light" "origin" "416 -160 1312" "light" "400" } { "classname" "light" "origin" "192 288 1312" "light" "400" } { "classname" "light" "light" "400" "origin" "192 -160 1312" } { "classname" "light" "origin" "-568 -1112 1022" "light" "750" "wait" ".8" } { "classname" "light" "origin" "1092 172 80" "light" "150" } { "classname" "light" "light" "150" "origin" "1132 212 80" } { "classname" "light" "origin" "1172 172 80" "light" "150" } { "classname" "light" "light" "150" "origin" "1092 -44 80" } { "classname" "light" "light" "150" "origin" "1172 -44 80" } { "classname" "light" "origin" "1132 -84 80" "light" "150" } { "classname" "light" "light" "750" "origin" "-568 1240 1022" "wait" "0.8" } { "classname" "light" "origin" "-282 -632 412" "light" "125" } { "classname" "light" "light" "125" "origin" "-310 -656 412" } { "classname" "light" "origin" "-282 -680 412" "light" "125" } { "classname" "light" "origin" "-256 784 412" "light" "125" } { "classname" "light" "light" "125" "origin" "-280 808 412" } { "classname" "light" "origin" "-308 784 412" "light" "125" } { "classname" "light" "light" "125" "origin" "-280 760 412" } { "classname" "light" "light" "600" "origin" "280 64 1336" } { "classname" "light" "light" "200" "origin" "2512 64 416" } { "classname" "light" "light" "125" "origin" "-256 -656 408" } { "classname" "light" "origin" "192 64 1088" "light" "200" "wait" ".25" } { "classname" "light" "origin" "-272 -592 528" "light" "200" } { "classname" "light" "origin" "-384 544 512" "light" "300" } { "classname" "light" "origin" "-272 -512 528" "light" "200" } { "classname" "light" "origin" "-384 -416 512" "light" "300" } { "classname" "light" "origin" "-272 640 528" "light" "200" } { "classname" "light" "origin" "-272 720 528" "light" "200" } { "classname" "light" "origin" "672 320 288" "light" "200" "style" "0" "wait" "0.5" } { "classname" "light" "origin" "832 64 288" "light" "200" "style" "0" "wait" ".5" } { "classname" "light" "origin" "672 -192 288" "light" "200" "style" "0" "wait" ".5" } { "classname" "light" "origin" "720 -256 352" "light" "150" } { "classname" "light" "origin" "720 -320 352" "light" "150" } { "classname" "light" "origin" "720 384 352" "light" "150" } { "classname" "light" "origin" "720 448 352" "light" "150" } { "classname" "light" "origin" "736 64 400" "light" "150" } { "classname" "light" "origin" "616 116 248" "light" "75" } { "classname" "light" "origin" "616 12 248" "light" "150" } { "classname" "light" "origin" "448 64 628" "light" "300" } { "classname" "light" "origin" "192 320 628" "light" "300" } { "classname" "light" "light" "300" "origin" "192 -192 628" } { "classname" "light" "light" "300" "origin" "-64 64 628" } { "classname" "light" "origin" "292 -36 32" "light" "300" } { "classname" "light" "origin" "92 -36 32" "light" "300" } { "classname" "light" "origin" "292 164 32" "light" "300" } { "classname" "light" "origin" "92 164 32" "light" "300" } { "classname" "light" "origin" "192 64 352" "light" "201" "wait" "0.25" } { "classname" "light" "origin" "64 640 128" "light" "200" } { "classname" "light" "origin" "-32 640 128" "light" "200" } { "classname" "light" "origin" "368 640 128" "light" "200" } { "classname" "light" "origin" "272 640 128" "light" "200" } { "classname" "light" "origin" "384 896 544" "light" "300" "wait" ".5" } { "classname" "light" "origin" "64 -512 128" "light" "200" } { "classname" "light" "origin" "-32 -512 128" "light" "200" } { "classname" "light" "origin" "368 -512 128" "light" "200" } { "classname" "light" "origin" "272 -512 128" "light" "200" } { "classname" "light" "origin" "384 -768 544" "light" "300" "wait" ".5" } { "classname" "light" "origin" "-512 64 1248" "light" "400" "wait" ".5" } { "classname" "light" "origin" "1728 64 768" "light" "600" "wait" ".5" } { "classname" "info_player_deathmatch" "origin" "-416 -1152 640" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "-416 1280 640" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "448 928 416" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "384 -896 416" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "128 -480 64" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "128 512 64" "angle" "90" } { "origin" "2448 163 280" "angle" "180" "classname" "info_player_deathmatch" } { "origin" "2448 -64 280" "angle" "180" "classname" "info_player_deathmatch" } { "classname" "item_armorInv" "origin" "664 64 352" } { "classname" "weapon_supershotgun" "origin" "-576 1216 640" } { "classname" "weapon_supershotgun" "origin" "-576 -1088 640" } { "classname" "weapon_rocketlauncher" "origin" "288 -544 400" } { "classname" "weapon_rocketlauncher" "origin" "288 672 384" } { "classname" "info_player_start" "origin" "192 64 1344" "angle" "90" } { "classname" "item_armor2" "origin" "-384 64 864" "targetname" "yarmor" } { "classname" "item_health" "origin" "96 1104 640" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "128 1104 640" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "96 -1008 640" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "128 -1008 640" "angle" "90" "spawnflags" "0" } { "classname" "item_shells" "origin" "-560 -1199 641" "angle" "90" } { "classname" "item_shells" "origin" "-548 1300 640" "angle" "90" } { "classname" "item_artifact_super_damage" "origin" "128 64 1344" } { "classname" "weapon_lightning" "origin" "2432 64 288" } { "classname" "item_cells" "origin" "2387 -19 288" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "2528 336 304" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "2528 -240 304" "angle" "90" "spawnflags" "0" } { "classname" "item_cells" "origin" "1027 141 48" "angle" "90" "spawnflags" "0" } { "classname" "item_cells" "origin" "1027 -51 48" "angle" "90" "spawnflags" "0" } { "classname" "info_teleport_destination" "origin" "744 64 324" "angle" "180" "targetname" "redarmor" } { "classname" "item_health" "origin" "592 -560 32" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "560 -560 32" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "592 656 32" "angle" "90" "spawnflags" "0" } { "classname" "item_health" "origin" "560 656 32" "angle" "90" "spawnflags" "0" } { "classname" "item_rockets" "origin" "392 808 384" "angle" "90" "spawnflags" "1" } { "classname" "item_rockets" "origin" "376 -584 384" "angle" "90" "spawnflags" "1" } { "classname" "trigger_hurt" "dmg" "999" "model" "*2" } { "classname" "func_illusionary" "model" "*3" } { "classname" "func_wall" "targetname" "kill" "model" "*4" } { "classname" "trigger_teleport" "target" "redarmor" "model" "*5" } { "classname" "trigger_teleport" "target" "redarmor" "model" "*6" } { "classname" "light" "origin" "-320 64 896" "light" "300" "target" "yarmor" } { "classname" "light" "origin" "-384 432 896" "light" "300" } { "classname" "light" "origin" "-384 176 1088" "light" "300" } { "classname" "light" "origin" "-384 -48 1088" "light" "300" } { "classname" "light" "origin" "-384 -304 896" "light" "300" } { "classname" "trigger_push" "speed" "95" "angles" "255 270 0" "model" "*7" } { "classname" "trigger_push" "speed" "95" "angles" "255 90 0" "model" "*8" } { "classname" "trigger_push" "speed" "90" "angles" "255 180 0" "model" "*9" } { "classname" "trigger_push" "speed" "150" "angles" "255 0 0" "model" "*10" } { "classname" "trigger_push" "speed" "115" "angles" "250 180 0" "model" "*11" } { "classname" "trigger_push" "speed" "100" "angles" "260 315 0" "model" "*12" } { "classname" "trigger_push" "speed" "100" "angles" "260 45 0" "model" "*13" } { "classname" "trigger_push" "speed" "95" "angles" "220 90 0" "model" "*14" } { "classname" "trigger_push" "speed" "110" "angles" "240 180 0" "model" "*15" } { "classname" "trigger_push" "speed" "135" "angles" "220 11 0" "model" "*16" } { "classname" "trigger_push" "speed" "135" "angles" "220 350 0" "model" "*17" } { "classname" "trigger_push" "speed" "95" "angles" "220 270 0" "model" "*18" } { "classname" "info_intermission" "origin" "2352 52 360" "mangle" "0 180 0" } { "classname" "trigger_once" "killtarget" "kill" "model" "*19" } { "classname" "item_health" "origin" "208 48 1152" "angle" "90" "spawnflags" "2" } { "classname" "trigger_push" "angle" "-1" "speed" "125" "model" "*20" } { "classname" "func_wall" "targetname" "kill" "model" "*21" } { "classname" "info_null" "origin" "-384 64 864" "angle" "90" "targetname" "yarmor" } { "classname" "info_monster_start" "origin" "-159.625 94.125 24" } { "classname" "info_monster_start" "origin" "-153 237.25 24" } { "classname" "info_monster_start" "origin" "-167.125 -95.625 24" } { "classname" "info_monster_start" "origin" "-155.375 -302.25 24" } { "classname" "info_monster_start" "origin" "-251.5 -301.625 24" } { "classname" "info_monster_start" "origin" "-42.125 -302.875 24" } { "classname" "info_monster_start" "origin" "75.875 -303.625 24" } { "classname" "info_monster_start" "origin" "-101.875 549.125 352" } { "classname" "info_monster_start" "origin" "32.75 554 352" } { "classname" "info_monster_start" "origin" "213.5 562.375 352" } { "classname" "info_monster_start" "origin" "-221.5 -508.75 352" } { "classname" "info_monster_start" "origin" "-182.875 -626.625 352" } { "classname" "info_monster_start" "origin" "-147.75 -734.25 352" } { "classname" "info_monster_start" "origin" "34.125 -794.625 352" } { "classname" "info_monster_start" "origin" "-70.75 -830.75 352" } { "classname" "info_monster_start" "origin" "-64.25 -543.875 352" } { "classname" "info_monster_start" "origin" "210.875 -845.75 352" } { "classname" "info_monster_start" "origin" "497.25 -677.75 352" } { "classname" "info_monster_start" "origin" "392.875 -868.625 352" } { "classname" "info_monster_start" "origin" "393.875 -943.625 352" } { "classname" "info_monster_start" "origin" "480.625 -947 352" } { "classname" "info_monster_start" "origin" "488 -827 352" } { "classname" "info_monster_start" "origin" "653.5 -830.125 352" } { "classname" "info_monster_start" "origin" "662 -690.5 352" } { "classname" "info_monster_start" "origin" "655.375 -513.125 348" } { "classname" "info_monster_start" "origin" "656.75 -400.75 348" } { "classname" "info_monster_start" "origin" "660 -124.125 348" } { "classname" "info_monster_start" "origin" "661.125 -29.25 348" } { "classname" "info_monster_start" "origin" "801.75 4.625 348" } { "classname" "info_monster_start" "origin" "801.375 104.75 348" } { "classname" "info_monster_start" "origin" "663.75 182.875 348" } { "classname" "info_monster_start" "origin" "665.125 296.875 348" } { "classname" "info_monster_start" "origin" "410.375 583.625 352" } { "classname" "info_monster_start" "origin" "-101.5 683 352" } { "classname" "info_monster_start" "origin" "-204.875 656.375 352" } { "classname" "info_monster_start" "origin" "-182.125 763.5 352" } { "classname" "info_monster_start" "origin" "54.875 944.875 352" } { "classname" "info_monster_start" "origin" "-33.875 950.625 352" } { "classname" "info_monster_start" "origin" "-155.5 889.5 352" } { "classname" "info_monster_start" "origin" "32.25 671.25 352" } { "classname" "info_monster_start" "origin" "214.5 650.375 352" } { "classname" "info_monster_start" "origin" "215.875 765.75 352" } { "classname" "info_monster_start" "origin" "217.125 876.75 352" } { "classname" "info_monster_start" "origin" "218.625 1001.5 352" } { "classname" "info_monster_start" "origin" "410.5 667.375 352" } { "classname" "info_monster_start" "origin" "410.875 796.5 352" } { "classname" "info_monster_start" "origin" "411.25 913.875 352" } { "classname" "info_monster_start" "origin" "411.5 1022.62 352" } { "classname" "info_monster_start" "origin" "555.25 748.125 352" } { "classname" "info_monster_start" "origin" "561 863.125 352" } { "classname" "info_monster_start" "origin" "667.125 906 352" } { "classname" "info_monster_start" "origin" "568.75 1015.5 352" } { "classname" "info_monster_start" "origin" "662.5 763.25 352" } { "classname" "info_monster_start" "origin" "668.875 617 348" } { "classname" "info_monster_start" "origin" "662.375 72.125 348" } { "classname" "info_monster_start" "origin" "82.75 1015.75 600" } { "classname" "info_monster_start" "origin" "119 1068.5 600" } { "classname" "info_monster_start" "origin" "49.125 1071.38 600" } { "classname" "info_monster_start" "origin" "-39.125 1075 600" } { "classname" "info_monster_start" "origin" "-134.5 1079 600" } { "classname" "info_monster_start" "origin" "-149.5 893.875 600" } { "classname" "info_monster_start" "origin" "-232.625 1083 600" } { "classname" "info_monster_start" "origin" "-386.375 911.25 600" } { "classname" "info_monster_start" "origin" "-267.5 676.75 600" } { "classname" "info_monster_start" "origin" "-402.25 658.625 600" } { "classname" "info_monster_start" "origin" "-397.875 727.75 600" } { "classname" "info_monster_start" "origin" "-392.625 811.875 600" } { "classname" "info_monster_start" "origin" "-381.5 989.5 600" } { "classname" "info_monster_start" "origin" "-311.375 1086.25 600" } { "classname" "info_monster_start" "origin" "-590.125 937.375 600" } { "classname" "info_monster_start" "origin" "-590.625 1025.88 600" } { "classname" "info_monster_start" "origin" "-591.25 1120.5 600" } { "classname" "info_monster_start" "origin" "-591.625 1195.88 600" } { "classname" "info_monster_start" "origin" "-628.25 1272.5 600" } { "classname" "info_monster_start" "origin" "-508.125 1260.75 600" } { "classname" "info_monster_start" "origin" "-432.875 1253.25 600" } { "classname" "info_monster_start" "origin" "-337.375 1243.88 600" } { "classname" "info_monster_start" "origin" "-268.5 1237.12 600" } { "classname" "info_monster_start" "origin" "-376.25 1073.38 600" } { "classname" "info_monster_start" "origin" "90 174 1304" } { "classname" "info_monster_start" "origin" "91 128 1304" } { "classname" "info_monster_start" "origin" "206.625 180.375 1304" } { "classname" "info_monster_start" "origin" "92.375 57.375 1304" } { "classname" "info_monster_start" "origin" "94.5 -42.625 1304" } { "classname" "info_monster_start" "origin" "-381.25 -505.625 600" } { "classname" "info_monster_start" "origin" "-407.875 -768.625 600" } { "classname" "info_monster_start" "origin" "-579.625 -822.75 600" } { "classname" "info_monster_start" "origin" "-585.75 -933.125 600" } { "classname" "info_monster_start" "origin" "-590.5 -1019.25 600" } { "classname" "info_monster_start" "origin" "-593.75 -1076.25 600" } { "classname" "info_monster_start" "origin" "-596.625 -1128.88 600" } { "classname" "info_monster_start" "origin" "-510.5 -1127.75 600" } { "classname" "info_monster_start" "origin" "-438.125 -1126.75 600" } { "classname" "info_monster_start" "origin" "-362 -1125.62 600" } { "classname" "info_monster_start" "origin" "-295.5 -1124.75 600" } { "classname" "info_monster_start" "origin" "-262.375 -943.625 600" } { "classname" "info_monster_start" "origin" "-174.875 -944.375 600" } { "classname" "info_monster_start" "origin" "-340.375 -942.875 600" } { "classname" "info_monster_start" "origin" "-417.5 -864.125 600" } { "classname" "info_monster_start" "origin" "-422.375 -942.125 600" } { "classname" "info_monster_start" "origin" "214.25 -54.75 1304" } { "classname" "info_monster_start" "origin" "209.125 103.375 1304" } { "classname" "info_monster_start" "origin" "2269.75 154.375 280" } { "classname" "info_monster_start" "origin" "2272.12 -40.875 280" } { "classname" "info_monster_start" "origin" "2361.38 -44.125 280" } { "classname" "info_monster_start" "origin" "2447.5 -47.125 280" } { "classname" "info_monster_start" "origin" "2527.88 -50 280" } { "classname" "info_monster_start" "origin" "2490.88 68.125 280" } { "classname" "info_monster_start" "origin" "2420.62 67.625 280" } { "classname" "info_monster_start" "origin" "2353.38 67 280" } { "classname" "info_monster_start" "origin" "2281.12 66.375 280" } { "classname" "info_monster_start" "origin" "2508.12 149.875 280" } { "classname" "info_monster_start" "origin" "2439.25 151.125 280" } { "classname" "info_monster_start" "origin" "2367.62 152.5 280" } { "classname" "info_monster_start" "origin" "211.875 20 1304" } { "classname" "info_monster_start" "origin" "1027.38 57.875 24" } { "classname" "info_monster_start" "origin" "943 59.5 24" } { "classname" "info_monster_start" "origin" "844.125 61.375 24" } { "classname" "info_monster_start" "origin" "105.75 -946.875 600" } { "classname" "info_monster_start" "origin" "22.875 -946.125 600" } { "classname" "info_monster_start" "origin" "-80.625 -945.25 600" } { "classname" "info_monster_start" "origin" "-398 -671.5 600" } { "classname" "info_monster_start" "origin" "-389.875 -590.5 600" } { "classname" "info_monster_start" "origin" "-150.25 -799 600" } { "classname" "info_monster_start" "origin" "-267 -562.75 600" } { "classname" "info_monster_start" "origin" "391.5 -750.75 352" } { "classname" "info_monster_start" "origin" "390 -635.125 352" } { "classname" "info_monster_start" "origin" "388.75 -528.625 352" } { "classname" "info_monster_start" "origin" "216.375 -737.125 352" } { "classname" "info_monster_start" "origin" "222.125 -623.75 352" } { "classname" "info_monster_start" "origin" "227.75 -514.75 352" } { "classname" "info_monster_start" "origin" "44.375 -533.875 352" } { "classname" "info_monster_start" "origin" "-75.375 -413.875 352" } { "classname" "info_monster_start" "origin" "37.75 -403.625 352" } { "classname" "info_monster_start" "origin" "232.375 -425 352" } { "classname" "info_monster_start" "origin" "387.625 -437 352" } { "classname" "info_monster_start" "origin" "658.75 -226.875 348" } { "classname" "info_monster_start" "origin" "657.75 -313.5 348" } { "classname" "info_monster_start" "origin" "526.875 -306.625 24" } { "classname" "info_monster_start" "origin" "428.625 -306 24" } { "classname" "info_monster_start" "origin" "-74.875 -96.25 24" } { "classname" "info_monster_start" "origin" "37.125 -97 24" } { "classname" "info_monster_start" "origin" "89.125 -97.375 24" } { "classname" "info_monster_start" "origin" "206.125 -304.5 24" } { "classname" "info_monster_start" "origin" "320.125 -305.25 24" } { "classname" "info_monster_start" "origin" "321.625 -136.375 24" } { "classname" "info_monster_start" "origin" "422 -137 24" } { "classname" "info_monster_start" "origin" "521.75 -137.75 24" } { "classname" "info_monster_start" "origin" "585.625 -138.25 24" } { "classname" "info_monster_start" "origin" "740.375 63.375 24" } { "classname" "info_monster_start" "origin" "640.125 65.375 24" } { "classname" "info_monster_start" "origin" "667.875 528.25 348" } { "classname" "info_monster_start" "origin" "666.5 415.875 348" } { "classname" "info_monster_start" "origin" "588.625 439.125 24" } { "classname" "info_monster_start" "origin" "476.75 439.375 24" } { "classname" "info_monster_start" "origin" "362.625 439.75 24" } { "classname" "info_monster_start" "origin" "265.375 440 24" } { "classname" "info_monster_start" "origin" "149.875 440.375 24" } { "classname" "info_monster_start" "origin" "45.875 440.625 24" } { "classname" "info_monster_start" "origin" "-40.5 441 24" } { "classname" "info_monster_start" "origin" "-264.5 441.625 24" } { "classname" "info_monster_start" "origin" "-145.375 441.25 24" } { "classname" "info_monster_start" "origin" "-74 232 24" } { "classname" "info_monster_start" "origin" "88.5 221.125 24" } { "classname" "info_monster_start" "origin" "273 219.25 24" } { "classname" "info_monster_start" "origin" "352.75 213.875 24" } { "classname" "info_monster_start" "origin" "462.375 206.625 24" } { "classname" "info_monster_start" "origin" "565.75 199.625 24" } { // distant area right corner "classname" "trigger_custom_monsterjump" "origin" "2300 184 280" "size" "50 50 50" "angle" "166" "speed" "1111" "height" "1111" } { // distant area left corner "classname" "trigger_custom_monsterjump" "origin" "2278 -47 280" "size" "50 50 50" "angle" "-166" "speed" "1111" "height" "1111" } { // from up to right side "classname" "trigger_custom_monsterjump" "origin" "53 211 1304" "size" "50 50 50" "angle" "118" "speed" "555" "height" "300" } { // from up to left side "classname" "trigger_custom_monsterjump" "origin" "60 -82 1304" "size" "50 50 50" "angle" "-118" "speed" "555" "height" "300" } { // from down to left side "classname" "trigger_custom_monsterjump" "origin" "-134 -173 24" "size" "50 50 50" "angle" "-106" "speed" "222" "height" "1100" } { // from up to right side "classname" "trigger_custom_monsterjump" "origin" "-134 307 24" "size" "50 50 50" "angle" "106" "speed" "222" "height" "1100" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/rz1pondb.ent000066400000000000000000000350621475442401000254150ustar00rootroot00000000000000{ "classname" "worldspawn" "sounds" "1" "message" "Woodland Pond - by rzarecta" } { "classname" "info_player_start" "origin" "-560 -672 -176" } { "classname" "light" "light" "700" "origin" "64 192 448" } { "classname" "light" "light" "700" "origin" "64 -1056 448" } { "classname" "light" "light" "700" "origin" "64 -448 448" } { "classname" "light" "light" "700" "origin" "864 -448 448" } { "classname" "light" "light" "700" "origin" "-704 -448 448" } { "classname" "light" "light" "550" "origin" "-480 32 224" } { "classname" "light" "light" "550" "origin" "640 32 224" } { "classname" "light" "light" "550" "origin" "640 -960 224" } { "classname" "light" "light" "550" "origin" "-480 -960 224" } { "classname" "light" "light" "400" "origin" "64 -32 32" } { "classname" "light" "light" "400" "origin" "64 -800 32" } { "classname" "light" "light" "400" "origin" "608 -448 32" } { "classname" "light" "light" "400" "origin" "-480 -448 32" } { "classname" "light" "light" "400" "origin" "384 32 -160" } { "classname" "light" "light" "400" "origin" "-192 -160 -160" } { "classname" "light" "light" "400" "origin" "384 -768 -160" } { "classname" "light" "light" "400" "origin" "-288 -992 -160" } { "classname" "light" "origin" "64 -448 -192" } { "classname" "light" "light" "500" "origin" "864 -512 128" } { "classname" "light" "light" "500" "origin" "-736 -512 128" } { "classname" "light" "light" "400" "origin" "576 -1248 -128" } { "classname" "light" "light" "400" "origin" "576 320 -128" } { "classname" "light" "light" "400" "origin" "-448 320 -128" } { "classname" "light" "light" "400" "origin" "-448 -1248 -64" } { "classname" "light" "origin" "64 -1312 0" } { "classname" "light" "origin" "64 416 0" } { "classname" "light" "light" "350" "origin" "896 -896 32" } { "classname" "light" "light" "350" "origin" "960 -192 -128" } { "classname" "light" "light" "350" "origin" "-864 -864 -64" } { "classname" "light" "light" "350" "origin" "-768 -160 -96" } { "classname" "light" "origin" "64 -1120 -160" } { "classname" "light" "origin" "64 256 -192" } { "classname" "light" "origin" "992 -736 -160" } { "classname" "light" "origin" "-544 416 64" } { "classname" "light" "light" "600" "origin" "64 192 -448" } { "classname" "light" "light" "600" "origin" "64 -1088 -448" } { "classname" "light" "light" "600" "origin" "64 -448 -320" } { "classname" "light" "light" "350" "origin" "512 192 -480" } { "classname" "light" "light" "350" "origin" "-384 192 -480" } { "classname" "light" "light" "350" "origin" "512 -1152 -480" } { "classname" "light" "light" "350" "origin" "-352 -1152 -480" } { "classname" "light" "light" "450" "origin" "416 -448 -416" } { "classname" "light" "light" "350" "origin" "-384 -448 -480" } { "classname" "light" "origin" "-960 -128 -96" } { "classname" "light" "light" "300" "origin" "-448 0 -480" } { "classname" "light" "light" "300" "origin" "512 -288 -416" } { "classname" "info_player_deathmatch" "angle" "323" "origin" "-608 448 0" } { "classname" "info_player_deathmatch" "origin" "-960 -480 0" } { "classname" "info_player_deathmatch" "origin" "-640 -576 -160" } { "classname" "info_player_deathmatch" "angle" "94" "origin" "64 -1312 -32" } { "classname" "info_player_deathmatch" "angle" "112" "origin" "864 -992 0" } { "classname" "info_player_deathmatch" "angle" "170" "origin" "960 -288 -112" } { "classname" "info_player_deathmatch" "angle" "276" "origin" "488 448 -200" } { "classname" "info_player_deathmatch" "origin" "256 -448 -192" } { "classname" "info_player_deathmatch" "angle" "183" "origin" "-160 -448 -192" } { "classname" "info_player_deathmatch" "angle" "98" "origin" "384 -1024 -192" } { "classname" "info_player_deathmatch" "angle" "281" "origin" "-272 32 -176" } { "classname" "info_intermission" "angle" "323" "origin" "-256 256 256" } { "classname" "info_teleport_destination" "angle" "87" "targetname" "tele1" "origin" "64 -432 -64" } { "classname" "trigger_teleport" "target" "tele1" "model" "*1" } { "classname" "trigger_teleport" "target" "tele1" "model" "*2" } { "classname" "func_door" "angle" "-1" "sounds" "0" "targetname" "dor1" "speed" "600" "wait" "1" "lip" "0" "dmg" "0" "health" "0" "model" "*3" } { "classname" "func_button" "angle" "-2" "speed" "100" "sounds" "2" "target" "dor1" "delay" "0" "model" "*4" } { "classname" "trigger_push" "angle" "18" "speed" "75" "sounds" "4" "style" "32" "delay" "0" "model" "*5" } { "classname" "weapon_rocketlauncher" "origin" "64 -992 -48" } { "classname" "item_rockets" "spawnflags" "1" "origin" "112 -992 -64" } { "classname" "info_monster_start" "origin" "474.625 -887.875 -297.375" } { "classname" "info_monster_start" "origin" "467.125 -776.75 -300.375" } { "classname" "info_monster_start" "origin" "469.25 -690.5 -303.375" } { "classname" "info_monster_start" "origin" "471 -614 -302.5" } { "classname" "info_monster_start" "origin" "473.375 -520.125 -301.75" } { "classname" "info_monster_start" "origin" "487.375 -473.5 -199.875" } { "classname" "info_monster_start" "origin" "477.125 -365.375 -320.75" } { "classname" "info_monster_start" "origin" "478.25 -315.75 -284.375" } { "classname" "info_monster_start" "origin" "480 -244.75 -282.75" } { "classname" "info_monster_start" "origin" "482 -159.125 -294.375" } { "classname" "info_monster_start" "origin" "484.375 -64.375 -298.5" } { "classname" "info_monster_start" "origin" "486.125 11.625 -296.125" } { "classname" "info_monster_start" "origin" "503.125 77.5 -287.625" } { "classname" "info_monster_start" "origin" "505 156.75 -285.5" } { "classname" "info_monster_start" "origin" "517.625 252.125 -292" } { "classname" "info_monster_start" "origin" "641.375 243.375 -199.875" } { "classname" "info_monster_start" "origin" "641.125 138.125 -199.875" } { "classname" "info_monster_start" "origin" "640.875 40.25 -199.875" } { "classname" "info_monster_start" "origin" "640.625 -59 -199.875" } { "classname" "info_monster_start" "origin" "350.25 227.5 -274" } { "classname" "info_monster_start" "origin" "214.75 229.5 -279.625" } { "classname" "info_monster_start" "origin" "92.875 221 -284.75" } { "classname" "info_monster_start" "origin" "-47.375 223 -290.625" } { "classname" "info_monster_start" "origin" "-187.875 225.125 -296.5" } { "classname" "info_monster_start" "origin" "-291.875 229 -292.75" } { "classname" "info_monster_start" "origin" "-363.25 191.5 -264" } { "classname" "info_monster_start" "origin" "-375.25 18.625 -275.875" } { "classname" "info_monster_start" "origin" "-271.375 28.625 -183.875" } { "classname" "info_monster_start" "origin" "-383.125 -121.75 -278.25" } { "classname" "info_monster_start" "origin" "-369.75 -275.5 -284.75" } { "classname" "info_monster_start" "origin" "-348.375 -460.625 -305.5" } { "classname" "info_monster_start" "origin" "-342.375 -501 -199.875" } { "classname" "info_monster_start" "origin" "-329.875 -610.875 -291.875" } { "classname" "info_monster_start" "origin" "-339.625 -750.25 -294.875" } { "classname" "info_monster_start" "origin" "-351.125 -908.375 -308.125" } { "classname" "info_monster_start" "origin" "-387.125 -1021.5 -307.625" } { "classname" "info_monster_start" "origin" "-388.25 -1105.62 -306.875" } { "classname" "info_monster_start" "origin" "-560.5 -1131.62 -199.875" } { "classname" "info_monster_start" "origin" "-158.875 -1104 -307.375" } { "classname" "info_monster_start" "origin" "52.25 -1102.5 -332.875" } { "classname" "info_monster_start" "origin" "263.875 -1111.25 -345.5" } { "classname" "info_monster_start" "origin" "468.625 -1109.75 -327" } { "classname" "info_monster_start" "origin" "369.25 -993.875 -199.875" } { "classname" "info_monster_start" "origin" "638.125 -1100.88 -199.875" } { "classname" "info_monster_start" "origin" "638 -1185.75 -199.875" } { "classname" "info_monster_start" "origin" "455.125 -1331.62 -199.875" } { "classname" "info_monster_start" "origin" "638.5 -939 -199.875" } { "classname" "info_monster_start" "origin" "638.75 -840.25 -199.875" } { "classname" "info_monster_start" "origin" "639 -758 -196" } { "classname" "info_monster_start" "origin" "639.25 -668.875 -191.625" } { "classname" "info_monster_start" "origin" "891 -1002.75 -23.875" } { "classname" "info_monster_start" "origin" "838.75 -691.5 -191.5" } { "classname" "info_monster_start" "origin" "57.5 -792 -71.875" } { "classname" "info_monster_start" "origin" "59.625 -705.125 -71.875" } { "classname" "info_monster_start" "origin" "61.5 -632.375 -71.875" } { "classname" "info_monster_start" "origin" "63.875 -534.5 -71.875" } { "classname" "info_monster_start" "origin" "66.25 -440.375 -63.875" } { "classname" "info_monster_start" "origin" "70.25 -280.625 -71.875" } { "classname" "info_monster_start" "origin" "382.375 -174.25 120" } { "classname" "info_monster_start" "origin" "74 -135.625 -71.875" } { "classname" "info_monster_start" "origin" "-92.875 -747.5 320" } { "classname" "info_monster_start" "origin" "-648.125 -771 216" } { "classname" "info_monster_start" "origin" "-549.75 -730.375 -199.875" } { "classname" "info_monster_start" "origin" "-973.625 -618.375 -23.875" } { "classname" "info_monster_start" "origin" "-977.25 -529.125 -23.875" } { "classname" "info_monster_start" "origin" "-980.75 -446 -23.875" } { "classname" "info_monster_start" "origin" "-983.125 -386.25 -23.875" } { "classname" "info_monster_start" "origin" "-985.375 -331.875 -23.875" } { "classname" "info_monster_start" "origin" "-538.875 -327.5 -199.875" } { "classname" "info_monster_start" "origin" "-536.125 -226.25 -199.875" } { "classname" "info_monster_start" "origin" "-533.5 -128.375 -199.875" } { "classname" "info_monster_start" "origin" "-547 -628.375 -199.875" } { "classname" "info_monster_start" "origin" "-552.375 -828.75 -199.875" } { "classname" "info_monster_start" "origin" "-555 -929.5 -199.875" } { "classname" "info_monster_start" "origin" "-521.125 333.75 -199.875" } { "classname" "info_monster_start" "origin" "-590.25 418.25 -7.875" } { "classname" "info_monster_start" "origin" "89.125 467.25 -71.875" } { "classname" "info_monster_start" "origin" "68.5 -350.875 -71.875" } { "classname" "info_monster_start" "origin" "830.25 -11.75 -199.25" } { "classname" "info_monster_start" "origin" "800.25 -247.125 -196.5" } { "classname" "info_monster_start" "origin" "961 -320.25 -151.875" } { "classname" "info_monster_start" "origin" "888.75 -518.625 -199.875" } { "classname" "info_monster_start" "origin" "952.25 -698.375 -199.875" } { "classname" "info_monster_start" "origin" "1040.62 -703.75 -199.875" } { "classname" "info_monster_start" "origin" "970.625 -986 -23.875" } { "classname" "info_monster_start" "origin" "1045.12 -970.25 -23.875" } { "classname" "info_monster_start" "origin" "961.375 -20.75 -199.875" } { "classname" "info_monster_start" "origin" "640.25 -246.75 -199.875" } { "classname" "info_monster_start" "origin" "1106.75 -103.375 -199.875" } { "classname" "info_monster_start" "origin" "1117.62 -708.375 -199.875" } { "classname" "info_monster_start" "origin" "55.25 -881 -71.875" } { "classname" "info_monster_start" "origin" "53 -967.625 -71.875" } { "classname" "info_monster_start" "origin" "50.875 -1052.88 -71.875" } { "classname" "info_monster_start" "origin" "48.75 -1140.75 -71.875" } { "classname" "info_monster_start" "origin" "46.5 -1228.62 -71.875" } { "classname" "info_monster_start" "origin" "44.625 -1301.38 -71.875" } { "classname" "info_monster_start" "origin" "43 -1365.75 -71.875" } { "classname" "info_monster_start" "origin" "-324.5 -1328.12 -199.875" } { "classname" "info_monster_start" "origin" "-382.625 -1320.75 -199.875" } { "classname" "info_monster_start" "origin" "-459.75 -1310.88 -199.875" } { "classname" "info_monster_start" "origin" "-564.875 -1297.62 -199.875" } { "classname" "info_monster_start" "origin" "-563.125 -1228.5 -199.875" } { "classname" "info_monster_start" "origin" "-557.75 -1030.75 -199.875" } { "classname" "info_monster_start" "origin" "-440 391.625 -199.875" } { "classname" "info_monster_start" "origin" "-312.25 401.125 -199.875" } { "classname" "info_monster_start" "origin" "76.125 -47.75 -71.875" } { "classname" "info_monster_start" "origin" "702.75 430.875 -199.875" } { "classname" "info_monster_start" "origin" "596.875 423 -199.875" } { "classname" "info_monster_start" "origin" "641.625 337.625 -199.875" } { "classname" "info_monster_start" "origin" "637.75 -1282.75 -199.875" } { "classname" "info_monster_start" "origin" "591.75 -1332 -199.875" } { "classname" "info_monster_start" "origin" "638.375 -1019.62 -199.875" } { "classname" "info_monster_start" "origin" "639.375 -587 -196.25" } { "classname" "info_monster_start" "origin" "639.625 -494 -199.875" } { "classname" "info_monster_start" "origin" "639.75 -419 -199.875" } { "classname" "info_monster_start" "origin" "640 -336.75 -199.875" } { "classname" "info_monster_start" "origin" "640.5 -155 -199.875" } { "classname" "info_monster_start" "origin" "521.5 417.375 -199.875" } { "classname" "info_monster_start" "origin" "465.5 413.25 -199.875" } { "classname" "info_monster_start" "origin" "87.125 391.125 -71.875" } { "classname" "info_monster_start" "origin" "85.125 309.625 -71.875" } { "classname" "info_monster_start" "origin" "82.75 214.625 -71.875" } { "classname" "info_monster_start" "origin" "80.5 126.875 -71.875" } { "classname" "info_monster_start" "origin" "78.375 40.5 -71.875" } { "classname" "info_monster_start" "origin" "-523.5 244.875 -199.875" } { "classname" "info_monster_start" "origin" "-525.875 157.375 -199.875" } { "classname" "info_monster_start" "origin" "-528.375 63.875 -199.875" } { "classname" "info_monster_start" "origin" "72 -213 -71.875" } { "classname" "info_monster_start" "origin" "-531 -35.125 -199.875" } { "classname" "info_monster_start" "origin" "-541.625 -431.5 -199.875" } { "classname" "info_monster_start" "origin" "-544.25 -527.875 -199.875" } { "classname" "info_monster_start" "origin" "-289.75 -499.25 -199.875" } { "classname" "info_monster_start" "origin" "-200 -496.25 -199.875" } { "classname" "info_monster_start" "origin" "-117.125 -493.5 -199.875" } { "classname" "info_monster_start" "origin" "-30 -490.625 -199.875" } { "classname" "info_monster_start" "origin" "48.75 -488 -199.875" } { "classname" "info_monster_start" "origin" "119.625 -485.75 -199.875" } { "classname" "info_monster_start" "origin" "200.375 -483 -199.875" } { "classname" "info_monster_start" "origin" "281.625 -480.375 -199.875" } { "classname" "info_monster_start" "origin" "354.375 -477.875 -199.875" } { // bridge "classname" "trigger_custom_monsterjump" "origin" "170 -436 -95" "size" "1 100 1" "angle" "0" "speed" "400" "height" "200" } { // bridge "classname" "trigger_custom_monsterjump" "origin" "-30 -448 -95" "size" "1 100 1" "angle" "180" "speed" "400" "height" "200" } { // corner stairs "classname" "trigger_custom_monsterjump" "origin" "824 -929 -23" "size" "32 32 32" "angle" "118" "speed" "200" "height" "200" } QW-Group-ktx-d05d6ca/resources/example-configs/id1/maps/slaug.ent000066400000000000000000000327611475442401000247740ustar00rootroot00000000000000{ "classname" "worldspawn" "message" "Slaughter-house" } { "angle" "90" "origin" "0 -712 28" "classname" "info_player_start" } { "light" "250" "angle" "0" "origin" "416 416 300" "classname" "light" } { "light" "300" "angle" "0" "origin" "0 0 284" "classname" "light" } { "light" "400" "angle" "0" "origin" "0 0 76" "classname" "light" } { "light" "250" "angle" "0" "origin" "-680 40 292" "classname" "light" } { "light" "250" "angle" "0" "origin" "680 40 292" "classname" "light" } { "light" "250" "angle" "0" "origin" "0 -712 96" "classname" "light" } { "light" "250" "angle" "0" "origin" "-704 -696 284" "classname" "light" } { "light" "250" "angle" "0" "origin" "704 -696 284" "classname" "light" } { "classname" "light_flame_small_white" "origin" "0 632 296" "light" "400" } { "light" "250" "angle" "0" "origin" "0 552 292" "classname" "light" } { "classname" "trigger_teleport" "target" "t1" "model" "*1" } { "classname" "info_teleport_destination" "origin" "0 576 202" "angle" "270" "targetname" "t1" } { "classname" "light_flame_small_white" "origin" "504 504 296" "light" "600" } { "light" "250" "angle" "0" "origin" "416 416 88" "classname" "light" } { "light" "250" "angle" "0" "origin" "416 -416 296" "classname" "light" } { "light" "250" "angle" "0" "origin" "416 -416 88" "classname" "light" } { "light" "250" "angle" "0" "origin" "-416 -416 88" "classname" "light" } { "light" "250" "angle" "0" "origin" "-416 -416 296" "classname" "light" } { "light" "250" "angle" "0" "origin" "-416 416 300" "classname" "light" } { "light" "250" "angle" "0" "origin" "-416 416 88" "classname" "light" } { "classname" "light_flame_small_white" "origin" "-504 -504 296" "light" "600" } { "classname" "light_flame_small_white" "origin" "-504 504 296" "light" "600" } { "classname" "light_flame_small_white" "origin" "504 -504 296" "light" "600" } { "classname" "light_flame_small_white" "origin" "0 -504 296" "light" "600" } { "classname" "light_flame_small_white" "origin" "0 -648 172" "light" "600" } { "classname" "light_flame_small_white" "origin" "-760 120 304" "light" "600" } { "classname" "light_flame_small_white" "origin" "760 120 304" "light" "600" } { "light" "250" "angle" "0" "origin" "0 -416 296" "classname" "light" } { "light" "250" "angle" "0" "origin" "0 -416 88" "classname" "light" } { "light" "200" "angle" "0" "origin" "-360 0 92" "classname" "light" } { "light" "200" "angle" "0" "origin" "360 0 92" "classname" "light" } { "light" "200" "angle" "0" "origin" "0 360 92" "classname" "light" } { "classname" "light_flame_small_white" "origin" "760 -760 304" "light" "600" } { "classname" "light_flame_small_white" "origin" "-760 -760 304" "light" "600" } { "light" "250" "angle" "0" "origin" "248 -420 160" "classname" "light" } { "light" "250" "angle" "0" "origin" "-248 -416 160" "classname" "light" } { "classname" "light" "origin" "0 0 632" "light" "500" "style" "0" } { "classname" "info_player_deathmatch" "origin" "0 -712 28" "angle" "90" } { "classname" "info_player_deathmatch" "origin" "-712 72 220" "angle" "313" } { "classname" "info_player_deathmatch" "origin" "712 72 220" "angle" "225" } { "classname" "info_player_deathmatch" "origin" "-456 -456 28" "angle" "45" } { "classname" "info_player_deathmatch" "origin" "456 456 28" "angle" "226" } { "classname" "info_player_deathmatch" "origin" "0 552 220" "angle" "270" } { "classname" "info_player_deathmatch" "origin" "-456 456 28" "angle" "314" } { "classname" "info_player_deathmatch" "origin" "456 -456 28" "angle" "136" } { "classname" "info_player_deathmatch" "origin" "0 0 220" "angle" "90" } { "classname" "weapon_supershotgun" "origin" "0 552 196" } { "classname" "weapon_nailgun" "origin" "252 424 0" } { "classname" "weapon_supernailgun" "origin" "0 -220 192" } { "classname" "weapon_grenadelauncher" "origin" "-244 424 0" } { "classname" "weapon_rocketlauncher" "origin" "-704 -696 192" } { "classname" "weapon_lightning" "origin" "704 -696 192" } { "classname" "item_shells" "origin" "408 236 0" } { "classname" "item_shells" "origin" "408 -268 0" } { "classname" "item_spikes" "origin" "-236 8 192" } { "classname" "item_spikes" "origin" "-236 -40 192" } { "classname" "item_rockets" "origin" "-656 84 192" } { "classname" "item_rockets" "origin" "-616 84 192" } { "classname" "item_rockets" "origin" "204 -40 192" } { "classname" "item_rockets" "origin" "204 8 192" } { "classname" "item_cells" "origin" "548 80 192" } { "classname" "item_cells" "origin" "588 80 192" } { "classname" "item_cells" "origin" "628 80 192" } { "classname" "item_cells" "origin" "-16 204 192" } { "classname" "item_health" "origin" "-440 236 0" } { "classname" "item_health" "origin" "-440 -268 0" } { "classname" "item_health" "origin" "-16 -440 0" } { "classname" "item_health" "origin" "-16 408 0" } { "classname" "item_health" "origin" "-720 -308 192" } { "classname" "item_health" "origin" "-16 -592 0" "spawnflags" "2" } { "classname" "item_artifact_super_damage" "origin" "0 -488 216" } { "classname" "item_armor1" "origin" "704 -488 192" } { "classname" "item_armor2" "origin" "-704 -488 192" } { "classname" "item_armorInv" "origin" "0 0 196" } { "classname" "item_health" "origin" "688 -308 192" } { "classname" "info_intermission" "origin" "-456 368 384" "mangle" "34 28 0" } { "classname" "weapon_rocketlauncher" "origin" "0 -216 0" } { "classname" "info_monster_start" "origin" "-3.375 562.625 218" } { "classname" "info_monster_start" "origin" "-0.375 623.875 216" } { "classname" "info_monster_start" "origin" "-80.75 553 216" } { "classname" "info_monster_start" "origin" "-39.875 286.625 216" } { "classname" "info_monster_start" "origin" "55.375 284.875 216" } { "classname" "info_monster_start" "origin" "68 347.625 24" } { "classname" "info_monster_start" "origin" "233.625 346.375 24" } { "classname" "info_monster_start" "origin" "383.875 392.125 24" } { "classname" "info_monster_start" "origin" "-366 80.875 24" } { "classname" "info_monster_start" "origin" "-368.625 -18.75 24" } { "classname" "info_monster_start" "origin" "-371.625 -130.625 24" } { "classname" "info_monster_start" "origin" "-374.125 -222.25 24" } { "classname" "info_monster_start" "origin" "-333.25 -353.125 24" } { "classname" "info_monster_start" "origin" "-174.375 -357.25 24" } { "classname" "info_monster_start" "origin" "-69.875 -359.875 24" } { "classname" "info_monster_start" "origin" "258.375 -368.25 24" } { "classname" "info_monster_start" "origin" "368.625 -341.375 24" } { "classname" "info_monster_start" "origin" "371.25 -217.25 24" } { "classname" "info_monster_start" "origin" "373.375 -112.375 24" } { "classname" "info_monster_start" "origin" "376 13.5 24" } { "classname" "info_monster_start" "origin" "378.5 131.375 24" } { "classname" "info_monster_start" "origin" "380.875 249.125 24" } { "classname" "info_monster_start" "origin" "154.625 283.125 216" } { "classname" "info_monster_start" "origin" "-122.75 288.125 216" } { "classname" "info_monster_start" "origin" "53.875 -274.875 216" } { "classname" "info_monster_start" "origin" "124.125 -278.125 216" } { "classname" "info_monster_start" "origin" "284.75 61 216" } { "classname" "info_monster_start" "origin" "699.125 -714.5 216" } { "classname" "info_monster_start" "origin" "-3.875 -477.375 216" } { "classname" "info_monster_start" "origin" "89 541.625 216" } { "classname" "info_monster_start" "origin" "8.375 483.875 216" } { "classname" "info_monster_start" "origin" "1.25 -92.375 216" } { "classname" "info_monster_start" "origin" "97.875 -103.625 216" } { "classname" "info_monster_start" "origin" "-7.125 -148.25 24" } { "classname" "info_monster_start" "origin" "53.5 158.25 24" } { "classname" "info_monster_start" "origin" "-163 -81.75 24" } { "classname" "info_monster_start" "origin" "-97.625 -145.25 24" } { "classname" "info_monster_start" "origin" "-127.125 -266.375 216" } { "classname" "info_monster_start" "origin" "-33.875 -270.75 216" } { "classname" "info_monster_start" "origin" "285.375 -281.25 216" } { "classname" "info_monster_start" "origin" "188.5 127.25 24" } { "classname" "info_monster_start" "origin" "154.875 163.625 24" } { "classname" "info_monster_start" "origin" "-89.375 -81.75 216" } { "classname" "info_monster_start" "origin" "-159.625 2 24" } { "classname" "info_monster_start" "origin" "-156.5 81.5 24" } { "classname" "info_monster_start" "origin" "-110.25 168.375 24" } { "classname" "info_monster_start" "origin" "-278 121.25 216" } { "classname" "info_monster_start" "origin" "-272.625 -292 216" } { "classname" "info_monster_start" "origin" "-279.125 -145.5 216" } { "classname" "info_monster_start" "origin" "102.375 101.25 216" } { "classname" "info_monster_start" "origin" "-85.75 130.625 216" } { "classname" "info_monster_start" "origin" "10.375 115.875 216" } { "classname" "info_monster_start" "origin" "-278.75 -64.625 216" } { "classname" "info_monster_start" "origin" "-278.375 29.375 216" } { "classname" "info_monster_start" "origin" "-89 5.375 216" } { "classname" "info_monster_start" "origin" "12.625 -1.875 218" } { "classname" "info_monster_start" "origin" "97.875 -0.125 216" } { "classname" "info_monster_start" "origin" "298.75 285.125 216" } { "classname" "info_monster_start" "origin" "285.375 141.625 216" } { "classname" "info_monster_start" "origin" "283.125 -138 216" } { "classname" "info_monster_start" "origin" "550.75 91.5 216" } { "classname" "info_monster_start" "origin" "723.375 74.5 218" } { "classname" "info_monster_start" "origin" "639.375 82.75 216" } { "classname" "info_monster_start" "origin" "632.875 16.875 216" } { "classname" "info_monster_start" "origin" "709.875 -64.875 216" } { "classname" "info_monster_start" "origin" "622.5 -89.5 216" } { "classname" "info_monster_start" "origin" "698.875 -167 216" } { "classname" "info_monster_start" "origin" "699 -241.125 216" } { "classname" "info_monster_start" "origin" "699 -311.375 216" } { "classname" "info_monster_start" "origin" "699 -379.375 216" } { "classname" "info_monster_start" "origin" "699 -458.75 216" } { "classname" "info_monster_start" "origin" "699.125 -527.875 216" } { "classname" "info_monster_start" "origin" "699.125 -586.625 216" } { "classname" "info_monster_start" "origin" "699.125 -662.75 216" } { "classname" "info_monster_start" "origin" "659.625 -714 216" } { "classname" "info_monster_start" "origin" "600.125 -713.25 216" } { "classname" "info_monster_start" "origin" "546.375 -712.5 216" } { "classname" "info_monster_start" "origin" "490.625 -711.875 200" } { "classname" "info_monster_start" "origin" "433.125 -711.125 184" } { "classname" "info_monster_start" "origin" "349.75 -710 152" } { "classname" "info_monster_start" "origin" "269 -709 120" } { "classname" "info_monster_start" "origin" "182.375 -707.875 88" } { "classname" "info_monster_start" "origin" "112.125 -707 56" } { "classname" "info_monster_start" "origin" "32.25 -706 26" } { "classname" "info_monster_start" "origin" "-2.25 -705.625 26" } { "classname" "info_monster_start" "origin" "-102.5 -695.125 56" } { "classname" "info_monster_start" "origin" "-170.375 -694.875 88" } { "classname" "info_monster_start" "origin" "-220.125 -694.75 104" } { "classname" "info_monster_start" "origin" "-297.125 -694.375 136" } { "classname" "info_monster_start" "origin" "-388.625 -694.125 168" } { "classname" "info_monster_start" "origin" "-462.625 -693.75 200" } { "classname" "info_monster_start" "origin" "-527 -693.5 216" } { "classname" "info_monster_start" "origin" "-575.5 -693.375 216" } { "classname" "info_monster_start" "origin" "-641.875 -693.125 216" } { "classname" "info_monster_start" "origin" "-706.75 -692.75 216" } { "classname" "info_monster_start" "origin" "-705 -603 216" } { "classname" "info_monster_start" "origin" "-703.375 -514.875 216" } { "classname" "info_monster_start" "origin" "-702 -441.125 216" } { "classname" "info_monster_start" "origin" "-700.25 -352.5 216" } { "classname" "info_monster_start" "origin" "-698.5 -258.5 216" } { "classname" "info_monster_start" "origin" "-696.875 -172.125 216" } { "classname" "info_monster_start" "origin" "-695.375 -92.875 216" } { "classname" "info_monster_start" "origin" "-694 -18.875 216" } { "classname" "info_monster_start" "origin" "-692 84.875 218" } { "classname" "info_monster_start" "origin" "-480.25 7.625 216" } { "classname" "info_monster_start" "origin" "-483.375 -81.25 216" } { "classname" "info_monster_start" "origin" "-577.625 -108.75 216" } { "classname" "info_monster_start" "origin" "-574.875 -28.5 216" } { "classname" "info_monster_start" "origin" "-571 81.125 216" } { "classname" "info_monster_start" "origin" "-477.875 77.875 216" } { "classname" "info_monster_start" "origin" "-297.625 294 216" } { "classname" "info_monster_start" "origin" "-363.25 182.375 24" } { "classname" "info_monster_start" "origin" "-360.25 296.125 24" } { "classname" "info_monster_start" "origin" "-270.625 392.375 24" } { "classname" "info_monster_start" "origin" "-162 378 24" } { "classname" "info_monster_start" "origin" "-44.125 362.375 24" } { "classname" "info_monster_start" "origin" "-32.625 172.5 24" } { "classname" "info_monster_start" "origin" "543 11.875 216" } { "classname" "info_monster_start" "origin" "533.875 -80.875 216" } { "classname" "info_monster_start" "origin" "283.75 -54.125 216" } { "classname" "info_monster_start" "origin" "186.625 35.25 24" } { "classname" "info_monster_start" "origin" "184.5 -70 24" } { "classname" "info_monster_start" "origin" "168.875 -154 24" } { "classname" "info_monster_start" "origin" "88.375 -151.375 24" } { "classname" "info_monster_start" "origin" "152.25 -365.625 24" } { "classname" "info_monster_start" "origin" "2.5 -584.125 24" } { "classname" "info_monster_start" "origin" "40.875 -362.75 24" } { "classname" "info_monster_start" "origin" "4.125 -464.375 24" } QW-Group-ktx-d05d6ca/resources/example-configs/ktx/000077500000000000000000000000001475442401000223315ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/000077500000000000000000000000001475442401000233005ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/000077500000000000000000000000001475442401000242405ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/2towers.bot000066400000000000000000000111171475442401000263540ustar00rootroot00000000000000CreateMarker 0 -816 248 CreateMarker 10 -753 280 CreateMarker -18 817 248 CreateMarker 3 746 280 CreateMarker -1 666 152 CreateMarker 229 675 152 CreateMarker -232 684 152 CreateMarker -230 347 152 CreateMarker -240 19 152 CreateMarker -233 -350 152 CreateMarker -226 -686 152 CreateMarker -19 -680 152 CreateMarker 240 -688 152 CreateMarker 234 -429 152 CreateMarker 225 -37 152 CreateMarker 225 370 152 CreateMarker 175 -599 24 CreateMarker -127 -610 24 CreateMarker -154 -405 24 CreateMarker 144 -385 24 CreateMarker -139 -192 -13 CreateMarker 86 -199 -11 CreateMarker -31 37 -40 CreateMarker -129 225 -2 CreateMarker 128 206 -8 CreateMarker 150 388 24 CreateMarker -138 386 24 CreateMarker -139 572 24 CreateMarker 95 586 24 CreateMarker -268 8 -40 CreateMarker -438 0 -40 CreateMarker -593 -1 -32 CreateMarker -796 4 56 CreateMarker 227 12 -40 CreateMarker 433 5 -40 CreateMarker 568 -2 -40 CreateMarker 802 -1 56 SetZone 1 8 SetMarkerPath 1 1 19 SetZone 2 7 SetMarkerPath 2 1 21 SetZone 3 10 SetMarkerPath 3 0 5 SetMarkerPath 3 1 4 SetZone 4 10 SetMarkerPath 4 0 3 SetMarkerPath 4 1 5 SetMarkerPath 4 2 6 SetMarkerPath 4 3 7 SetZone 5 10 SetMarkerPath 5 0 3 SetMarkerPath 5 1 4 SetZone 6 10 SetMarkerPath 6 0 4 SetMarkerPath 6 1 8 SetZone 7 10 SetMarkerPath 7 0 4 SetMarkerPath 7 1 9 SetZone 8 10 SetMarkerPath 8 0 6 SetMarkerPath 8 1 10 SetZone 9 10 SetMarkerPath 9 0 7 SetMarkerPath 9 1 10 SetZone 10 10 SetMarkerPath 10 0 9 SetMarkerPath 10 1 8 SetZone 11 5 SetMarkerPath 11 0 37 SetMarkerPath 11 1 39 SetMarkerPath 11 2 40 SetMarkerPath 11 3 38 SetMarkerPath 11 4 36 SetMarkerPath 11 5 35 SetZone 12 4 SetMarkerPath 12 0 45 SetMarkerPath 12 1 46 SetMarkerPath 12 2 47 SetMarkerPath 12 3 44 SetMarkerPath 12 4 43 SetMarkerPath 12 5 42 SetMarkerPath 12 6 41 SetZone 13 9 SetMarkerPath 13 1 26 SetMarkerPath 13 2 28 SetZone 14 9 SetMarkerPath 14 1 32 SetMarkerPath 14 2 34 SetZone 15 1 SetMarkerPath 15 1 2 SetZone 16 1 SetMarkerPath 16 1 13 SetZone 17 2 SetMarkerPath 17 0 1 SetMarkerPath 17 1 19 SetZone 18 2 SetMarkerPath 18 1 14 SetZone 19 8 SetMarkerPath 19 1 1 SetMarkerPath 19 2 20 SetMarkerPathFlags 19 2 j SetZone 20 8 SetMarkerPath 20 1 30 SetZone 21 7 SetMarkerPath 21 1 2 SetMarkerPath 21 2 22 SetMarkerPathFlags 21 2 j SetZone 22 7 SetMarkerPath 22 1 23 SetMarkerPathFlags 22 1 j SetZone 23 6 SetMarkerPath 23 1 24 SetMarkerPath 23 2 25 SetZone 24 6 SetMarkerPath 24 1 23 SetMarkerPath 24 2 34 SetZone 25 6 SetMarkerPath 25 1 23 SetMarkerPath 25 2 26 SetZone 26 6 SetMarkerPath 26 1 27 SetMarkerPath 26 2 25 SetZone 27 6 SetMarkerPath 27 1 28 SetMarkerPath 27 2 26 SetMarkerPath 27 3 41 SetZone 28 6 SetMarkerPath 28 1 29 SetMarkerPath 28 2 27 SetZone 29 6 SetMarkerPath 29 1 30 SetMarkerPath 29 2 28 SetZone 30 6 SetMarkerPath 30 1 31 SetMarkerPath 30 2 29 SetZone 31 6 SetMarkerPath 31 1 32 SetMarkerPath 31 2 30 SetZone 32 6 SetMarkerPath 32 1 33 SetMarkerPath 32 2 31 SetZone 33 6 SetMarkerPath 33 1 34 SetMarkerPath 33 2 32 SetMarkerPath 33 3 41 SetZone 34 6 SetMarkerPath 34 1 24 SetMarkerPath 34 2 33 SetZone 35 5 SetMarkerPath 35 0 11 SetMarkerPath 35 1 36 SetMarkerPath 35 2 38 SetZone 36 5 SetMarkerPath 36 0 11 SetMarkerPath 36 1 37 SetMarkerPath 36 2 35 SetZone 37 5 SetMarkerPath 37 0 11 SetMarkerPath 37 1 39 SetMarkerPath 37 2 36 SetZone 38 5 SetMarkerPath 38 0 11 SetMarkerPath 38 1 35 SetMarkerPath 38 2 40 SetZone 39 3 SetMarkerPath 39 0 11 SetMarkerPath 39 1 41 SetMarkerPath 39 2 37 SetMarkerPath 39 3 40 SetZone 40 3 SetMarkerPath 40 0 11 SetMarkerPath 40 1 41 SetMarkerPath 40 2 38 SetMarkerPath 40 3 39 SetZone 41 3 SetMarkerPath 41 0 12 SetMarkerPath 41 1 42 SetMarkerPath 41 2 43 SetMarkerPath 41 3 52 SetMarkerPath 41 4 39 SetMarkerPath 41 5 48 SetMarkerPath 41 6 40 SetZone 42 3 SetMarkerPath 42 0 12 SetMarkerPath 42 1 41 SetMarkerPath 42 2 45 SetZone 43 3 SetMarkerPath 43 0 12 SetMarkerPath 43 1 41 SetMarkerPath 43 2 44 SetZone 44 4 SetMarkerPath 44 0 12 SetMarkerPath 44 1 47 SetMarkerPath 44 2 43 SetZone 45 4 SetMarkerPath 45 0 12 SetMarkerPath 45 1 42 SetMarkerPath 45 2 46 SetZone 46 4 SetMarkerPath 46 0 12 SetMarkerPath 46 1 45 SetMarkerPath 46 2 47 SetZone 47 4 SetMarkerPath 47 0 12 SetMarkerPath 47 1 44 SetMarkerPath 47 2 46 SetZone 48 2 SetMarkerPath 48 1 41 SetMarkerPath 48 2 49 SetZone 49 2 SetMarkerPath 49 1 48 SetMarkerPath 49 2 50 SetZone 50 2 SetMarkerPath 50 1 49 SetMarkerPath 50 2 51 SetZone 51 2 SetMarkerPath 51 1 50 SetMarkerPath 51 2 18 SetMarkerPath 51 3 17 SetZone 52 1 SetMarkerPath 52 1 41 SetMarkerPath 52 2 53 SetZone 53 1 SetMarkerPath 53 1 52 SetMarkerPath 53 2 54 SetZone 54 1 SetMarkerPath 54 1 53 SetMarkerPath 54 2 55 SetZone 55 1 SetMarkerPath 55 1 54 SetMarkerPath 55 2 15 SetMarkerPath 55 3 16 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/aerowalk.bot000066400000000000000000000276771475442401000265760ustar00rootroot00000000000000CreateMarker 129 6 248 CreateMarker -321 -102 24 CreateMarker -315 -212 24 CreateMarker -394 -219 69 CreateMarker -500 -223 122 CreateMarker -593 -229 152 CreateMarker -680 -234 152 CreateMarker -678 -379 152 CreateMarker -643 -640 152 CreateMarker -541 -669 200 CreateMarker -420 -666 248 CreateMarker -424 -836 248 CreateMarker -581 -838 248 CreateMarker -873 -838 248 CreateMarker -877 -695 296 CreateMarker -879 -592 360 CreateMarker -882 -441 424 CreateMarker -823 -376 440 CreateMarker -662 -348 440 CreateMarker -727 -448 440 CreateMarker -639 -660 440 CreateMarker -457 -665 440 CreateMarker -289 -658 440 CreateMarker -131 -400 440 CreateMarker 131 -230 440 CreateMarker 129 -335 440 CreateMarker 264 -251 440 CreateMarker 271 165 440 CreateMarker -328 483 248 CreateMarker -188 488 284 CreateMarker -90 479 328 CreateMarker 19 482 392 CreateMarker 204 442 444 CreateMarker 224 306 440 CreateMarker -251 -443 440 CreateMarker -658 -464 440 CreateMarker -297 -668 248 CreateMarker -264 -478 252 CreateMarker -38 -345 440 CreateMarker -674 87 152 CreateMarker -674 227 216 CreateMarker -676 351 248 CreateMarker -622 483 248 CreateMarker -171 -282 248 CreateMarker -69 -261 248 CreateMarker -86 99 248 CreateMarker -321 346 248 CreateMarker -106 23 252 CreateMarker -322 108 248 CreateMarker -125 -198 248 SetZone 1 2 SetMarkerPath 1 0 94 SetMarkerPath 1 1 93 SetMarkerPath 1 2 53 SetMarkerPath 1 3 25 SetMarkerPath 1 4 46 SetGoal 2 5 SetZone 2 6 SetMarkerPath 2 0 80 SetZone 3 6 SetMarkerPath 3 0 74 SetZone 4 6 SetMarkerPath 4 0 74 SetZone 5 3 SetMarkerPath 5 0 8 SetZone 6 3 SetMarkerPath 6 0 17 SetMarkerPath 6 1 5 SetMarkerPath 6 2 51 SetMarkerPath 6 3 52 SetMarkerPathFlags 6 3 j SetZone 7 5 SetMarkerPath 7 0 6 SetZone 8 5 SetMarkerPath 8 0 7 SetMarkerPath 8 1 43 SetZone 9 1 SetMarkerPath 9 0 11 SetMarkerPath 9 1 28 SetZone 10 1 SetMarkerPath 10 0 9 SetMarkerPath 10 1 45 SetMarkerPath 10 2 51 SetMarkerPath 10 3 27 SetMarkerPath 10 4 28 SetZone 11 3 SetMarkerPath 11 0 62 SetMarkerPath 11 1 15 SetMarkerPath 11 2 71 SetZone 12 1 SetMarkerPath 12 0 1 SetGoal 13 6 SetZone 13 4 SetMarkerPath 13 0 21 SetMarkerPath 13 1 22 SetMarkerPath 13 2 83 SetGoal 14 7 SetZone 14 1 SetMarkerPath 14 0 56 SetMarkerPath 14 1 89 SetMarkerPath 14 2 28 SetMarkerPath 14 3 9 SetMarkerPath 14 4 51 SetMarkerPathFlags 14 4 j SetMarkerPath 14 5 55 SetMarkerPath 14 6 27 SetMarkerPathFlags 14 6 j SetGoal 15 8 SetZone 15 2 SetMarkerPath 15 0 63 SetMarkerPath 15 1 62 SetMarkerPath 15 2 70 SetMarkerPathFlags 15 2 r SetRocketJumpPathFields 15 2 78.3 -1.0 0 SetGoal 16 9 SetZone 16 5 SetMarkerPath 16 0 91 SetMarkerPath 16 1 92 SetGoal 17 20 SetZone 17 3 SetMarkerPath 17 0 23 SetMarkerPath 17 1 5 SetMarkerPath 17 2 6 SetMarkerPath 17 3 9 SetMarkerPath 17 4 88 SetMarkerPathFlags 17 4 r SetRocketJumpPathFields 17 4 35.0 155.0 0 SetMarkerPath 17 5 45 SetMarkerPathFlags 17 5 j SetMarkerPath 17 6 51 SetMarkerPathFlags 17 6 j SetMarkerPath 17 7 33 SetMarkerPathFlags 17 7 j SetZone 18 2 SetMarkerPath 18 0 47 SetMarkerPath 18 1 86 SetMarkerPath 18 2 87 SetGoal 19 10 SetZone 19 5 SetMarkerPath 19 0 43 SetZone 20 5 SetMarkerViewOfs 20 30 SetMarkerFlag 20 n SetMarkerPath 20 0 19 SetMarkerPath 20 1 43 SetGoal 21 19 SetZone 21 4 SetMarkerPath 21 0 82 SetMarkerPath 21 1 83 SetMarkerPath 21 2 13 SetGoal 22 19 SetZone 22 4 SetMarkerPath 22 0 77 SetMarkerPath 22 1 13 SetMarkerPath 22 2 83 SetMarkerPath 22 3 42 SetMarkerPath 22 4 38 SetGoal 23 3 SetZone 23 3 SetMarkerPath 23 0 24 SetMarkerPath 23 1 17 SetMarkerPath 23 2 51 SetGoal 24 3 SetZone 24 3 SetMarkerPath 24 0 68 SetMarkerPath 24 1 23 SetMarkerPath 24 2 54 SetMarkerPath 24 3 25 SetGoal 25 20 SetZone 25 1 SetMarkerPath 25 0 12 SetMarkerPath 25 1 35 SetMarkerPath 25 2 44 SetMarkerPath 25 3 51 SetMarkerPath 25 4 52 SetZone 26 3 SetMarkerPath 26 0 72 SetMarkerPath 26 1 31 SetGoal 27 2 SetZone 27 1 SetMarkerPath 27 0 9 SetMarkerPath 27 1 28 SetMarkerPath 27 2 45 SetMarkerPath 27 3 51 SetMarkerPath 27 4 35 SetGoal 28 2 SetZone 28 1 SetMarkerPath 28 0 27 SetMarkerPath 28 1 51 SetMarkerPath 28 2 45 SetMarkerPath 28 3 9 SetGoal 29 11 SetZone 29 3 SetMarkerPath 29 0 84 SetMarkerPath 29 1 30 SetMarkerPath 29 2 73 SetMarkerPath 29 4 51 SetMarkerPathFlags 29 4 j SetGoal 30 23 SetZone 30 3 SetMarkerPath 30 0 29 SetMarkerPath 30 1 84 SetMarkerPath 30 2 31 SetGoal 31 23 SetZone 31 3 SetMarkerPath 31 0 30 SetMarkerPath 31 1 72 SetMarkerPath 31 2 26 SetGoal 32 19 SetZone 32 5 SetMarkerPath 32 0 96 SetMarkerPath 32 1 33 SetMarkerPath 32 2 25 SetMarkerPath 32 3 9 SetMarkerPath 32 4 51 SetMarkerPathFlags 32 4 j SetMarkerPath 32 5 28 SetMarkerPathFlags 32 5 j SetGoal 33 19 SetZone 33 5 SetMarkerPath 33 0 32 SetMarkerPath 33 1 95 SetMarkerPath 33 2 25 SetMarkerPathFlags 33 2 j SetMarkerPath 33 3 28 SetMarkerPathFlags 33 3 j SetGoal 34 12 SetZone 34 2 SetMarkerPath 34 0 58 SetMarkerPath 34 1 57 SetZone 35 1 SetMarkerPath 35 0 25 SetMarkerPath 35 1 44 SetMarkerPath 35 2 45 SetMarkerPath 35 3 51 SetMarkerPath 35 4 52 SetMarkerPath 35 5 27 SetZone 36 6 SetMarkerPath 36 0 74 SetGoal 37 23 SetZone 37 5 SetMarkerPath 37 0 50 SetMarkerPath 37 1 42 SetGoal 38 23 SetZone 38 5 SetMarkerPath 38 0 95 SetMarkerPath 38 1 50 SetMarkerPath 38 2 42 SetMarkerPath 38 3 77 SetMarkerPathFlags 38 3 r SetRocketJumpPathFields 38 3 75.0 181.0 0 SetGoal 39 13 SetZone 39 2 SetMarkerPath 39 0 61 SetMarkerPath 39 1 47 SetGoal 40 14 SetZone 40 3 SetMarkerPath 40 0 75 SetMarkerPath 40 1 88 SetMarkerPath 40 2 73 SetMarkerPath 40 3 95 SetMarkerPathFlags 40 3 j SetMarkerPath 40 4 25 SetMarkerPath 40 5 53 SetMarkerPath 40 6 93 SetMarkerPathFlags 40 6 j SetZone 41 6 SetMarkerViewOfs 41 30 SetMarkerPath 41 0 80 SetMarkerPath 41 1 2 SetZone 42 5 SetMarkerPath 42 0 50 SetMarkerPath 42 1 37 SetMarkerPath 42 2 38 SetGoal 43 15 SetZone 43 5 SetMarkerPath 43 0 92 SetMarkerPath 43 1 19 SetMarkerPath 43 2 7 SetMarkerPath 43 3 8 SetMarkerPath 43 4 78 SetGoal 44 1 SetZone 44 1 SetMarkerPath 44 0 25 SetMarkerPath 44 1 35 SetMarkerPath 44 2 45 SetGoal 45 1 SetZone 45 1 SetMarkerPath 45 0 35 SetMarkerPath 45 1 44 SetMarkerPath 45 2 9 SetMarkerPath 45 3 28 SetMarkerPath 45 4 27 SetGoal 46 16 SetZone 46 2 SetMarkerPath 46 0 87 SetMarkerPath 46 1 93 SetMarkerPath 46 2 52 SetMarkerPath 46 3 9 SetMarkerPath 46 4 25 SetMarkerPath 46 5 94 SetMarkerPath 46 6 1 SetGoal 47 17 SetZone 47 2 SetMarkerPath 47 0 39 SetMarkerPath 47 1 18 SetGoal 48 4 SetZone 48 4 SetMarkerPath 48 0 76 SetMarkerPath 48 1 49 SetGoal 49 4 SetZone 49 4 SetMarkerPath 49 0 48 SetMarkerPath 49 1 77 SetZone 50 5 SetMarkerPath 50 0 74 SetMarkerPath 50 1 38 SetMarkerPath 50 2 37 SetMarkerPath 50 3 42 SetZone 51 1 SetMarkerPath 51 0 25 SetMarkerPath 51 1 35 SetMarkerPath 51 2 9 SetMarkerPath 51 3 28 SetMarkerPath 51 4 27 SetMarkerPath 51 5 52 SetMarkerPath 51 6 46 SetMarkerPathFlags 51 6 r SetRocketJumpPathFields 51 6 75.0 100.0 0 SetMarkerPath 51 7 32 SetMarkerPathFlags 51 7 r SetRocketJumpPathFields 51 7 72.0 270.0 0 SetZone 52 1 SetMarkerPath 52 0 25 SetMarkerPath 52 1 35 SetMarkerPath 52 2 53 SetMarkerPath 52 3 51 SetZone 53 1 SetMarkerPath 53 0 52 SetMarkerPath 53 1 54 SetZone 54 1 SetMarkerPath 54 0 53 SetMarkerPath 54 1 55 SetZone 55 1 SetMarkerPath 55 0 54 SetMarkerPath 55 1 56 SetMarkerPath 55 2 14 SetMarkerPath 55 3 28 SetMarkerPathFlags 55 3 j SetZone 56 1 SetMarkerPath 56 0 55 SetMarkerPath 56 1 14 SetMarkerPath 56 2 57 SetMarkerPath 56 3 27 SetMarkerPathFlags 56 3 j SetMarkerPath 56 4 32 SetMarkerPathFlags 56 4 r SetRocketJumpPathFields 56 4 50.0 225.0 0 SetZone 57 2 SetMarkerPath 57 0 34 SetMarkerPath 57 1 56 SetZone 58 2 SetMarkerPath 58 0 59 SetMarkerPath 58 1 34 SetZone 59 2 SetMarkerPath 59 0 60 SetMarkerPath 59 1 58 SetZone 60 2 SetMarkerPath 60 0 61 SetMarkerPath 60 1 86 SetMarkerPath 60 2 59 SetMarkerPath 60 3 58 SetMarkerPathFlags 60 3 j SetZone 61 2 SetMarkerPath 61 0 62 SetMarkerPath 61 1 60 SetMarkerPath 61 2 39 SetZone 62 2 SetMarkerPath 62 0 15 SetMarkerPath 62 1 61 SetMarkerPath 62 2 71 SetMarkerPathFlags 62 2 r SetRocketJumpPathFields 62 2 78.3 -1.0 0 SetZone 63 2 SetMarkerPath 63 0 64 SetMarkerPath 63 1 15 SetZone 64 2 SetMarkerPath 64 0 65 SetMarkerPath 64 1 63 SetZone 65 2 SetMarkerPath 65 0 66 SetMarkerPath 65 1 64 SetZone 66 3 SetMarkerPath 66 0 67 SetMarkerPath 66 1 65 SetMarkerPath 66 2 63 SetMarkerPathFlags 66 2 j SetZone 67 3 SetMarkerPath 67 0 69 SetMarkerPath 67 1 66 SetMarkerPath 67 2 68 SetMarkerPath 67 3 63 SetMarkerPathFlags 67 3 j SetZone 68 3 SetMarkerPath 68 0 69 SetMarkerPath 68 1 67 SetMarkerPath 68 2 85 SetMarkerPath 68 3 24 SetZone 69 3 SetMarkerPath 69 0 85 SetMarkerPath 69 1 67 SetMarkerPath 69 2 68 SetMarkerPath 69 3 70 SetMarkerPath 69 4 15 SetMarkerPathFlags 69 4 j SetZone 70 3 SetMarkerPath 70 0 71 SetMarkerPath 70 1 85 SetMarkerPath 70 2 69 SetMarkerPath 70 3 15 SetMarkerPath 70 4 61 SetMarkerPath 70 5 63 SetMarkerPathFlags 70 5 j SetMarkerPath 70 6 62 SetMarkerPathFlags 70 6 j SetZone 71 3 SetMarkerPath 71 0 72 SetMarkerPath 71 1 70 SetMarkerPath 71 2 61 SetMarkerPathFlags 71 2 j SetMarkerPath 71 3 15 SetMarkerPathFlags 71 3 j SetZone 72 3 SetMarkerPath 72 0 31 SetMarkerPath 72 1 26 SetMarkerPath 72 2 71 SetMarkerPath 72 3 84 SetMarkerPath 72 4 62 SetMarkerPathFlags 72 4 j SetZone 73 3 SetMarkerPath 73 0 88 SetMarkerPath 73 1 40 SetMarkerPath 73 2 29 SetMarkerPath 73 3 84 SetMarkerPath 73 4 93 SetMarkerPathFlags 73 4 j SetMarkerPath 73 5 51 SetZone 74 4 SetMarkerPath 74 0 75 SetMarkerPath 74 1 76 SetZone 75 4 SetMarkerPath 75 0 74 SetMarkerPath 75 1 76 SetMarkerPath 75 2 40 SetMarkerPath 75 3 88 SetZone 76 4 SetMarkerPath 76 0 74 SetMarkerPath 76 1 75 SetMarkerPath 76 2 48 SetZone 77 4 SetMarkerPath 77 0 49 SetMarkerPath 77 1 22 SetMarkerPath 77 2 83 SetZone 78 5 SetMarkerPath 78 0 43 SetMarkerPath 78 1 96 SetMarkerPath 78 2 79 SetZone 79 4 SetMarkerPath 79 0 78 SetMarkerPath 79 1 80 SetMarkerPath 79 2 2 SetMarkerPathFlags 79 2 r SetRocketJumpPathFields 79 2 0.0 0.0 0 SetZone 80 4 SetMarkerPath 80 0 81 SetMarkerPath 80 1 79 SetZone 81 4 SetMarkerPath 81 0 80 SetMarkerPath 81 1 82 SetZone 82 4 SetMarkerPath 82 0 83 SetMarkerPath 82 1 81 SetMarkerPath 82 2 21 SetMarkerPath 82 3 2 SetMarkerPathFlags 82 3 r SetRocketJumpPathFields 82 3 35.0 350.0 0 SetZone 83 4 SetMarkerPath 83 0 77 SetMarkerPath 83 1 82 SetMarkerPath 83 2 21 SetMarkerPath 83 3 13 SetMarkerPath 83 4 22 SetZone 84 3 SetMarkerPath 84 0 73 SetMarkerPath 84 1 29 SetMarkerPath 84 2 30 SetMarkerPath 84 3 72 SetZone 85 3 SetMarkerPath 85 0 70 SetMarkerPath 85 1 69 SetMarkerPath 85 2 68 SetZone 86 2 SetMarkerPath 86 0 18 SetMarkerPath 86 1 60 SetMarkerPath 86 2 87 SetZone 87 2 SetMarkerPath 87 0 86 SetMarkerPath 87 1 46 SetMarkerPath 87 2 18 SetZone 88 3 SetMarkerPath 88 0 75 SetMarkerPath 88 1 40 SetMarkerPath 88 2 73 SetMarkerPath 88 3 93 SetZone 89 1 SetMarkerPath 89 0 14 SetMarkerPath 89 1 90 SetMarkerPath 89 2 28 SetMarkerPathFlags 89 2 j SetZone 90 5 SetMarkerPath 90 0 89 SetMarkerPath 90 1 91 SetZone 91 5 SetMarkerPath 91 0 90 SetMarkerPath 91 1 16 SetMarkerPath 91 2 92 SetZone 92 5 SetMarkerPath 92 0 91 SetMarkerPath 92 1 16 SetMarkerPath 92 2 43 SetZone 93 2 SetMarkerPath 93 0 46 SetMarkerPath 93 1 94 SetMarkerPath 93 2 1 SetMarkerPath 93 3 53 SetMarkerPath 93 4 25 SetMarkerPath 93 5 9 SetMarkerPath 93 7 99 SetZone 94 2 SetMarkerPath 94 0 93 SetMarkerPath 94 1 1 SetMarkerPath 94 2 98 SetMarkerPath 94 3 12 SetMarkerPath 94 4 25 SetMarkerPath 94 5 51 SetMarkerPath 94 6 46 SetMarkerPath 94 7 99 SetZone 95 5 SetMarkerPath 95 0 33 SetMarkerPath 95 1 38 SetMarkerPath 95 3 12 SetMarkerPath 95 4 25 SetMarkerPathFlags 95 4 j SetMarkerPath 95 5 52 SetMarkerPath 95 6 28 SetMarkerPathFlags 95 6 j SetMarkerPath 95 7 98 SetZone 96 5 SetMarkerPath 96 0 78 SetMarkerPath 96 1 32 SetZone 97 5 SetMarkerPath 97 0 95 SetMarkerPath 97 1 94 SetMarkerPath 97 2 40 SetMarkerPathFlags 97 2 r SetRocketJumpPathFields 97 2 68.0 90.0 0 SetMarkerPath 97 3 99 SetZone 98 5 SetMarkerPath 98 0 32 SetMarkerPath 98 1 33 SetMarkerPath 98 2 28 SetMarkerPath 98 3 45 SetMarkerPath 98 4 14 SetMarkerPath 98 5 95 SetMarkerPath 98 6 29 SetMarkerPathFlags 98 6 r SetRocketJumpPathFields 98 6 73.0 93.0 0 SetMarkerPath 98 7 10 SetZone 99 2 SetMarkerPath 99 0 94 SetMarkerPath 99 1 93 SetMarkerPath 99 2 51 SetMarkerPath 99 3 97 SetMarkerPath 99 4 53 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/amphi2.bot000066400000000000000000000157631475442401000261420ustar00rootroot00000000000000CreateMarker -18 -355 -344 CreateMarker -259 -235 -344 CreateMarker -358 10 -344 CreateMarker -232 260 -344 CreateMarker 18 350 -344 CreateMarker 259 238 -344 CreateMarker 354 -13 -344 CreateMarker 4 4 -344 CreateMarker 189 -73 -344 CreateMarker -182 77 -344 CreateMarker 85 179 -344 CreateMarker -85 -182 -344 CreateMarker -69 190 -344 CreateMarker 72 -187 -344 CreateMarker 202 75 -344 CreateMarker -203 -79 -344 CreateMarker 635 -655 -360 CreateMarker 514 -524 -360 CreateMarker -41 -517 -360 CreateMarker -672 -660 -360 CreateMarker -454 -596 -360 CreateMarker -612 -427 -360 CreateMarker -389 -369 -360 CreateMarker 227 -628 -360 CreateMarker 167 -460 -360 CreateMarker -193 -448 -360 CreateMarker -277 -639 -360 CreateMarker -511 21 -360 CreateMarker -467 -164 -360 CreateMarker -603 -200 -360 CreateMarker -655 662 -360 CreateMarker -587 442 -360 CreateMarker -429 591 -360 CreateMarker -359 381 -360 CreateMarker 14 519 -360 CreateMarker -165 454 -360 CreateMarker -211 582 -360 CreateMarker -438 200 -360 CreateMarker -572 265 -360 CreateMarker 646 667 -360 CreateMarker 488 560 -360 CreateMarker 379 344 -360 CreateMarker 735 506 -360 CreateMarker 609 365 -360 CreateMarker 515 -18 -360 CreateMarker 436 158 -360 CreateMarker 585 210 -360 CreateMarker 451 -194 -360 CreateMarker 636 -276 -360 CreateMarker 668 -407 -360 CreateMarker 392 -671 -360 CreateMarker 395 -406 -360 CreateMarker 467 -329 -360 CreateMarker 316 -472 -360 CreateMarker 661 -18 -360 CreateMarker -58 -654 -360 CreateMarker -675 36 -360 CreateMarker 15 681 -360 CreateMarker 210 444 -360 CreateMarker 290 614 -360 CreateMarker 349 752 -360 CreateMarker -343 -752 -360 CreateMarker -752 -247 -360 CreateMarker -752 359 -360 CreateMarker -275 752 -360 CreateMarker 752 261 -360 SetZone 1 4 SetMarkerPath 1 0 9 SetZone 2 2 SetMarkerPath 2 0 6 SetMarkerPath 2 1 12 SetMarkerPath 2 2 19 SetMarkerPath 2 3 14 SetZone 3 3 SetMarkerPath 3 0 7 SetZone 4 5 SetMarkerPath 4 0 11 SetZone 6 2 SetMarkerPath 6 0 2 SetMarkerPath 6 1 7 SetMarkerPath 6 2 19 SetMarkerPath 6 3 17 SetZone 7 3 SetMarkerPath 7 0 6 SetMarkerPath 7 1 8 SetMarkerPath 7 2 17 SetMarkerPath 7 3 21 SetZone 8 3 SetMarkerPath 8 0 7 SetMarkerPath 8 1 9 SetMarkerPath 8 2 21 SetMarkerPath 8 3 15 SetZone 9 4 SetMarkerPath 9 0 8 SetMarkerPath 9 1 10 SetMarkerPath 9 2 15 SetMarkerPath 9 3 18 SetZone 10 5 SetMarkerPath 10 0 9 SetMarkerPath 10 1 11 SetMarkerPath 10 2 18 SetMarkerPath 10 3 16 SetZone 11 5 SetMarkerPath 11 0 10 SetMarkerPath 11 1 12 SetMarkerPath 11 2 16 SetMarkerPath 11 3 20 SetZone 12 2 SetMarkerPath 12 0 11 SetMarkerPath 12 1 2 SetMarkerPath 12 2 20 SetMarkerPath 12 3 14 SetZone 13 1 SetMarkerPath 13 0 19 SetMarkerPath 13 1 17 SetMarkerPath 13 2 21 SetMarkerPath 13 3 15 SetMarkerPath 13 4 18 SetMarkerPath 13 5 16 SetMarkerPath 13 6 20 SetMarkerPath 13 7 14 SetZone 14 2 SetMarkerPath 14 0 13 SetMarkerPath 14 1 19 SetMarkerPath 14 2 20 SetMarkerPath 14 3 2 SetMarkerPath 14 4 12 SetZone 15 4 SetMarkerPath 15 0 13 SetMarkerPath 15 1 21 SetMarkerPath 15 2 18 SetMarkerPath 15 3 8 SetMarkerPath 15 4 9 SetZone 16 5 SetMarkerPath 16 0 13 SetMarkerPath 16 1 18 SetMarkerPath 16 2 20 SetMarkerPath 16 3 10 SetMarkerPath 16 4 11 SetZone 17 3 SetMarkerPath 17 0 13 SetMarkerPath 17 1 19 SetMarkerPath 17 2 21 SetMarkerPath 17 3 6 SetMarkerPath 17 4 7 SetZone 18 4 SetMarkerPath 18 0 13 SetMarkerPath 18 1 15 SetMarkerPath 18 2 16 SetMarkerPath 18 3 9 SetMarkerPath 18 4 10 SetZone 19 2 SetMarkerPath 19 0 13 SetMarkerPath 19 1 14 SetMarkerPath 19 2 17 SetMarkerPath 19 3 2 SetMarkerPath 19 4 6 SetZone 20 5 SetMarkerPath 20 0 13 SetMarkerPath 20 1 16 SetMarkerPath 20 2 14 SetMarkerPath 20 3 11 SetMarkerPath 20 4 12 SetZone 21 3 SetMarkerPath 21 0 13 SetMarkerPath 21 1 17 SetMarkerPath 21 2 15 SetMarkerPath 21 3 7 SetMarkerPath 21 4 8 SetZone 22 6 SetMarkerPath 22 0 23 SetMarkerPath 22 1 2 SetMarkerPathFlags 22 1 r SetRocketJumpPathFields 22 1 78.3 -1.0 0 SetZone 23 6 SetMarkerPath 23 0 57 SetZone 24 6 SetMarkerPath 24 0 6 SetZone 25 7 SetMarkerPath 25 0 26 SetMarkerPath 25 1 27 SetMarkerPath 25 2 7 SetMarkerPathFlags 25 2 r SetRocketJumpPathFields 25 2 78.3 -1.0 0 SetZone 26 7 SetMarkerPath 26 0 28 SetZone 27 7 SetMarkerPath 27 0 28 SetZone 28 7 SetMarkerPath 28 0 7 SetZone 29 6 SetMarkerPath 29 0 30 SetZone 30 6 SetMarkerPath 30 0 6 SetMarkerPath 30 1 2 SetZone 31 7 SetMarkerPath 31 0 7 SetMarkerPath 31 1 6 SetZone 32 7 SetMarkerPath 32 0 31 SetZone 33 8 SetMarkerPath 33 0 8 SetZone 34 7 SetMarkerPath 34 0 8 SetMarkerPath 34 1 7 SetZone 35 7 SetMarkerPath 35 0 34 SetZone 36 8 SetMarkerPath 36 0 37 SetMarkerPath 36 1 38 SetMarkerPath 36 2 9 SetMarkerPathFlags 36 2 r SetRocketJumpPathFields 36 2 78.3 -1.0 0 SetZone 37 8 SetMarkerPath 37 0 39 SetZone 38 8 SetMarkerPath 38 0 39 SetZone 39 8 SetMarkerPath 39 0 9 SetZone 40 8 SetMarkerPath 40 0 10 SetZone 41 8 SetMarkerPath 41 0 10 SetMarkerPath 41 1 9 SetZone 42 8 SetMarkerPath 42 0 41 SetZone 43 8 SetMarkerPath 43 0 9 SetMarkerPath 43 1 8 SetZone 44 8 SetMarkerPath 44 0 43 SetZone 45 9 SetMarkerPath 45 0 46 SetMarkerPath 45 1 11 SetMarkerPathFlags 45 1 r SetRocketJumpPathFields 45 1 78.3 -1.0 0 SetZone 46 9 SetMarkerPath 46 0 47 SetZone 47 9 SetMarkerPath 47 0 11 SetZone 48 9 SetMarkerPath 48 0 49 SetZone 49 9 SetMarkerPath 49 0 47 SetZone 50 6 SetMarkerPath 50 0 12 SetZone 51 9 SetMarkerPath 51 0 12 SetMarkerPath 51 1 11 SetZone 52 9 SetMarkerPath 52 0 51 SetZone 53 6 SetMarkerPath 53 0 2 SetMarkerPath 53 1 12 SetZone 54 6 SetMarkerPath 54 0 53 SetZone 55 6 SetMarkerPath 55 0 58 SetZone 56 6 SetMarkerPath 56 0 59 SetZone 57 6 SetMarkerPath 57 0 2 SetZone 58 6 SetMarkerPath 58 0 2 SetZone 59 6 SetMarkerPath 59 0 2 SetZone 60 6 SetMarkerPath 60 0 50 SetMarkerPath 60 1 12 SetMarkerPathFlags 60 1 r SetRocketJumpPathFields 60 1 78.3 -1.0 0 SetMarkerPath 60 2 2 SetMarkerPathFlags 60 2 r SetRocketJumpPathFields 60 2 78.3 -1.0 0 SetMarkerPath 60 3 11 SetMarkerPathFlags 60 3 r SetRocketJumpPathFields 60 3 78.3 -1.0 0 SetZone 61 6 SetMarkerPath 61 0 24 SetMarkerPath 61 1 7 SetMarkerPathFlags 61 1 r SetRocketJumpPathFields 61 1 78.3 -1.0 0 SetMarkerPath 61 2 6 SetMarkerPathFlags 61 2 r SetRocketJumpPathFields 61 2 78.3 -1.0 0 SetMarkerPath 61 3 2 SetMarkerPathFlags 61 3 r SetRocketJumpPathFields 61 3 78.3 -1.0 0 SetZone 62 8 SetMarkerPath 62 0 33 SetMarkerPath 62 1 8 SetMarkerPathFlags 62 1 r SetRocketJumpPathFields 62 1 78.3 -1.0 0 SetMarkerPath 62 2 9 SetMarkerPathFlags 62 2 r SetRocketJumpPathFields 62 2 78.3 -1.0 0 SetMarkerPath 62 3 7 SetMarkerPathFlags 62 3 r SetRocketJumpPathFields 62 3 78.3 -1.0 0 SetZone 63 8 SetMarkerPath 63 0 40 SetMarkerPath 63 1 10 SetMarkerPathFlags 63 1 r SetRocketJumpPathFields 63 1 78.3 -1.0 0 SetMarkerPath 63 2 11 SetMarkerPathFlags 63 2 r SetRocketJumpPathFields 63 2 78.3 -1.0 0 SetMarkerPath 63 3 9 SetMarkerPathFlags 63 3 r SetRocketJumpPathFields 63 3 78.3 -1.0 0 SetZone 64 9 SetMarkerPath 64 0 11 SetMarkerPath 64 1 10 SetZone 65 9 SetMarkerPath 65 0 64 SetZone 66 9 SetMarkerPath 66 0 65 SetZone 67 7 SetMarkerPath 67 0 32 SetZone 68 7 SetMarkerPath 68 0 35 SetZone 69 8 SetMarkerPath 69 0 44 SetZone 70 8 SetMarkerPath 70 0 42 SetZone 71 9 SetMarkerPath 71 0 52 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/arenazap.bot000066400000000000000000000057311475442401000265550ustar00rootroot00000000000000CreateMarker -166 -91 24 CreateMarker -6 -273 24 CreateMarker 185 -80 24 CreateMarker 5 94 24 CreateMarker 200 113 24 CreateMarker 230 -303 24 CreateMarker -236 -268 24 CreateMarker -192 102 24 CreateMarker -8 -524 24 CreateMarker -381 -73 24 CreateMarker 13 339 24 CreateMarker 417 -92 24 SetZone 2 3 SetMarkerPath 2 0 8 SetMarkerPath 2 1 3 SetZone 3 3 SetMarkerPath 3 0 2 SetMarkerPath 3 1 4 SetZone 4 3 SetMarkerPath 4 0 3 SetMarkerPath 4 1 5 SetZone 5 3 SetMarkerPath 5 0 4 SetZone 6 3 SetMarkerPath 6 0 7 SetZone 7 3 SetMarkerPath 7 0 6 SetMarkerPath 7 1 8 SetZone 8 3 SetMarkerPath 8 0 7 SetMarkerPath 8 1 2 SetZone 18 2 SetMarkerPath 18 0 19 SetZone 19 2 SetMarkerPath 19 0 18 SetMarkerPath 19 1 20 SetZone 20 2 SetMarkerPath 20 0 19 SetMarkerPath 20 1 21 SetZone 21 2 SetMarkerPath 21 0 20 SetMarkerPath 21 1 22 SetZone 22 2 SetMarkerPath 22 0 21 SetMarkerPath 22 1 23 SetZone 23 2 SetMarkerPath 23 0 22 SetMarkerPath 23 1 24 SetZone 24 2 SetMarkerPath 24 0 23 SetZone 25 1 SetMarkerViewOfs 25 33 SetMarkerPath 25 1 40 SetMarkerPath 25 2 39 SetMarkerPath 25 3 38 SetMarkerPath 25 4 41 SetZone 26 1 SetZone 27 1 SetZone 28 1 SetZone 29 1 SetZone 30 1 SetMarkerPath 30 0 48 SetMarkerPath 30 1 45 SetMarkerPath 30 2 42 SetZone 31 1 SetMarkerPath 31 0 49 SetMarkerPath 31 1 42 SetMarkerPath 31 2 43 SetZone 32 1 SetMarkerPath 32 0 47 SetMarkerPath 32 1 44 SetMarkerPath 32 2 45 SetZone 33 1 SetMarkerPath 33 0 46 SetMarkerPath 33 1 43 SetMarkerPath 33 2 44 SetZone 34 1 SetMarkerPath 34 0 35 SetMarkerPath 34 1 37 SetMarkerPath 34 2 41 SetZone 35 1 SetMarkerPath 35 0 36 SetMarkerPath 35 1 34 SetMarkerPath 35 2 40 SetZone 36 1 SetMarkerPath 36 0 39 SetMarkerPath 36 1 35 SetMarkerPath 36 2 38 SetMarkerPath 36 3 37 SetZone 37 1 SetMarkerPath 37 0 34 SetMarkerPath 37 1 36 SetMarkerPath 37 2 38 SetZone 38 1 SetMarkerPath 38 0 36 SetMarkerPath 38 1 25 SetMarkerPath 38 2 45 SetMarkerPath 38 3 44 SetMarkerPath 38 4 37 SetZone 39 1 SetMarkerPath 39 0 36 SetMarkerPath 39 1 25 SetMarkerPath 39 2 43 SetMarkerPath 39 3 44 SetZone 40 1 SetMarkerPath 40 0 35 SetMarkerPath 40 1 25 SetMarkerPath 40 2 42 SetMarkerPath 40 3 43 SetZone 41 1 SetMarkerPath 41 0 34 SetMarkerPath 41 1 25 SetMarkerPath 41 2 45 SetMarkerPath 41 3 42 SetZone 42 1 SetMarkerPath 42 0 30 SetMarkerPath 42 1 41 SetMarkerPath 42 2 40 SetMarkerPath 42 3 48 SetMarkerPath 42 4 49 SetMarkerPath 42 5 31 SetZone 43 1 SetMarkerPath 43 0 31 SetMarkerPath 43 1 40 SetMarkerPath 43 2 39 SetMarkerPath 43 3 46 SetMarkerPath 43 4 49 SetMarkerPath 43 5 33 SetZone 44 1 SetMarkerPath 44 0 33 SetMarkerPath 44 1 39 SetMarkerPath 44 2 38 SetMarkerPath 44 3 46 SetMarkerPath 44 4 47 SetMarkerPath 44 5 32 SetZone 45 1 SetMarkerPath 45 0 30 SetMarkerPath 45 1 38 SetMarkerPath 45 2 41 SetMarkerPath 45 3 47 SetMarkerPath 45 4 48 SetMarkerPath 45 5 32 SetZone 46 1 SetMarkerPath 46 1 43 SetMarkerPath 46 2 44 SetZone 47 1 SetMarkerPath 47 1 44 SetMarkerPath 47 2 45 SetZone 48 1 SetMarkerPath 48 1 45 SetMarkerPath 48 2 42 SetZone 49 1 SetMarkerPath 49 1 42 SetMarkerPath 49 2 43 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/bravado.bot000066400000000000000000000274771475442401000264050ustar00rootroot00000000000000CreateMarker 656 -72 72 CreateMarker 656 120 72 CreateMarker 880 119 72 CreateMarker 880 -72 72 CreateMarker 822 267 104 CreateMarker 829 452 108 CreateMarker 818 673 104 CreateMarker -475 161 168 CreateMarker -351 296 168 CreateMarker -127 297 172 CreateMarker 278 670 168 CreateMarker 226 904 172 CreateMarker 468 912 168 CreateMarker 314 810 172 CreateMarker 737 781 136 CreateMarker 133 446 24 CreateMarker 367 447 24 CreateMarker -17 607 24 CreateMarker -16 813 24 CreateMarker 179 1165 172 CreateMarker -192 1175 156 CreateMarker -287 953 200 CreateMarker -174 431 296 CreateMarker -71 241 296 CreateMarker 418 293 296 CreateMarker 678 22 284 CreateMarker 766 96 284 CreateMarker 478 -322 216 CreateMarker 353 -279 264 CreateMarker 427 126 300 CreateMarker 427 -45 300 CreateMarker -17 295 24 CreateMarker 110 -59 24 CreateMarker 386 -62 145 CreateMarker -222 -59 56 CreateMarker 121 1090 24 CreateMarker -17 759 296 CreateMarker 153 342 172 CreateMarker -181 170 296 CreateMarker -15 3 24 CreateMarker -301 438 296 CreateMarker -136 1173 24 CreateMarker 104 1166 24 CreateMarker -18 1117 24 CreateMarker -208 792 24 CreateMarker -240 1098 156 CreateMarker 636 257 168 CreateMarker -384 136 296 CreateMarker 464 124 168 SetZone 1 11 SetMarkerPath 1 0 2 SetZone 2 1 SetMarkerPath 2 0 14 SetMarkerPath 2 1 64 SetGoal 3 1 SetZone 3 12 SetMarkerPath 3 0 70 SetMarkerPath 3 1 71 SetGoal 4 2 SetZone 4 3 SetMarkerPath 4 0 49 SetMarkerPath 4 1 50 SetMarkerPath 4 2 51 SetGoal 5 3 SetZone 5 7 SetMarkerPath 5 0 11 SetMarkerPath 5 1 78 SetMarkerPath 5 2 22 SetMarkerPath 5 3 70 SetMarkerPathFlags 5 3 r SetRocketJumpPathFields 5 3 770.0 215.0 4 SetGoal 6 4 SetZone 6 11 SetMarkerPath 6 0 63 SetMarkerPath 6 1 35 SetMarkerPath 6 2 19 SetMarkerPath 6 3 80 SetMarkerPath 6 5 34 SetMarkerPath 6 6 88 SetGoal 7 5 SetZone 7 10 SetMarkerPath 7 0 67 SetMarkerPathAngleHint 7 0 20 SetMarkerPath 7 1 81 SetMarkerPath 7 2 82 SetMarkerPath 7 3 76 SetGoal 8 16 SetZone 8 5 SetMarkerPath 8 0 76 SetMarkerPath 8 1 84 SetGoal 9 16 SetZone 9 7 SetMarkerPath 9 0 25 SetMarkerPath 9 1 75 SetMarkerPath 9 2 73 SetGoal 10 18 SetZone 10 1 SetMarkerPath 10 0 59 SetMarkerPath 10 1 41 SetMarkerPath 10 2 57 SetMarkerPath 10 3 58 SetGoal 11 18 SetZone 11 7 SetMarkerPath 11 0 72 SetMarkerPath 11 1 5 SetMarkerPath 11 2 78 SetGoal 12 16 SetZone 12 3 SetMarkerPath 12 0 43 SetMarkerPath 12 1 51 SetMarkerPath 12 2 59 SetMarkerPath 12 3 41 SetGoal 13 16 SetZone 13 5 SetMarkerPath 13 0 50 SetMarkerPath 13 1 61 SetMarkerPath 13 2 20 SetMarkerPath 13 3 71 SetMarkerPathFlags 13 3 r SetRocketJumpPathFields 13 3 80.0 120.0 0 SetGoal 14 16 SetZone 14 1 SetMarkerPath 14 0 56 SetMarkerPath 14 1 2 SetMarkerPath 14 2 64 SetMarkerPath 14 3 81 SetMarkerPathFlags 14 3 r SetRocketJumpPathFields 14 3 55.0 40.0 0 SetGoal 15 16 SetZone 15 13 SetMarkerPath 15 0 54 SetMarkerPath 15 1 53 SetMarkerPath 15 2 29 SetMarkerPath 15 3 76 SetGoal 16 17 SetZone 16 8 SetMarkerPath 16 0 68 SetMarkerPath 16 1 83 SetMarkerPath 16 2 26 SetGoal 17 16 SetZone 17 9 SetMarkerPath 17 0 33 SetMarkerPath 17 1 18 SetMarkerPath 17 2 85 SetMarkerPath 17 3 53 SetMarkerPath 17 4 52 SetZone 18 9 SetMarkerPath 18 0 17 SetMarkerPath 18 1 33 SetMarkerPath 18 2 53 SetZone 19 11 SetMarkerPath 19 0 63 SetMarkerPath 19 1 6 SetZone 20 5 SetMarkerPath 20 0 13 SetGoal 21 20 SetZone 21 5 SetMarkerPath 21 0 60 SetMarkerPath 21 1 62 SetMarkerPath 21 2 76 SetMarkerPath 21 3 27 SetGoal 22 23 SetZone 22 7 SetMarkerPath 22 0 5 SetMarkerPath 22 1 30 SetMarkerPath 22 2 91 SetMarkerPath 22 3 50 SetMarkerPath 22 4 3 SetMarkerPathFlags 22 4 r SetRocketJumpPathFields 22 4 65.0 135.0 2 SetMarkerPath 22 5 74 SetMarkerPathFlags 22 5 r SetRocketJumpPathFields 22 5 70.0 25.0 5 SetGoal 23 6 SetZone 23 9 SetMarkerPath 23 0 65 SetMarkerPath 23 1 66 SetMarkerPath 23 2 6 SetMarkerPath 23 3 34 SetMarkerPath 23 4 90 SetZone 24 8 SetMarkerPath 24 0 83 SetGoal 25 16 SetZone 25 7 SetMarkerPath 25 0 42 SetMarkerPath 25 1 75 SetMarkerPath 25 2 9 SetGoal 26 16 SetZone 26 8 SetMarkerPath 26 0 68 SetMarkerPath 26 1 16 SetMarkerPath 26 2 42 SetMarkerPath 26 3 27 SetMarkerPath 26 4 82 SetMarkerPath 26 5 54 SetZone 27 5 SetMarkerPath 27 0 28 SetZone 28 9 SetMarkerPath 28 0 18 SetZone 29 2 SetMarkerPath 29 0 32 SetMarkerPath 29 1 82 SetMarkerPath 29 2 54 SetMarkerPath 29 3 27 SetMarkerPath 29 4 15 SetGoal 30 19 SetZone 30 7 SetMarkerPath 30 0 22 SetMarkerPath 30 1 91 SetMarkerPath 30 2 13 SetGoal 31 19 SetZone 31 2 SetMarkerPath 31 0 55 SetMarkerPath 31 1 32 SetMarkerPath 31 2 21 SetGoal 32 21 SetZone 32 2 SetMarkerPath 32 0 31 SetMarkerPath 32 1 82 SetMarkerPath 32 2 29 SetMarkerPath 32 3 21 SetGoal 33 18 SetZone 33 9 SetMarkerPath 33 0 66 SetMarkerPath 33 1 6 SetMarkerPath 33 2 17 SetGoal 34 19 SetZone 34 11 SetMarkerPath 34 0 35 SetMarkerPath 34 1 6 SetMarkerPath 34 2 1 SetMarkerPath 34 3 63 SetMarkerPath 34 4 88 SetGoal 35 19 SetZone 35 11 SetMarkerPath 35 0 63 SetMarkerPath 35 1 34 SetMarkerPath 35 2 6 SetZone 36 6 SetMarkerPath 36 0 52 SetZone 37 6 SetMarkerPath 37 0 84 SetMarkerPath 37 1 38 SetMarkerPath 37 2 77 SetMarkerPath 37 3 79 SetGoal 38 15 SetZone 38 6 SetMarkerPath 38 0 37 SetGoal 39 7 SetZone 39 6 SetMarkerPath 39 0 40 SetMarkerPath 39 1 79 SetMarkerPath 39 2 52 SetGoal 40 23 SetZone 40 6 SetMarkerPath 40 0 79 SetMarkerPath 40 1 39 SetMarkerPath 40 2 52 SetMarkerPath 40 3 17 SetMarkerPathFlags 40 3 r SetRocketJumpPathFields 40 3 65.0 270.0 0 SetGoal 41 22 SetZone 41 1 SetMarkerPath 41 0 43 SetMarkerPath 41 1 59 SetMarkerPath 41 2 12 SetMarkerPath 41 3 10 SetMarkerPath 41 4 57 SetGoal 42 24 SetZone 42 7 SetMarkerPath 42 0 26 SetMarkerPath 42 1 69 SetMarkerPath 42 2 25 SetMarkerPath 42 3 74 SetZone 43 3 SetMarkerPath 43 0 12 SetMarkerPath 43 1 59 SetMarkerPath 43 2 41 SetGoal 44 23 SetZone 44 8 SetMarkerPath 44 0 67 SetMarkerPath 44 1 68 SetMarkerPath 44 2 83 SetMarkerPath 44 3 85 SetZone 45 4 SetMarkerPath 45 0 48 SetMarkerPath 45 1 46 SetZone 46 4 SetMarkerPath 46 0 47 SetZone 47 4 SetMarkerPath 47 0 49 SetMarkerPathFlags 47 0 j SetZone 48 4 SetMarkerPath 48 0 47 SetZone 49 3 SetMarkerPath 49 1 50 SetMarkerPath 49 2 4 SetMarkerPath 49 4 71 SetMarkerPathFlags 49 4 r SetRocketJumpPathFields 49 4 70.0 72.0 0 SetMarkerPath 49 5 91 SetZone 50 3 SetMarkerPath 50 0 49 SetMarkerPath 50 1 4 SetMarkerPath 50 2 51 SetMarkerPath 50 3 13 SetMarkerPath 50 4 42 SetMarkerPathFlags 50 4 r SetRocketJumpPathFields 50 4 70.0 30.0 0 SetMarkerPath 50 5 3 SetMarkerPathFlags 50 5 r SetRocketJumpPathFields 50 5 60.0 75.0 0 SetZone 51 3 SetMarkerPath 51 0 4 SetMarkerPath 51 1 50 SetMarkerPath 51 2 12 SetMarkerPath 51 3 59 SetZone 52 6 SetMarkerPath 52 0 39 SetMarkerPath 52 1 40 SetMarkerPath 52 2 53 SetMarkerPath 52 3 36 SetMarkerPath 52 4 33 SetMarkerPathFlags 52 4 r SetRocketJumpPathFields 52 4 65.0 260.0 0 SetZone 53 13 SetMarkerPath 53 0 52 SetMarkerPath 53 1 15 SetMarkerPath 53 2 54 SetZone 54 13 SetMarkerPath 54 0 29 SetMarkerPath 54 1 15 SetMarkerPath 54 2 21 SetMarkerPath 54 3 60 SetMarkerPath 54 4 82 SetMarkerPathAngleHint 54 4 20 SetMarkerPath 54 5 53 SetMarkerPath 54 6 8 SetMarkerPath 54 7 7 SetMarkerPathFlags 54 7 r SetRocketJumpPathFields 54 7 56.0 245.0 0 SetZone 55 1 SetMarkerPath 55 0 56 SetMarkerPath 55 1 58 SetMarkerPath 55 2 31 SetZone 56 1 SetMarkerPath 56 0 57 SetMarkerPath 56 1 14 SetMarkerPath 56 2 6 SetMarkerPath 56 3 58 SetMarkerPath 56 4 55 SetMarkerPath 56 5 63 SetMarkerPath 56 6 23 SetMarkerPathFlags 56 6 r SetRocketJumpPathFields 56 6 30.0 330.0 0 SetMarkerPath 56 7 33 SetMarkerPathFlags 56 7 r SetRocketJumpPathFields 56 7 40.0 10.0 0 SetZone 57 1 SetMarkerPath 57 0 41 SetMarkerPath 57 1 10 SetMarkerPath 57 2 58 SetMarkerPath 57 3 56 SetZone 58 1 SetMarkerPath 58 0 57 SetMarkerPath 58 1 56 SetMarkerPath 58 2 10 SetMarkerPath 58 3 55 SetMarkerPath 58 4 23 SetMarkerPathFlags 58 4 r SetRocketJumpPathFields 58 4 40.0 330.0 0 SetZone 59 3 SetMarkerPath 59 0 43 SetMarkerPath 59 1 12 SetMarkerPath 59 2 51 SetMarkerPath 59 3 10 SetMarkerPath 59 4 41 SetZone 60 5 SetMarkerPath 60 0 61 SetMarkerPath 60 1 21 SetMarkerPath 60 2 62 SetMarkerPath 60 3 76 SetZone 61 5 SetMarkerPath 61 0 13 SetMarkerPath 61 1 60 SetZone 62 5 SetMarkerPath 62 0 60 SetMarkerPath 62 1 21 SetMarkerPath 62 2 27 SetMarkerPath 62 3 63 SetZone 63 11 SetMarkerPath 63 0 62 SetMarkerPath 63 1 35 SetMarkerPath 63 2 6 SetMarkerPath 63 3 19 SetMarkerPath 63 4 80 SetMarkerPath 63 5 34 SetMarkerPath 63 6 23 SetMarkerPathFlags 63 6 r SetRocketJumpPathFields 63 6 50.0 300.0 0 SetZone 64 1 SetMarkerPath 64 0 2 SetMarkerPath 64 1 6 SetMarkerPath 64 2 80 SetMarkerPath 64 3 14 SetMarkerPath 64 4 65 SetMarkerPath 64 5 23 SetMarkerPathFlags 64 5 r SetRocketJumpPathFields 64 5 24.0 360.0 0 SetZone 65 9 SetMarkerPath 65 0 23 SetMarkerPath 65 1 90 SetMarkerPath 65 2 1 SetZone 66 9 SetMarkerPath 66 0 23 SetMarkerPath 66 1 6 SetMarkerPath 66 2 63 SetMarkerPath 66 3 33 SetMarkerPath 66 4 1 SetMarkerPath 66 5 90 SetZone 67 8 SetMarkerPath 67 0 85 SetMarkerPath 67 1 7 SetMarkerPathAngleHint 67 1 -20 SetMarkerPath 67 2 44 SetMarkerPath 67 3 60 SetZone 68 8 SetMarkerPath 68 0 44 SetMarkerPath 68 1 16 SetMarkerPath 68 2 26 SetMarkerPath 68 3 82 SetMarkerPath 68 4 27 SetMarkerPath 68 5 60 SetMarkerPath 68 6 62 SetMarkerPath 68 7 83 SetZone 69 7 SetMarkerPath 69 0 42 SetMarkerPath 69 1 74 SetMarkerPath 69 2 50 SetZone 70 12 SetMarkerPath 70 0 3 SetMarkerPath 70 1 75 SetMarkerPath 70 2 74 SetMarkerPath 70 3 71 SetMarkerPath 70 4 5 SetZone 71 12 SetMarkerPath 71 0 3 SetMarkerPath 71 1 70 SetMarkerPath 71 2 49 SetMarkerPath 71 3 22 SetZone 72 7 SetMarkerPath 72 0 73 SetMarkerPath 72 1 11 SetZone 73 7 SetMarkerPath 73 0 9 SetMarkerPath 73 1 72 SetZone 74 7 SetMarkerPath 74 0 42 SetMarkerPath 74 1 70 SetMarkerPath 74 2 69 SetZone 75 7 SetMarkerPath 75 0 25 SetMarkerPath 75 1 9 SetMarkerPath 75 2 70 SetZone 76 5 SetMarkerPath 76 0 60 SetMarkerPath 76 1 21 SetMarkerPath 76 2 27 SetMarkerPath 76 3 8 SetMarkerPath 76 4 31 SetMarkerPathFlags 76 4 r SetRocketJumpPathFields 76 4 55.0 220.0 0 SetZone 77 6 SetMarkerPath 77 0 84 SetMarkerPath 77 1 37 SetMarkerPath 77 2 79 SetMarkerPath 77 3 78 SetZone 78 7 SetMarkerPath 78 0 11 SetMarkerPath 78 1 5 SetMarkerPath 78 2 77 SetZone 79 6 SetMarkerPath 79 0 84 SetMarkerPath 79 1 37 SetMarkerPath 79 2 77 SetMarkerPath 79 3 40 SetMarkerPath 79 4 39 SetZone 80 11 SetMarkerPath 80 0 6 SetMarkerPath 80 1 1 SetMarkerPath 80 2 63 SetMarkerPath 80 3 88 SetZone 81 10 SetMarkerPath 81 0 7 SetMarkerPath 81 1 35 SetMarkerPath 81 2 6 SetMarkerPath 81 3 66 SetMarkerPathAngleHint 81 3 -30 SetMarkerPath 81 4 14 SetMarkerPathAngleHint 81 4 30 SetZone 82 2 SetMarkerPath 82 0 32 SetMarkerPath 82 1 29 SetMarkerPath 82 2 7 SetMarkerPathFlags 82 2 r SetRocketJumpPathFields 82 2 60.0 300.0 2 SetMarkerPath 82 3 27 SetMarkerPath 82 4 54 SetZone 83 8 SetMarkerPath 83 0 44 SetMarkerPath 83 1 68 SetMarkerPath 83 2 16 SetMarkerPath 83 3 24 SetZone 84 6 SetMarkerPath 84 0 8 SetMarkerPath 84 1 77 SetMarkerPath 84 2 79 SetMarkerPath 84 3 37 SetZone 85 8 SetMarkerPath 85 0 17 SetMarkerPath 85 1 44 SetMarkerPath 85 2 67 SetZone 86 11 SetMarkerPath 86 0 1 SetMarkerPath 86 1 6 SetMarkerPath 86 2 88 SetZone 87 11 SetMarkerPath 87 0 80 SetMarkerPath 87 1 88 SetMarkerPath 87 2 1 SetMarkerPath 87 3 6 SetZone 88 11 SetMarkerPath 88 0 1 SetMarkerPath 88 1 6 SetMarkerPath 88 2 34 SetMarkerPath 88 3 80 SetMarkerPath 88 4 87 SetZone 89 11 SetMarkerPath 89 0 63 SetMarkerPath 89 1 6 SetMarkerPath 89 2 35 SetZone 90 9 SetMarkerPath 90 0 23 SetMarkerPath 90 1 65 SetMarkerPath 90 2 66 SetMarkerPath 90 3 81 SetMarkerPathFlags 90 3 r SetRocketJumpPathFields 90 3 60.0 120.0 0 SetMarkerPath 90 4 56 SetMarkerPathFlags 90 4 r SetRocketJumpPathFields 90 4 35.0 150.0 0 SetZone 91 7 SetMarkerPath 91 0 49 SetMarkerPath 91 1 13 SetMarkerPath 91 2 22 SetMarkerPath 91 3 30 SetMarkerPath 91 4 50 SetMarkerPathAngleHint 91 4 30 SetMarkerPath 91 5 74 SetMarkerPathFlags 91 5 r SetRocketJumpPathFields 91 5 55.0 27.0 0 SetMarkerPath 91 6 3 SetMarkerPathFlags 91 6 r SetRocketJumpPathFields 91 6 64.0 141.0 4 SetZone 92 6 SetMarkerPath 92 0 52 SetMarkerPath 92 1 40 SetZone 93 7 SetMarkerPath 93 0 22 SetMarkerPath 93 1 5 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/cmt1b.bot000066400000000000000000000703411475442401000257610ustar00rootroot00000000000000CreateMarker 1220 -107 120 CreateMarker 1049 -111 120 CreateMarker 968 -238 120 CreateMarker 1150 -407 120 CreateMarker 982 -382 120 CreateMarker 896 -486 120 CreateMarker 662 -337 120 CreateMarker 825 -220 120 CreateMarker 690 -164 120 CreateMarker 675 -39 120 CreateMarker 665 128 120 CreateMarker 838 -63 120 CreateMarker 853 107 120 CreateMarker 962 13 120 CreateMarker 990 184 120 CreateMarker 1184 204 120 CreateMarker 1075 15 120 CreateMarker 1199 22 312 CreateMarker 1317 -19 312 CreateMarker 1370 -145 312 CreateMarker 1359 -310 312 CreateMarker 1351 -462 312 CreateMarker 1259 -541 312 CreateMarker 1133 -533 312 CreateMarker 467 131 120 CreateMarker 313 99 120 CreateMarker 392 -14 120 CreateMarker 348 -152 120 CreateMarker 341 -310 120 CreateMarker 336 -464 120 CreateMarker 340 -618 120 CreateMarker 331 -783 120 CreateMarker 333 -964 120 CreateMarker 329 -1097 120 CreateMarker 339 -1255 120 CreateMarker 498 -1223 152 CreateMarker 616 -1220 200 CreateMarker 742 -1157 200 CreateMarker 723 -1014 200 CreateMarker 734 -812 200 CreateMarker 308 -1413 120 CreateMarker 794 -491 -72 CreateMarker 634 -494 -72 CreateMarker 494 -486 -72 CreateMarker 374 -550 -72 CreateMarker 325 -708 -72 CreateMarker 376 -863 -72 CreateMarker 512 -887 -72 CreateMarker 139 -849 -72 CreateMarker 263 -942 -72 CreateMarker 396 -1075 -72 CreateMarker 276 -1105 -72 CreateMarker 158 -1453 136 CreateMarker -3 -1460 168 CreateMarker -44 -1319 184 CreateMarker -35 -1185 248 CreateMarker -16 -1063 280 CreateMarker 57 -942 280 CreateMarker 24 -795 280 CreateMarker -60 -913 280 CreateMarker -163 -1009 280 CreateMarker -145 -812 280 CreateMarker -250 -910 280 CreateMarker -227 -706 280 CreateMarker -343 -805 280 CreateMarker -478 -862 280 CreateMarker -417 -969 280 CreateMarker -299 -1062 280 CreateMarker -404 -1154 280 CreateMarker -474 -1301 280 CreateMarker -606 -1312 312 CreateMarker -757 -1294 328 CreateMarker -763 -1160 344 CreateMarker -770 -1021 408 CreateMarker -691 -901 408 CreateMarker -770 -787 408 CreateMarker -710 -662 408 CreateMarker -614 -559 376 CreateMarker -440 -586 376 CreateMarker -462 -441 376 CreateMarker -314 -469 376 CreateMarker -172 -444 376 CreateMarker -51 -348 376 CreateMarker -255 -974 424 CreateMarker -485 -1044 408 CreateMarker -69 -200 376 CreateMarker 60 -118 376 CreateMarker -90 -53 376 CreateMarker -203 -156 376 CreateMarker -340 -181 376 CreateMarker -303 -34 376 CreateMarker -298 117 376 CreateMarker -159 105 376 CreateMarker -20 108 376 CreateMarker 129 58 376 CreateMarker 273 55 376 CreateMarker 447 85 376 CreateMarker 471 227 376 CreateMarker 481 365 376 CreateMarker 578 489 376 CreateMarker 711 504 376 CreateMarker 863 505 328 CreateMarker 987 502 264 CreateMarker 1125 486 200 CreateMarker 1238 358 168 CreateMarker 959 609 280 CreateMarker 1110 622 280 CreateMarker 1221 571 280 CreateMarker 1328 457 280 CreateMarker 1316 281 280 CreateMarker 372 512 376 CreateMarker 234 599 376 CreateMarker 241 805 376 CreateMarker 353 899 376 CreateMarker 354 1066 376 CreateMarker 253 1179 376 CreateMarker 490 1045 376 CreateMarker 437 1211 376 CreateMarker 571 1230 376 CreateMarker 562 1368 376 CreateMarker 437 1376 376 CreateMarker 367 1498 376 CreateMarker 256 1389 376 CreateMarker 159 1295 376 CreateMarker 234 1536 376 CreateMarker 77 1459 376 CreateMarker -9 1332 376 CreateMarker -101 1435 376 CreateMarker -205 1352 376 CreateMarker -335 1320 376 CreateMarker -330 1440 376 CreateMarker -199 1550 376 CreateMarker 489 1584 408 CreateMarker 482 1616 440 CreateMarker 473 1648 472 CreateMarker 432 1643 504 CreateMarker 400 1641 536 CreateMarker 351 1633 568 CreateMarker 356 1491 568 CreateMarker 351 1319 568 CreateMarker 494 1313 568 CreateMarker 183 1312 568 CreateMarker 40 1311 568 CreateMarker -122 1313 568 CreateMarker -255 1311 568 CreateMarker 351 1170 568 CreateMarker 360 1065 568 CreateMarker 223 1076 568 CreateMarker 370 902 568 CreateMarker 256 821 568 CreateMarker 12 1552 461 CreateMarker 270 1633 536 CreateMarker 184 1629 504 CreateMarker 264 608 568 CreateMarker 415 556 568 CreateMarker 568 541 568 CreateMarker 572 411 568 CreateMarker 436 385 568 CreateMarker 513 209 568 CreateMarker 500 36 568 CreateMarker 593 91 600 CreateMarker 375 138 568 CreateMarker 287 38 568 CreateMarker 395 -63 568 CreateMarker 169 210 568 CreateMarker 92 329 568 CreateMarker -210 320 568 CreateMarker -337 236 568 CreateMarker -167 1030 408 CreateMarker -307 1042 408 CreateMarker -448 1064 408 CreateMarker -46 850 120 CreateMarker -96 705 120 CreateMarker -235 705 120 CreateMarker -423 697 152 CreateMarker -450 907 152 CreateMarker -449 526 152 CreateMarker -336 1195 408 CreateMarker -445 351 152 CreateMarker -602 319 152 CreateMarker -750 325 152 CreateMarker -869 322 152 CreateMarker -834 462 104 CreateMarker -938 515 104 CreateMarker -821 633 104 CreateMarker -623 810 104 CreateMarker -590 657 104 CreateMarker -699 182 152 CreateMarker -694 36 152 CreateMarker -720 -90 152 CreateMarker -561 -73 152 CreateMarker -399 -78 120 CreateMarker -221 -56 120 CreateMarker -54 -32 120 CreateMarker 52 -35 168 CreateMarker 58 75 184 CreateMarker 62 250 184 CreateMarker -56 270 184 CreateMarker -799 73 104 CreateMarker -964 487 376 CreateMarker -1155 455 376 CreateMarker -1143 330 376 CreateMarker -1156 197 376 CreateMarker -1158 50 376 CreateMarker -985 59 376 CreateMarker -842 68 376 CreateMarker -687 70 376 CreateMarker -523 64 376 CreateMarker -518 -68 376 CreateMarker -490 -178 376 CreateMarker -855 -233 568 CreateMarker -721 -224 568 CreateMarker -516 -102 568 CreateMarker -494 0 568 CreateMarker -598 56 568 CreateMarker -68 200 184 SetZone 1 5 SetMarkerPath 1 1 43 SetMarkerPath 1 2 127 SetMarkerPath 1 3 124 SetGoal 3 4 SetZone 3 6 SetMarkerPath 3 1 149 SetGoal 4 12 SetZone 4 14 SetMarkerPath 4 0 276 SetMarkerPath 4 1 271 SetGoal 5 11 SetZone 5 12 SetMarkerPath 5 1 58 SetMarkerPath 5 2 258 SetMarkerPath 5 3 281 SetGoal 6 7 SetZone 6 13 SetMarkerPath 6 1 267 SetMarkerPath 6 2 246 SetGoal 7 23 SetZone 7 11 SetMarkerPath 7 1 248 SetMarkerPath 7 2 252 SetMarkerPath 7 3 250 SetGoal 8 9 SetZone 8 8 SetMarkerPath 8 1 196 SetMarkerPath 8 2 197 SetGoal 9 22 SetZone 9 9 SetMarkerPath 9 1 52 SetMarkerPathFlags 9 1 j SetMarkerPath 9 2 219 SetMarkerPath 9 3 215 SetGoal 10 1 SetZone 10 3 SetMarkerPath 10 1 98 SetMarkerPathFlags 10 1 j SetMarkerPath 10 2 104 SetMarkerPath 10 3 105 SetGoal 11 12 SetZone 11 14 SetMarkerPath 11 0 278 SetMarkerPath 11 1 148 SetMarkerPath 11 2 153 SetGoal 12 19 SetZone 12 12 SetMarkerPath 12 1 255 SetMarkerPathFlags 12 1 j SetMarkerPath 12 2 17 SetGoal 13 20 SetZone 13 11 SetMarkerPath 13 1 14 SetMarkerPath 13 2 241 SetMarkerPath 13 3 240 SetGoal 14 20 SetZone 14 11 SetMarkerPath 14 1 237 SetMarkerPath 14 2 238 SetMarkerPath 14 3 13 SetMarkerPath 14 4 239 SetGoal 15 21 SetZone 15 11 SetMarkerPath 15 1 239 SetGoal 16 19 SetZone 16 11 SetMarkerPath 16 1 247 SetMarkerPath 16 2 249 SetGoal 17 19 SetZone 17 12 SetMarkerPath 17 1 12 SetMarkerPath 17 2 247 SetMarkerPathFlags 17 2 j SetGoal 18 8 SetZone 18 8 SetMarkerPath 18 1 180 SetMarkerPath 18 2 181 SetGoal 19 8 SetZone 19 8 SetMarkerPath 19 1 54 SetMarkerPath 19 2 187 SetMarkerPath 19 3 186 SetZone 20 3 SetMarkerPath 20 1 105 SetGoal 21 15 SetZone 21 1 SetMarkerPath 21 1 22 SetMarkerPath 21 2 24 SetGoal 22 15 SetZone 22 1 SetMarkerPath 22 1 21 SetMarkerPath 22 2 69 SetMarkerPath 22 3 24 SetGoal 23 17 SetZone 23 2 SetMarkerPath 23 1 73 SetGoal 24 15 SetZone 24 1 SetMarkerPath 24 1 28 SetMarkerPath 24 2 21 SetMarkerPath 24 3 22 SetGoal 25 17 SetZone 25 2 SetMarkerPath 25 1 89 SetMarkerPath 25 2 53 SetMarkerPath 25 3 23 SetMarkerPathFlags 25 3 j SetGoal 26 16 SetZone 26 1 SetMarkerPath 26 1 67 SetMarkerPath 26 2 69 SetMarkerPath 26 3 66 SetMarkerPath 26 4 70 SetMarkerPath 26 5 68 SetGoal 27 18 SetZone 27 7 SetMarkerPath 27 1 81 SetMarkerPath 27 2 175 SetGoal 28 15 SetZone 28 1 SetMarkerPath 28 1 66 SetMarkerPath 28 2 24 SetGoal 29 2 SetZone 29 4 SetMarkerPath 29 1 110 SetMarkerPath 29 2 111 SetGoal 30 2 SetZone 30 4 SetMarkerPath 30 1 115 SetMarkerPath 30 2 114 SetMarkerPath 30 3 98 SetGoal 31 6 SetZone 31 13 SetMarkerPath 31 1 32 SetGoal 32 6 SetZone 32 13 SetMarkerPath 32 1 34 SetMarkerPath 32 2 31 SetZone 33 13 SetZone 34 13 SetMarkerPath 34 1 269 SetMarkerPath 34 2 32 SetZone 35 10 SetMarkerPath 35 1 221 SetMarkerPath 35 2 222 SetZone 36 8 SetMarkerPath 36 1 177 SetMarkerPath 36 2 176 SetMarkerPath 36 3 178 SetZone 37 12 SetMarkerPath 37 1 259 SetZone 38 12 SetMarkerPath 38 1 259 SetZone 41 5 SetMarkerPath 41 0 37 SetMarkerPath 41 1 131 SetGoal 42 3 SetZone 42 5 SetMarkerPath 42 1 134 SetMarkerPath 42 2 135 SetGoal 43 3 SetZone 43 5 SetMarkerPath 43 1 50 SetMarkerPath 43 2 1 SetZone 44 3 SetMarkerPath 44 1 93 SetMarkerPath 44 2 59 SetMarkerPath 44 3 55 SetMarkerPath 44 4 92 SetZone 45 11 SetMarkerPath 45 1 234 SetMarkerPath 45 2 243 SetGoal 46 14 SetZone 46 10 SetMarkerPath 46 1 231 SetMarkerPath 46 2 232 SetZone 47 7 SetMarkerPath 47 1 159 SetMarkerPath 47 2 48 SetZone 48 7 SetMarkerPath 48 1 47 SetMarkerPath 48 2 158 SetMarkerPath 48 3 159 SetGoal 49 21 SetZone 49 11 SetMarkerPath 49 1 238 SetMarkerPath 49 2 64 SetMarkerPathFlags 49 2 j SetGoal 50 3 SetZone 50 5 SetMarkerPath 50 1 124 SetMarkerPath 50 2 43 SetZone 51 7 SetMarkerPath 51 1 60 SetMarkerPath 51 2 162 SetMarkerPath 51 3 225 SetGoal 52 10 SetZone 52 11 SetMarkerPath 52 1 234 SetMarkerPath 52 2 235 SetMarkerPath 52 3 240 SetGoal 53 17 SetZone 53 2 SetMarkerPath 53 1 25 SetMarkerPath 53 2 89 SetGoal 54 8 SetZone 54 8 SetMarkerPath 54 1 185 SetMarkerPath 54 2 19 SetGoal 55 13 SetZone 55 3 SetMarkerPath 55 1 44 SetMarkerPath 55 2 93 SetMarkerPath 55 3 94 SetGoal 56 5 SetZone 56 6 SetMarkerPath 56 1 147 SetMarkerPath 56 2 148 SetGoal 57 12 SetZone 57 14 SetMarkerPath 57 0 277 SetMarkerPath 57 1 278 SetGoal 58 11 SetZone 58 12 SetMarkerPath 58 1 5 SetMarkerPath 58 2 263 SetMarkerPath 58 3 46 SetGoal 59 13 SetZone 59 3 SetMarkerPath 59 1 91 SetMarkerPath 59 2 44 SetMarkerPath 59 3 92 SetGoal 60 24 SetZone 60 7 SetMarkerPath 60 1 162 SetMarkerPath 60 2 51 SetMarkerPath 60 3 161 SetGoal 61 10 SetZone 61 11 SetMarkerPath 61 1 236 SetMarkerPath 61 2 243 SetGoal 63 3 SetZone 63 5 SetMarkerPath 63 1 130 SetMarkerPath 63 2 129 SetZone 64 11 SetMarkerPath 64 0 65 SetZone 65 13 SetMarkerPath 65 1 265 SetMarkerPathFlags 65 1 j SetZone 66 1 SetMarkerPath 66 1 26 SetMarkerPath 66 2 28 SetMarkerPath 66 3 67 SetZone 67 1 SetMarkerPath 67 1 79 SetMarkerPath 67 2 82 SetMarkerPath 67 3 26 SetMarkerPath 67 4 68 SetMarkerPath 67 5 66 SetMarkerPath 67 6 77 SetZone 68 1 SetMarkerPath 68 1 67 SetMarkerPath 68 2 70 SetMarkerPath 68 3 73 SetMarkerPath 68 4 26 SetZone 69 1 SetMarkerPath 69 1 70 SetMarkerPath 69 2 22 SetMarkerPath 69 3 26 SetZone 70 1 SetMarkerPath 70 1 68 SetMarkerPath 70 2 69 SetMarkerPath 70 3 26 SetMarkerPath 70 4 73 SetMarkerPath 70 5 71 SetZone 71 1 SetMarkerPath 71 1 70 SetMarkerPath 71 2 107 SetZone 72 1 SetMarkerPath 72 1 74 SetMarkerPath 72 2 108 SetZone 73 1 SetMarkerPath 73 1 68 SetMarkerPath 73 2 70 SetMarkerPath 73 3 77 SetMarkerPath 73 4 74 SetZone 74 1 SetMarkerPath 74 1 73 SetMarkerPath 74 2 72 SetMarkerPath 74 3 77 SetMarkerPath 74 4 75 SetZone 75 1 SetMarkerPath 75 1 76 SetMarkerPath 75 2 77 SetMarkerPath 75 3 74 SetMarkerPath 75 4 78 SetZone 76 1 SetMarkerPath 76 1 75 SetMarkerPath 76 2 78 SetMarkerPath 76 3 90 SetZone 77 1 SetMarkerPath 77 1 75 SetMarkerPath 77 2 78 SetMarkerPath 77 3 79 SetMarkerPath 77 4 67 SetMarkerPath 77 5 73 SetMarkerPath 77 6 74 SetZone 78 1 SetMarkerPath 78 1 77 SetMarkerPath 78 2 76 SetMarkerPath 78 3 80 SetMarkerPath 78 4 79 SetMarkerPath 78 5 75 SetZone 79 1 SetMarkerPath 79 1 77 SetMarkerPath 79 2 67 SetMarkerPath 79 3 80 SetMarkerPath 79 4 78 SetMarkerPath 79 5 82 SetZone 80 1 SetMarkerPath 80 1 79 SetMarkerPath 80 2 78 SetMarkerPath 80 3 82 SetMarkerPath 80 4 81 SetZone 81 1 SetMarkerPath 81 1 80 SetMarkerPath 81 2 170 SetZone 82 1 SetMarkerPath 82 1 79 SetMarkerPath 82 2 80 SetMarkerPath 82 3 67 SetMarkerPath 82 4 83 SetZone 83 2 SetMarkerPath 83 1 84 SetZone 84 2 SetMarkerPath 84 1 83 SetMarkerPath 84 2 85 SetZone 85 2 SetMarkerPath 85 1 84 SetMarkerPath 85 2 86 SetMarkerPath 85 3 26 SetZone 86 2 SetMarkerPath 86 1 85 SetMarkerPath 86 2 87 SetZone 87 2 SetMarkerPath 87 1 86 SetMarkerPath 87 2 88 SetZone 88 2 SetMarkerPath 88 1 87 SetMarkerPath 88 2 89 SetZone 89 2 SetMarkerPath 89 1 88 SetMarkerPath 89 2 25 SetMarkerPath 89 3 53 SetZone 90 3 SetMarkerPath 90 1 76 SetMarkerPath 90 2 92 SetMarkerPath 90 3 91 SetZone 91 3 SetMarkerPath 91 1 92 SetMarkerPath 91 2 90 SetMarkerPath 91 3 59 SetZone 92 3 SetMarkerPath 92 1 90 SetMarkerPath 92 2 91 SetMarkerPath 92 3 93 SetMarkerPath 92 4 44 SetMarkerPath 92 5 59 SetZone 93 3 SetMarkerPath 93 1 92 SetMarkerPath 93 2 44 SetMarkerPath 93 3 55 SetMarkerPath 93 4 94 SetZone 94 3 SetMarkerPath 94 1 93 SetMarkerPath 94 2 55 SetMarkerPath 94 3 95 SetZone 95 3 SetMarkerPath 95 1 96 SetMarkerPath 95 2 94 SetZone 96 3 SetMarkerPath 96 1 95 SetMarkerPath 96 2 97 SetZone 97 3 SetMarkerPath 97 1 96 SetMarkerPath 97 2 98 SetZone 98 3 SetMarkerPath 98 1 97 SetMarkerPath 98 2 99 SetZone 99 3 SetMarkerPath 99 1 98 SetMarkerPath 99 2 100 SetZone 100 3 SetMarkerPath 100 1 99 SetMarkerPath 100 2 101 SetMarkerPath 100 3 106 SetZone 101 3 SetMarkerPath 101 1 100 SetMarkerPath 101 2 102 SetZone 102 3 SetMarkerPath 102 1 101 SetMarkerPath 102 2 103 SetZone 103 3 SetMarkerPath 103 1 102 SetMarkerPath 103 2 104 SetZone 104 3 SetMarkerPath 104 1 103 SetMarkerPath 104 2 10 SetZone 105 3 SetMarkerPath 105 1 10 SetMarkerPath 105 2 20 SetZone 106 3 SetMarkerPath 106 1 100 SetMarkerPath 106 2 118 SetZone 107 4 SetMarkerPath 107 1 71 SetMarkerPath 107 2 108 SetZone 108 4 SetMarkerPath 108 1 107 SetMarkerPath 108 2 109 SetZone 109 4 SetMarkerPath 109 1 108 SetMarkerPath 109 2 110 SetZone 110 4 SetMarkerPath 110 1 109 SetMarkerPath 110 2 29 SetMarkerPath 110 3 111 SetZone 111 4 SetMarkerPath 111 1 29 SetMarkerPath 111 2 110 SetMarkerPath 111 3 112 SetZone 112 4 SetMarkerPath 112 1 111 SetMarkerPath 112 2 113 SetMarkerPath 112 3 115 SetMarkerPath 112 4 116 SetZone 113 4 SetMarkerPath 113 1 112 SetMarkerPath 113 2 116 SetMarkerPath 113 3 97 SetZone 114 4 SetMarkerPath 114 1 115 SetMarkerPath 114 2 30 SetMarkerPath 114 3 98 SetZone 115 4 SetMarkerPath 115 1 112 SetMarkerPath 115 2 117 SetMarkerPath 115 3 30 SetMarkerPath 115 4 114 SetMarkerPath 115 5 116 SetZone 116 4 SetMarkerPath 116 1 117 SetMarkerPath 116 2 113 SetMarkerPath 116 3 112 SetMarkerPath 116 4 115 SetZone 117 4 SetMarkerPath 117 1 115 SetMarkerPath 117 2 116 SetZone 118 5 SetMarkerPath 118 1 106 SetMarkerPath 118 2 119 SetZone 119 5 SetMarkerPath 119 1 118 SetMarkerPath 119 2 120 SetZone 120 5 SetMarkerPath 120 1 119 SetMarkerPath 120 2 121 SetZone 121 5 SetMarkerPath 121 1 120 SetMarkerPath 121 2 122 SetZone 122 5 SetMarkerPath 122 1 121 SetMarkerPath 122 2 126 SetMarkerPath 122 3 125 SetMarkerPath 122 4 123 SetZone 123 5 SetMarkerPath 123 1 98 SetMarkerPath 123 2 125 SetMarkerPath 123 3 122 SetMarkerPath 123 4 124 SetZone 124 5 SetMarkerPath 124 1 123 SetMarkerPath 124 2 127 SetMarkerPath 124 3 125 SetMarkerPath 124 4 50 SetMarkerPath 124 5 1 SetZone 125 5 SetMarkerPath 125 1 122 SetMarkerPath 125 2 123 SetMarkerPath 125 3 126 SetMarkerPath 125 4 127 SetMarkerPath 125 5 124 SetMarkerPath 125 6 128 SetZone 126 5 SetMarkerPath 126 1 122 SetMarkerPath 126 2 125 SetMarkerPath 126 3 128 SetMarkerPath 126 4 133 SetZone 127 5 SetMarkerPath 127 1 124 SetMarkerPath 127 2 125 SetMarkerPath 127 3 1 SetMarkerPath 127 4 129 SetMarkerPath 127 5 128 SetZone 128 5 SetMarkerPath 128 1 127 SetMarkerPath 128 2 126 SetMarkerPath 128 3 125 SetMarkerPath 128 4 133 SetMarkerPath 128 5 130 SetMarkerPath 128 6 132 SetZone 129 5 SetMarkerPath 129 1 127 SetMarkerPath 129 2 130 SetMarkerPath 129 3 63 SetZone 130 5 SetMarkerPath 130 1 63 SetMarkerPath 130 2 129 SetMarkerPath 130 3 128 SetMarkerPath 130 4 131 SetMarkerPath 130 5 132 SetZone 131 5 SetMarkerPath 131 1 132 SetMarkerPath 131 2 41 SetMarkerPath 131 3 130 SetMarkerPath 131 4 37 SetZone 132 5 SetMarkerPath 132 1 133 SetMarkerPath 132 2 131 SetMarkerPath 132 3 130 SetMarkerPath 132 4 134 SetMarkerPath 132 5 128 SetZone 133 5 SetMarkerPath 133 1 128 SetMarkerPath 133 2 126 SetMarkerPath 133 3 134 SetMarkerPath 133 4 132 SetZone 134 5 SetMarkerPath 134 1 133 SetMarkerPath 134 2 42 SetMarkerPath 134 3 135 SetMarkerPath 134 4 132 SetZone 135 5 SetMarkerPath 135 1 42 SetMarkerPath 135 2 134 SetMarkerPath 135 3 136 SetZone 136 6 SetMarkerPath 136 1 135 SetMarkerPath 136 2 137 SetZone 137 6 SetMarkerPath 137 1 136 SetMarkerPath 137 2 138 SetZone 138 6 SetMarkerPath 138 1 137 SetMarkerPath 138 2 139 SetZone 139 6 SetMarkerPath 139 1 138 SetMarkerPath 139 2 140 SetMarkerPath 139 3 141 SetZone 140 6 SetMarkerPath 140 1 150 SetMarkerPathFlags 140 1 j SetMarkerPath 140 2 139 SetMarkerPath 140 3 141 SetZone 141 6 SetMarkerPath 141 1 140 SetMarkerPath 141 2 142 SetMarkerPath 141 3 139 SetZone 142 6 SetMarkerPath 142 1 141 SetMarkerPath 142 2 143 SetZone 143 6 SetMarkerPath 143 1 142 SetMarkerPath 143 2 145 SetMarkerPath 143 3 144 SetZone 144 6 SetMarkerPath 144 1 130 SetZone 145 6 SetMarkerPath 145 1 143 SetMarkerPath 145 2 144 SetMarkerPath 145 3 146 SetZone 146 6 SetMarkerPath 146 1 144 SetMarkerPath 146 2 145 SetMarkerPath 146 3 147 SetZone 147 6 SetMarkerPath 147 1 146 SetMarkerPath 147 2 56 SetMarkerPath 147 3 148 SetZone 148 6 SetMarkerPath 148 1 147 SetMarkerPath 148 2 56 SetMarkerPath 148 3 151 SetZone 149 6 SetMarkerPath 149 1 3 SetMarkerPath 149 2 133 SetZone 150 6 SetMarkerPath 150 1 149 SetMarkerPathFlags 150 1 j SetZone 151 7 SetMarkerPath 151 1 153 SetMarkerPath 151 2 148 SetMarkerPath 151 3 154 SetMarkerPath 151 4 152 SetZone 152 7 SetMarkerPath 152 1 160 SetMarkerPath 152 2 153 SetMarkerPath 152 3 151 SetZone 153 7 SetMarkerPath 153 0 11 SetMarkerPathFlags 153 0 r SetRocketJumpPathFields 153 0 0.0 0.0 0 SetMarkerPath 153 1 152 SetMarkerPath 153 2 159 SetMarkerPath 153 3 154 SetMarkerPath 153 4 158 SetMarkerPath 153 5 151 SetMarkerPath 153 6 156 SetZone 154 7 SetMarkerPath 154 1 153 SetMarkerPath 154 2 156 SetMarkerPath 154 3 151 SetMarkerPath 154 4 155 SetZone 155 7 SetMarkerPath 155 1 156 SetMarkerPath 155 2 154 SetMarkerPath 155 3 275 SetZone 156 7 SetMarkerPath 156 1 155 SetMarkerPath 156 2 154 SetMarkerPath 156 3 158 SetMarkerPath 156 4 153 SetMarkerPath 156 5 157 SetZone 157 7 SetMarkerPath 157 1 158 SetMarkerPath 157 2 156 SetZone 158 7 SetMarkerPath 158 1 48 SetMarkerPath 158 2 153 SetMarkerPath 158 3 159 SetMarkerPath 158 4 156 SetMarkerPath 158 5 157 SetZone 159 7 SetMarkerPath 159 1 160 SetMarkerPath 159 2 47 SetMarkerPath 159 3 48 SetMarkerPath 159 4 153 SetMarkerPath 159 5 158 SetZone 160 7 SetMarkerPath 160 1 161 SetMarkerPath 160 2 152 SetMarkerPath 160 3 159 SetZone 161 7 SetMarkerPath 161 1 162 SetMarkerPath 161 2 60 SetMarkerPath 161 3 160 SetZone 162 7 SetMarkerPath 162 1 163 SetMarkerPath 162 2 60 SetMarkerPath 162 3 51 SetMarkerPath 162 4 161 SetZone 163 7 SetMarkerPath 163 1 164 SetMarkerPath 163 2 162 SetZone 164 8 SetMarkerPath 164 1 165 SetMarkerPath 164 2 163 SetMarkerPath 164 3 176 SetZone 165 7 SetMarkerPath 165 1 166 SetMarkerPath 165 2 164 SetMarkerPath 165 3 176 SetZone 166 7 SetMarkerPath 166 1 167 SetMarkerPath 166 2 165 SetZone 167 7 SetMarkerPath 167 1 168 SetMarkerPath 167 2 171 SetMarkerPath 167 3 166 SetZone 168 7 SetMarkerPath 168 1 169 SetMarkerPath 168 2 167 SetZone 169 7 SetMarkerPath 169 1 170 SetMarkerPath 169 2 168 SetZone 170 7 SetMarkerPath 170 1 81 SetMarkerPath 170 2 169 SetZone 171 7 SetMarkerPath 171 1 167 SetMarkerPath 171 2 172 SetZone 172 7 SetMarkerPath 172 1 171 SetMarkerPath 172 2 173 SetZone 173 7 SetMarkerPath 173 1 172 SetMarkerPath 173 2 174 SetZone 174 7 SetMarkerPath 174 1 173 SetMarkerPath 174 2 175 SetMarkerPath 174 3 170 SetZone 175 7 SetMarkerPath 175 1 174 SetMarkerPath 175 2 27 SetZone 176 8 SetMarkerPath 176 1 164 SetMarkerPath 176 2 165 SetMarkerPath 176 3 177 SetMarkerPath 176 4 36 SetZone 177 8 SetMarkerPath 177 1 176 SetMarkerPath 177 2 36 SetMarkerPath 177 3 178 SetZone 178 8 SetMarkerPath 178 1 36 SetMarkerPath 178 2 177 SetMarkerPath 178 3 179 SetZone 179 8 SetMarkerPath 179 1 178 SetMarkerPath 179 2 180 SetZone 180 8 SetMarkerPath 180 1 179 SetMarkerPath 180 2 18 SetMarkerPath 180 3 181 SetMarkerPath 180 4 182 SetMarkerPath 180 5 183 SetZone 181 8 SetMarkerPath 181 1 18 SetMarkerPath 181 2 180 SetMarkerPath 181 3 183 SetMarkerPath 181 4 189 SetZone 182 8 SetMarkerPath 182 1 180 SetMarkerPath 182 2 183 SetZone 183 8 SetMarkerPath 183 1 182 SetMarkerPath 183 2 181 SetMarkerPath 183 3 184 SetMarkerPath 183 4 186 SetMarkerPath 183 5 180 SetZone 184 8 SetMarkerPath 184 1 183 SetMarkerPath 184 2 185 SetZone 185 8 SetMarkerPath 185 1 184 SetMarkerPath 185 2 186 SetMarkerPath 185 3 54 SetZone 186 8 SetMarkerPath 186 1 183 SetMarkerPath 186 2 185 SetMarkerPath 186 3 19 SetMarkerPath 186 4 188 SetMarkerPath 186 5 187 SetZone 187 8 SetMarkerPath 187 1 19 SetMarkerPath 187 2 188 SetMarkerPath 187 3 190 SetMarkerPath 187 4 186 SetMarkerPath 187 5 198 SetMarkerPathFlags 187 5 j SetZone 188 8 SetMarkerPath 188 1 186 SetMarkerPath 188 2 187 SetMarkerPath 188 3 189 SetMarkerPath 188 4 191 SetMarkerPath 188 5 190 SetZone 189 8 SetMarkerPath 189 1 188 SetMarkerPath 189 2 181 SetMarkerPath 189 3 191 SetMarkerPath 189 4 192 SetZone 190 8 SetMarkerPath 190 1 187 SetMarkerPath 190 2 191 SetMarkerPath 190 3 188 SetZone 191 8 SetMarkerPath 191 1 188 SetMarkerPath 191 2 190 SetMarkerPath 191 3 189 SetMarkerPath 191 4 192 SetZone 192 8 SetMarkerPath 192 1 191 SetMarkerPath 192 2 189 SetMarkerPath 192 3 193 SetMarkerPath 192 4 194 SetZone 193 8 SetMarkerPath 193 1 192 SetMarkerPath 193 2 197 SetMarkerPath 193 3 194 SetZone 194 8 SetMarkerPath 194 1 195 SetMarkerPath 194 2 193 SetMarkerPath 194 3 196 SetMarkerPath 194 4 192 SetZone 195 8 SetMarkerPath 195 1 194 SetMarkerPath 195 2 196 SetMarkerPath 195 3 243 SetZone 196 8 SetMarkerPath 196 1 8 SetMarkerPath 196 2 197 SetMarkerPath 196 3 194 SetMarkerPath 196 4 195 SetZone 197 8 SetMarkerPath 197 1 193 SetMarkerPath 197 2 196 SetMarkerPath 197 3 8 SetZone 198 9 SetMarkerPath 198 1 199 SetMarkerPathFlags 198 1 j SetZone 199 9 SetMarkerPath 199 1 200 SetMarkerPathFlags 199 1 j SetZone 200 9 SetMarkerPath 200 1 201 SetMarkerPathFlags 200 1 j SetZone 201 9 SetMarkerPath 201 1 202 SetMarkerPathFlags 201 1 j SetZone 202 9 SetMarkerPath 202 1 203 SetMarkerPathFlags 202 1 j SetZone 203 9 SetMarkerPath 203 1 204 SetZone 204 9 SetMarkerPath 204 1 203 SetMarkerPath 204 2 205 SetZone 205 9 SetMarkerPath 205 1 211 SetMarkerPath 205 2 206 SetMarkerPath 205 3 204 SetMarkerPath 205 4 207 SetZone 206 9 SetMarkerPath 206 1 205 SetZone 207 9 SetMarkerPath 207 1 205 SetMarkerPath 207 2 208 SetZone 208 9 SetMarkerPath 208 1 216 SetMarkerPath 208 2 207 SetMarkerPath 208 3 209 SetZone 209 9 SetMarkerPath 209 1 210 SetMarkerPath 209 2 208 SetZone 210 9 SetMarkerPath 210 1 209 SetZone 211 9 SetMarkerPath 211 1 205 SetMarkerPath 211 2 212 SetZone 212 9 SetMarkerPath 212 1 214 SetMarkerPath 212 2 213 SetMarkerPath 212 3 211 SetZone 213 9 SetMarkerPath 213 1 189 SetMarkerPath 213 2 212 SetZone 214 9 SetMarkerPath 214 1 215 SetMarkerPath 214 2 212 SetZone 215 9 SetMarkerPath 215 1 9 SetMarkerPath 215 2 214 SetZone 216 9 SetMarkerPath 216 1 217 SetMarkerPathFlags 216 1 j SetZone 217 9 SetMarkerPath 217 1 203 SetMarkerPathFlags 217 1 j SetZone 218 9 SetMarkerPath 218 1 217 SetMarkerPathFlags 218 1 j SetZone 219 10 SetMarkerPath 219 1 220 SetMarkerPath 219 2 9 SetZone 220 10 SetMarkerPath 220 1 219 SetMarkerPath 220 2 221 SetMarkerPath 220 3 223 SetZone 221 10 SetMarkerPath 221 1 220 SetMarkerPath 221 2 35 SetMarkerPath 221 3 222 SetMarkerPath 221 4 223 SetZone 222 10 SetMarkerPath 222 1 35 SetMarkerPath 222 2 221 SetMarkerPath 222 3 223 SetMarkerPath 222 4 224 SetZone 223 10 SetMarkerPath 223 1 222 SetMarkerPath 223 2 220 SetMarkerPath 223 3 224 SetMarkerPath 223 4 227 SetMarkerPath 223 5 221 SetZone 224 10 SetMarkerPath 224 1 226 SetMarkerPathFlags 224 1 j SetMarkerPath 224 2 222 SetMarkerPath 224 3 223 SetMarkerPath 224 4 227 SetMarkerPath 224 5 225 SetZone 225 10 SetMarkerPath 225 1 226 SetMarkerPathFlags 225 1 j SetMarkerPath 225 2 229 SetMarkerPath 225 3 227 SetMarkerPath 225 4 224 SetZone 226 10 SetMarkerPath 226 1 77 SetZone 227 10 SetMarkerPath 227 1 223 SetMarkerPath 227 2 229 SetMarkerPath 227 3 225 SetMarkerPath 227 4 224 SetMarkerPath 227 5 228 SetZone 228 10 SetMarkerPath 228 1 230 SetMarkerPathFlags 228 1 j SetMarkerPath 228 2 229 SetMarkerPath 228 3 227 SetMarkerPath 228 4 160 SetZone 229 10 SetMarkerPath 229 1 227 SetMarkerPath 229 2 225 SetMarkerPath 229 3 228 SetZone 230 10 SetMarkerPath 230 1 231 SetMarkerPath 230 2 228 SetMarkerPathFlags 230 2 j SetZone 231 10 SetMarkerPath 231 1 46 SetMarkerPath 231 2 230 SetZone 232 10 SetMarkerPath 232 1 159 SetMarkerPath 232 2 233 SetMarkerPath 232 3 46 SetZone 233 10 SetMarkerPath 233 1 158 SetMarkerPath 233 2 232 SetZone 234 11 SetMarkerPath 234 1 235 SetMarkerPath 234 2 52 SetMarkerPath 234 3 45 SetZone 235 11 SetMarkerPath 235 1 243 SetMarkerPath 235 2 234 SetMarkerPath 235 3 52 SetMarkerPath 235 4 236 SetZone 236 11 SetMarkerPath 236 1 61 SetMarkerPath 236 2 243 SetMarkerPath 236 3 235 SetZone 237 11 SetMarkerPath 237 1 14 SetMarkerPath 237 2 238 SetMarkerPath 237 3 64 SetMarkerPathFlags 237 3 j SetZone 238 11 SetMarkerPath 238 1 14 SetMarkerPath 238 2 237 SetMarkerPath 238 3 49 SetMarkerPath 238 4 239 SetMarkerPath 238 5 64 SetMarkerPathFlags 238 5 j SetMarkerPath 238 6 247 SetZone 239 11 SetMarkerPath 239 1 238 SetMarkerPath 239 2 240 SetMarkerPath 239 3 14 SetZone 240 11 SetMarkerPath 240 1 252 SetMarkerPath 240 2 239 SetMarkerPath 240 3 241 SetMarkerPath 240 4 242 SetMarkerPath 240 5 15 SetMarkerPathFlags 240 5 j SetMarkerPath 240 6 13 SetZone 241 11 SetMarkerPath 241 1 236 SetMarkerPath 241 2 13 SetMarkerPath 241 3 240 SetZone 242 11 SetMarkerPath 242 1 240 SetMarkerPath 242 2 244 SetZone 243 11 SetMarkerPath 243 1 236 SetMarkerPath 243 2 235 SetMarkerPath 243 3 61 SetMarkerPath 243 4 195 SetMarkerPath 243 5 45 SetZone 244 11 SetMarkerPath 244 1 242 SetMarkerPath 244 2 245 SetZone 245 11 SetMarkerPath 245 1 244 SetMarkerPath 245 2 246 SetZone 246 11 SetMarkerPath 246 1 245 SetMarkerPath 246 2 247 SetMarkerPath 246 3 248 SetMarkerPath 246 4 253 SetZone 247 11 SetMarkerPath 247 1 246 SetMarkerPath 247 2 16 SetMarkerPath 247 3 248 SetMarkerPath 247 4 249 SetZone 248 11 SetMarkerPath 248 1 247 SetMarkerPath 248 2 246 SetMarkerPath 248 3 249 SetMarkerPath 248 4 250 SetMarkerPath 248 5 7 SetZone 249 11 SetMarkerPath 249 1 247 SetMarkerPath 249 2 248 SetMarkerPath 249 3 16 SetMarkerPath 249 4 250 SetZone 250 11 SetMarkerPath 250 1 249 SetMarkerPath 250 2 248 SetMarkerPath 250 3 251 SetMarkerPath 250 4 7 SetZone 251 11 SetMarkerPath 251 1 252 SetMarkerPath 251 2 250 SetZone 252 11 SetMarkerPath 252 1 7 SetMarkerPath 252 2 251 SetZone 253 12 SetMarkerPath 253 1 246 SetMarkerPath 253 2 254 SetZone 254 12 SetMarkerPath 254 1 253 SetMarkerPath 254 2 255 SetZone 255 12 SetMarkerPath 255 1 12 SetMarkerPathFlags 255 1 j SetMarkerPath 255 2 254 SetMarkerPath 255 3 256 SetZone 256 12 SetMarkerPath 256 1 255 SetMarkerPath 256 2 257 SetZone 257 12 SetMarkerPath 257 1 256 SetMarkerPath 257 2 258 SetZone 258 12 SetMarkerPath 258 1 257 SetMarkerPath 258 2 259 SetZone 259 12 SetMarkerPath 259 1 37 SetMarkerPath 259 2 258 SetMarkerPath 259 3 38 SetMarkerPath 259 4 260 SetZone 260 12 SetMarkerPath 260 1 259 SetMarkerPath 260 2 261 SetZone 261 12 SetMarkerPath 261 1 262 SetMarkerPath 261 2 260 SetMarkerPath 261 3 281 SetMarkerPathFlags 261 3 j SetZone 262 12 SetMarkerPath 262 1 261 SetMarkerPath 262 2 263 SetZone 263 12 SetMarkerPath 263 1 46 SetZone 264 12 SetMarkerPath 264 1 254 SetZone 265 13 SetMarkerPath 265 1 266 SetZone 266 13 SetMarkerPath 266 1 265 SetMarkerPath 266 2 267 SetZone 267 13 SetMarkerPath 267 1 266 SetMarkerPath 267 2 268 SetMarkerPath 267 3 6 SetZone 268 13 SetMarkerPath 268 1 267 SetMarkerPath 268 2 269 SetZone 269 13 SetMarkerPath 269 1 268 SetMarkerPath 269 2 34 SetMarkerPath 269 3 270 SetZone 270 13 SetMarkerPath 270 1 269 SetMarkerPath 270 2 271 SetZone 271 13 SetMarkerPath 271 1 270 SetMarkerPath 271 2 272 SetMarkerPath 271 3 247 SetZone 272 13 SetMarkerPath 272 1 271 SetMarkerPath 272 2 273 SetZone 273 13 SetMarkerPath 273 1 272 SetMarkerPath 273 2 274 SetZone 274 13 SetMarkerPath 274 1 273 SetMarkerPath 274 2 275 SetZone 275 13 SetMarkerPath 275 1 274 SetMarkerPath 275 2 155 SetZone 276 14 SetMarkerPath 276 0 4 SetMarkerPath 276 1 277 SetZone 277 14 SetMarkerPath 277 0 276 SetMarkerPath 277 1 57 SetZone 278 14 SetMarkerPath 278 0 57 SetMarkerPath 278 1 11 SetMarkerPath 278 2 279 SetZone 279 14 SetMarkerPath 279 0 278 SetMarkerPath 279 1 280 SetZone 280 14 SetMarkerPath 280 0 279 SetMarkerPath 280 1 271 SetZone 281 12 SetMarkerPath 281 1 5 SetMarkerPath 281 2 263 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/cmt3.bot000066400000000000000000000444621475442401000256260ustar00rootroot00000000000000CreateMarker -956 265 -472 CreateMarker -789 191 -472 CreateMarker -798 37 -472 CreateMarker -972 -202 -440 CreateMarker -938 -392 -408 CreateMarker -725 -419 -392 CreateMarker -556 -281 -360 CreateMarker -664 7 -344 CreateMarker -666 244 -344 CreateMarker -568 363 -344 CreateMarker -440 114 -344 CreateMarker -948 474 -488 CreateMarker -891 639 -504 CreateMarker -686 659 -520 CreateMarker -510 658 -520 CreateMarker -484 492 -520 CreateMarker -219 473 -584 CreateMarker -190 629 -584 CreateMarker 191 694 -584 CreateMarker 9 600 -584 CreateMarker 646 691 -584 CreateMarker 874 670 -552 CreateMarker 921 870 -520 CreateMarker 1091 869 -520 CreateMarker 1111 691 -520 CreateMarker 1173 435 -528 CreateMarker 1016 337 -528 CreateMarker 919 472 -528 CreateMarker 1021 562 -528 CreateMarker 847 269 -480 CreateMarker 752 138 -416 CreateMarker 658 307 -352 CreateMarker 666 463 -320 CreateMarker 719 644 -304 CreateMarker 858 733 -304 CreateMarker 1030 839 -304 CreateMarker 1111 966 -256 CreateMarker 1125 1099 -192 CreateMarker 1101 1336 -160 CreateMarker 1057 1511 -160 CreateMarker 1185 1556 -160 CreateMarker 1303 1695 -160 CreateMarker 1411 1561 -160 CreateMarker 1435 470 -528 CreateMarker -247 121 -344 CreateMarker -81 153 -344 CreateMarker 225 124 -344 CreateMarker 92 261 -344 CreateMarker 68 440 -320 CreateMarker 12 640 -272 CreateMarker -43 813 -320 CreateMarker -109 1049 -344 CreateMarker 94 1020 -344 CreateMarker -232 1250 -344 CreateMarker -427 1225 -344 CreateMarker -588 1145 -344 CreateMarker -581 932 -344 CreateMarker -151 1578 -408 CreateMarker -63 1403 -456 CreateMarker 100 1394 -488 CreateMarker 108 1151 -488 CreateMarker 176 1263 -504 CreateMarker 333 1228 -520 CreateMarker 473 1290 -520 CreateMarker 493 1460 -528 CreateMarker 509 1636 -528 CreateMarker 838 1695 -528 CreateMarker 878 1532 -528 CreateMarker 1275 1479 -523 CreateMarker 1496 1551 -532 CreateMarker 1348 1410 -528 CreateMarker 1310 1685 -528 CreateMarker 938 1875 -528 CreateMarker 1048 2024 -608 CreateMarker 1197 1907 -672 CreateMarker 1065 1830 -704 CreateMarker 1258 1627 -704 CreateMarker 1074 1431 -704 CreateMarker 898 1614 -704 CreateMarker 1084 1239 -720 CreateMarker 1089 1125 -768 CreateMarker 1075 995 -816 CreateMarker 1235 934 -816 CreateMarker 1388 888 -816 CreateMarker 1309 765 -816 CreateMarker 1054 724 -896 CreateMarker 779 703 -896 CreateMarker 510 709 -904 CreateMarker 1544 892 -816 CreateMarker 1724 790 -816 CreateMarker 1740 447 -816 CreateMarker 1623 318 -816 CreateMarker 1496 287 -816 CreateMarker 1305 309 -816 CreateMarker 1129 301 -816 CreateMarker 1119 126 -816 CreateMarker 1171 -44 -816 CreateMarker 1300 -82 -816 CreateMarker 934 122 -816 CreateMarker 745 30 -816 CreateMarker 685 -286 -816 CreateMarker 421 -305 -816 CreateMarker 385 -86 -784 CreateMarker 1138 628 -896 CreateMarker 950 681 -896 CreateMarker 1011 839 -896 CreateMarker 639 714 -904 CreateMarker 1180 758 -864 CreateMarker 531 -207 -816 CreateMarker 769 653 -584 CreateMarker 682 816 -733 CreateMarker 1585 1558 -548 CreateMarker 1591 1564 -149 SetGoal 1 4 SetZone 1 1 SetMarkerPath 1 1 60 SetMarkerPath 1 2 62 SetMarkerPath 1 3 51 SetMarkerPath 1 4 63 SetZone 2 1 SetMarkerPath 2 1 61 SetMarkerPath 2 2 62 SetZone 4 4 SetMarkerPath 4 1 116 SetMarkerPath 4 2 75 SetMarkerPathFlags 4 2 j SetMarkerPath 4 3 38 SetMarkerPathFlags 4 3 j SetMarkerPath 4 4 74 SetMarkerPathFlags 4 4 j SetMarkerPath 4 5 73 SetMarkerPathFlags 4 5 j SetMarkerPath 4 6 10 SetGoal 5 1 SetZone 5 5 SetMarkerPath 5 0 121 SetMarkerPath 5 1 118 SetMarkerPath 5 2 120 SetGoal 7 6 SetZone 7 2 SetMarkerPath 7 1 77 SetMarkerPath 7 2 45 SetZone 8 4 SetMarkerPath 8 1 56 SetMarkerPath 8 2 117 SetZone 9 4 SetMarkerPath 9 1 105 SetMarkerPath 9 2 104 SetMarkerPath 9 3 21 SetZone 10 4 SetMarkerPath 10 1 4 SetMarkerPath 10 2 116 SetMarkerPath 10 3 74 SetMarkerPathFlags 10 3 j SetMarkerPath 10 4 75 SetMarkerPathFlags 10 4 j SetMarkerPath 10 5 38 SetMarkerPathFlags 10 5 j SetMarkerPath 10 6 73 SetMarkerPathFlags 10 6 j SetGoal 12 20 SetZone 12 5 SetMarkerPath 12 1 135 SetMarkerPath 12 2 136 SetMarkerPath 12 3 137 SetMarkerPath 12 4 138 SetZone 13 6 SetMarkerPath 13 0 147 SetZone 14 5 SetMarkerPath 14 0 102 SetGoal 15 9 SetZone 15 3 SetMarkerPath 15 1 17 SetMarkerPath 15 2 155 SetMarkerPathFlags 15 2 j SetMarkerPath 15 3 156 SetMarkerPathFlags 15 3 j SetMarkerPath 15 4 154 SetMarkerPathFlags 15 4 j SetMarkerPath 15 5 153 SetMarkerPathFlags 15 5 j SetZone 16 7 SetMarkerPath 16 0 17 SetMarkerPath 16 1 157 SetMarkerPath 16 2 15 SetZone 17 3 SetMarkerPath 17 1 15 SetGoal 18 7 SetZone 18 2 SetMarkerPath 18 1 78 SetMarkerPath 18 2 80 SetGoal 19 11 SetZone 19 7 SetMarkerPath 19 1 162 SetZone 20 7 SetMarkerPath 20 0 21 SetMarkerPath 20 1 161 SetMarkerPath 20 2 160 SetMarkerPath 20 3 37 SetMarkerPath 20 4 107 SetMarkerPath 20 5 168 SetZone 21 4 SetMarkerPath 21 1 9 SetMarkerPath 21 2 106 SetMarkerPath 21 3 107 SetGoal 22 17 SetZone 22 3 SetMarkerPath 22 1 35 SetMarkerPath 22 2 96 SetMarkerPath 22 3 95 SetZone 23 3 SetMarkerPath 23 1 93 SetMarkerPath 23 2 92 SetZone 24 6 SetMarkerPath 24 1 144 SetMarkerPath 24 2 163 SetZone 25 7 SetMarkerPath 25 1 158 SetMarkerPath 25 2 159 SetZone 26 5 SetMarkerPath 26 1 122 SetMarkerPath 26 2 123 SetGoal 27 15 SetZone 27 6 SetMarkerPath 27 1 28 SetMarkerPath 27 2 165 SetGoal 28 15 SetZone 28 6 SetMarkerPath 28 1 27 SetMarkerPath 28 2 165 SetGoal 29 15 SetZone 29 6 SetMarkerPath 29 1 30 SetMarkerPath 29 2 164 SetMarkerPath 29 3 165 SetGoal 30 15 SetZone 30 6 SetMarkerPath 30 1 29 SetMarkerPath 30 2 27 SetMarkerPath 30 3 165 SetGoal 31 16 SetZone 31 3 SetMarkerPath 31 1 57 SetMarkerPath 31 2 97 SetMarkerPath 31 3 95 SetMarkerPathFlags 31 3 j SetGoal 32 16 SetZone 32 3 SetMarkerPath 32 1 57 SetMarkerPath 32 2 97 SetMarkerPath 32 3 22 SetMarkerPathFlags 32 3 j SetGoal 33 18 SetZone 33 3 SetMarkerPath 33 1 34 SetMarkerPath 33 2 93 SetMarkerPath 33 3 92 SetGoal 34 18 SetZone 34 3 SetMarkerPath 34 1 92 SetMarkerPath 34 2 33 SetGoal 35 17 SetZone 35 3 SetMarkerPath 35 1 95 SetMarkerPath 35 2 22 SetGoal 36 10 SetZone 36 7 SetMarkerPath 36 1 37 SetMarkerPath 36 2 161 SetMarkerPath 36 3 162 SetMarkerPath 36 4 160 SetMarkerPath 36 5 168 SetGoal 37 10 SetZone 37 7 SetMarkerPath 37 1 160 SetMarkerPath 37 2 36 SetMarkerPath 37 3 159 SetMarkerPath 37 4 48 SetMarkerPath 37 5 20 SetMarkerPath 37 6 168 SetGoal 38 5 SetZone 38 2 SetMarkerPath 38 1 73 SetMarkerPath 38 2 75 SetGoal 39 12 SetZone 39 6 SetMarkerPath 39 1 40 SetMarkerPath 39 2 153 SetGoal 40 12 SetZone 40 6 SetMarkerPath 40 1 153 SetMarkerPath 40 2 39 SetGoal 41 23 SetZone 41 1 SetMarkerPath 41 1 66 SetMarkerPath 41 2 42 SetMarkerPath 41 3 67 SetGoal 42 3 SetZone 42 1 SetMarkerPath 42 1 41 SetMarkerPath 42 2 67 SetMarkerPath 42 3 70 SetGoal 43 8 SetZone 43 2 SetMarkerPath 43 0 169 SetMarkerPath 43 1 80 SetGoal 44 2 SetZone 44 4 SetMarkerPath 44 1 111 SetMarkerPath 44 2 114 SetMarkerPath 44 3 113 SetMarkerPath 44 4 59 SetGoal 45 6 SetZone 45 2 SetMarkerPath 45 1 7 SetMarkerPath 45 2 78 SetMarkerPath 45 3 79 SetGoal 46 13 SetZone 46 6 SetMarkerPath 46 1 150 SetMarkerPath 46 2 149 SetGoal 47 24 SetZone 47 5 SetMarkerPath 47 1 125 SetMarkerPath 47 2 126 SetGoal 48 10 SetZone 48 7 SetMarkerPath 48 1 159 SetMarkerPath 48 2 49 SetMarkerPath 48 3 37 SetMarkerPath 48 4 160 SetGoal 49 10 SetZone 49 7 SetMarkerPath 49 1 48 SetMarkerPath 49 2 160 SetGoal 50 4 SetZone 50 1 SetMarkerPath 50 1 62 SetMarkerPath 50 2 51 SetGoal 51 4 SetZone 51 1 SetMarkerPath 51 1 62 SetMarkerPath 51 2 50 SetMarkerPath 51 3 1 SetMarkerPath 51 4 63 SetGoal 52 3 SetZone 52 1 SetMarkerPath 52 1 68 SetMarkerPath 52 2 70 SetMarkerPath 52 3 69 SetGoal 53 19 SetZone 53 5 SetMarkerPath 53 0 128 SetMarkerPath 53 1 54 SetMarkerPath 53 2 130 SetMarkerPath 53 3 12 SetGoal 54 19 SetZone 54 5 SetMarkerPath 54 0 12 SetMarkerPath 54 1 127 SetMarkerPath 54 2 53 SetGoal 55 2 SetZone 55 4 SetMarkerPath 55 1 113 SetMarkerPath 55 2 56 SetGoal 56 2 SetZone 56 4 SetMarkerPath 56 1 113 SetMarkerPath 56 2 8 SetMarkerPath 56 3 55 SetMarkerPath 56 4 117 SetGoal 57 16 SetZone 57 3 SetMarkerPath 57 1 31 SetMarkerPath 57 2 32 SetMarkerPath 57 3 98 SetMarkerPath 57 4 97 SetGoal 58 6 SetZone 58 2 SetMarkerPath 58 1 76 SetMarkerPath 58 2 79 SetMarkerPath 58 3 77 SetGoal 59 2 SetZone 59 4 SetMarkerPath 59 1 111 SetMarkerPath 59 2 44 SetZone 60 1 SetMarkerPath 60 1 61 SetMarkerPath 60 2 1 SetMarkerPath 60 3 71 SetZone 61 1 SetMarkerPath 61 1 60 SetMarkerPath 61 2 62 SetMarkerPath 61 3 2 SetZone 62 1 SetMarkerPath 62 1 61 SetMarkerPath 62 2 1 SetMarkerPath 62 3 50 SetMarkerPath 62 4 2 SetMarkerPath 62 5 51 SetZone 63 1 SetMarkerPath 63 1 1 SetMarkerPath 63 2 51 SetMarkerPath 63 3 64 SetZone 64 1 SetMarkerPath 64 1 63 SetMarkerPath 64 2 65 SetZone 65 1 SetMarkerPath 65 1 64 SetMarkerPath 65 2 66 SetZone 66 1 SetMarkerPath 66 1 65 SetMarkerPath 66 2 41 SetZone 67 1 SetMarkerPath 67 1 42 SetMarkerPath 67 2 41 SetMarkerPath 67 3 68 SetMarkerPath 67 4 62 SetMarkerPathFlags 67 4 j SetZone 68 1 SetMarkerPath 68 1 67 SetMarkerPath 68 2 69 SetMarkerPath 68 3 52 SetMarkerPath 68 4 61 SetMarkerPathFlags 68 4 j SetZone 69 1 SetMarkerPath 69 1 68 SetMarkerPath 69 2 52 SetMarkerPath 69 3 75 SetMarkerPathFlags 69 3 j SetMarkerPath 69 4 38 SetMarkerPathFlags 69 4 j SetMarkerPath 69 5 73 SetMarkerPathFlags 69 5 j SetMarkerPath 69 6 74 SetMarkerPathFlags 69 6 j SetZone 70 1 SetMarkerPath 70 1 52 SetMarkerPath 70 2 42 SetMarkerPath 70 3 104 SetZone 71 2 SetMarkerPath 71 1 60 SetMarkerPath 71 2 72 SetZone 72 2 SetMarkerPath 72 1 71 SetMarkerPath 72 2 73 SetZone 73 2 SetMarkerPath 73 1 72 SetMarkerPath 73 2 38 SetMarkerPath 73 3 74 SetZone 74 2 SetMarkerPath 74 1 73 SetMarkerPath 74 2 75 SetZone 75 2 SetMarkerPath 75 1 74 SetMarkerPath 75 2 38 SetMarkerPath 75 3 76 SetZone 76 2 SetMarkerPath 76 1 75 SetMarkerPath 76 2 77 SetMarkerPath 76 3 58 SetZone 77 2 SetMarkerPath 77 1 76 SetMarkerPath 77 2 58 SetMarkerPath 77 3 7 SetMarkerPath 77 4 79 SetZone 78 2 SetMarkerPath 78 1 45 SetMarkerPath 78 2 79 SetMarkerPath 78 3 18 SetZone 79 2 SetMarkerPath 79 1 58 SetMarkerPath 79 2 77 SetMarkerPath 79 3 45 SetMarkerPath 79 4 78 SetZone 80 2 SetMarkerPath 80 0 169 SetMarkerPath 80 1 18 SetMarkerPath 80 2 43 SetZone 81 2 SetMarkerPath 81 0 169 SetMarkerPath 81 3 82 SetZone 82 3 SetMarkerPath 82 0 43 SetMarkerPath 82 1 81 SetMarkerPath 82 3 83 SetZone 83 3 SetMarkerPath 83 1 82 SetMarkerPath 83 2 84 SetZone 84 3 SetMarkerPath 84 1 83 SetMarkerPath 84 2 88 SetZone 85 3 SetMarkerPath 85 1 88 SetMarkerPath 85 2 86 SetMarkerPath 85 3 103 SetMarkerPathFlags 85 3 j SetMarkerPath 85 4 15 SetMarkerPathFlags 85 4 j SetMarkerPath 85 5 153 SetMarkerPathFlags 85 5 j SetMarkerPath 85 6 154 SetMarkerPathFlags 85 6 j SetZone 86 3 SetMarkerPath 86 1 85 SetMarkerPath 86 2 87 SetMarkerPathFlags 86 2 j SetMarkerPath 86 3 15 SetMarkerPathFlags 86 3 j SetMarkerPath 86 4 154 SetMarkerPathFlags 86 4 j SetMarkerPath 86 5 155 SetMarkerPathFlags 86 5 j SetMarkerPath 86 6 153 SetMarkerPathFlags 86 6 j SetZone 87 3 SetMarkerPath 87 1 86 SetMarkerPath 87 2 88 SetMarkerPath 87 3 89 SetZone 88 3 SetMarkerPath 88 1 84 SetMarkerPath 88 2 85 SetMarkerPath 88 3 87 SetZone 89 3 SetMarkerPath 89 1 87 SetMarkerPath 89 2 90 SetZone 90 3 SetMarkerPath 90 1 89 SetMarkerPath 90 2 91 SetZone 91 3 SetMarkerPath 91 1 90 SetMarkerPath 91 2 92 SetZone 92 3 SetMarkerPath 92 1 91 SetMarkerPath 92 2 34 SetMarkerPath 92 3 33 SetMarkerPath 92 4 23 SetMarkerPath 92 5 93 SetZone 93 3 SetMarkerPath 93 1 33 SetMarkerPath 93 2 23 SetMarkerPath 93 3 92 SetMarkerPath 93 4 94 SetZone 94 3 SetMarkerPath 94 1 93 SetMarkerPath 94 2 95 SetZone 95 3 SetMarkerPath 95 1 94 SetMarkerPath 95 2 35 SetMarkerPath 95 3 96 SetMarkerPath 95 4 22 SetZone 96 3 SetMarkerPath 96 1 95 SetMarkerPath 96 2 22 SetMarkerPath 96 3 97 SetZone 97 3 SetMarkerPath 97 1 96 SetMarkerPath 97 2 32 SetMarkerPath 97 3 31 SetMarkerPath 97 4 57 SetZone 98 3 SetMarkerPath 98 1 57 SetMarkerPath 98 2 99 SetZone 99 3 SetMarkerPath 99 1 98 SetMarkerPath 99 2 100 SetZone 100 3 SetMarkerPath 100 1 99 SetMarkerPath 100 2 101 SetMarkerPath 100 3 102 SetMarkerPath 100 4 12 SetMarkerPathFlags 100 4 j SetMarkerPath 100 5 135 SetMarkerPathFlags 100 5 j SetZone 101 3 SetMarkerPath 101 1 100 SetMarkerPath 101 2 102 SetMarkerPath 101 3 12 SetMarkerPathFlags 101 3 j SetZone 102 3 SetMarkerPath 102 1 101 SetMarkerPath 102 2 100 SetZone 103 3 SetMarkerPath 103 1 15 SetMarkerPathFlags 103 1 j SetMarkerPath 103 2 152 SetMarkerPathFlags 103 2 j SetMarkerPath 103 3 153 SetMarkerPathFlags 103 3 j SetZone 104 4 SetMarkerPath 104 1 70 SetMarkerPath 104 2 105 SetMarkerPath 104 3 9 SetZone 105 4 SetMarkerPath 105 1 104 SetMarkerPath 105 2 9 SetMarkerPath 105 3 107 SetZone 106 4 SetMarkerPath 106 1 21 SetMarkerPath 106 2 107 SetMarkerPath 106 3 19 SetMarkerPathFlags 106 3 j SetZone 107 4 SetMarkerPath 107 1 106 SetMarkerPath 107 2 105 SetMarkerPath 107 3 21 SetMarkerPath 107 4 108 SetZone 108 4 SetMarkerPath 108 1 107 SetMarkerPath 108 2 109 SetZone 109 4 SetMarkerPath 109 1 108 SetMarkerPath 109 2 110 SetZone 110 4 SetMarkerPath 110 1 109 SetMarkerPath 110 2 112 SetMarkerPath 110 3 111 SetZone 111 4 SetMarkerPath 111 1 110 SetMarkerPath 111 2 59 SetMarkerPath 111 3 112 SetMarkerPath 111 4 44 SetMarkerPath 111 5 113 SetZone 112 4 SetMarkerPath 112 1 110 SetMarkerPath 112 2 111 SetZone 113 4 SetMarkerPath 113 1 111 SetMarkerPath 113 2 114 SetMarkerPath 113 3 55 SetMarkerPath 113 4 56 SetMarkerPath 113 5 44 SetZone 114 4 SetMarkerPath 114 1 113 SetMarkerPath 114 2 44 SetMarkerPath 114 3 115 SetZone 115 4 SetMarkerPath 115 1 114 SetMarkerPath 115 2 116 SetZone 116 4 SetMarkerPath 116 1 115 SetMarkerPath 116 2 4 SetMarkerPath 116 3 10 SetZone 117 5 SetMarkerPath 117 1 8 SetMarkerPath 117 2 56 SetMarkerPath 117 3 118 SetZone 118 5 SetMarkerPath 118 1 117 SetMarkerPath 118 2 5 SetMarkerPath 118 3 119 SetZone 119 5 SetMarkerPath 119 0 121 SetMarkerPath 119 1 118 SetZone 120 5 SetMarkerPath 120 1 5 SetMarkerPath 120 2 121 SetZone 121 5 SetMarkerPath 121 0 119 SetMarkerPath 121 1 120 SetMarkerPath 121 2 122 SetMarkerPath 121 3 5 SetZone 122 5 SetMarkerPath 122 1 121 SetMarkerPath 122 2 123 SetMarkerPath 122 4 26 SetZone 123 5 SetMarkerPath 123 1 122 SetMarkerPath 123 2 124 SetMarkerPath 123 4 26 SetZone 124 5 SetMarkerPath 124 1 123 SetMarkerPath 124 2 125 SetZone 125 5 SetMarkerPath 125 1 47 SetMarkerPath 125 2 124 SetZone 126 5 SetMarkerPath 126 1 47 SetMarkerPath 126 2 127 SetMarkerPath 126 3 132 SetMarkerPath 126 4 12 SetMarkerPathFlags 126 4 j SetMarkerPath 126 5 138 SetMarkerPathFlags 126 5 j SetZone 127 5 SetMarkerPath 127 1 126 SetMarkerPath 127 2 54 SetMarkerPath 127 3 12 SetMarkerPathFlags 127 3 j SetMarkerPath 127 4 138 SetMarkerPathFlags 127 4 j SetZone 128 5 SetMarkerPath 128 0 53 SetMarkerPath 128 1 130 SetMarkerPath 128 2 131 SetMarkerPath 128 3 129 SetMarkerPath 128 4 12 SetMarkerPathFlags 128 4 j SetMarkerPath 128 5 136 SetMarkerPathFlags 128 5 j SetZone 129 5 SetMarkerPath 129 0 171 SetMarkerPath 129 1 131 SetMarkerPath 129 2 128 SetMarkerPath 129 3 130 SetZone 130 5 SetMarkerPath 130 1 53 SetMarkerPath 130 2 128 SetMarkerPath 130 3 129 SetZone 131 5 SetMarkerPath 131 1 128 SetMarkerPath 131 2 129 SetZone 132 5 SetMarkerPath 132 1 126 SetMarkerPath 132 2 133 SetMarkerPath 132 3 12 SetMarkerPathFlags 132 3 j SetMarkerPath 132 4 135 SetMarkerPathFlags 132 4 j SetZone 133 5 SetMarkerPath 133 0 135 SetMarkerPath 133 1 132 SetMarkerPath 133 2 134 SetZone 134 5 SetMarkerPath 134 1 133 SetMarkerPath 134 2 135 SetMarkerPath 134 3 136 SetZone 135 5 SetMarkerPath 135 1 134 SetMarkerPath 135 2 12 SetMarkerPath 135 3 138 SetZone 136 5 SetMarkerPath 136 1 12 SetMarkerPath 136 2 137 SetMarkerPath 136 3 134 SetZone 137 5 SetMarkerPath 137 1 12 SetMarkerPath 137 2 138 SetMarkerPath 137 3 136 SetMarkerPath 137 4 139 SetZone 138 5 SetMarkerPath 138 1 137 SetMarkerPath 138 2 12 SetMarkerPath 138 3 135 SetZone 139 6 SetMarkerPath 139 1 140 SetMarkerPath 139 2 137 SetZone 140 6 SetMarkerPath 140 1 141 SetMarkerPath 140 2 139 SetZone 141 6 SetMarkerPath 141 1 140 SetMarkerPath 141 2 142 SetMarkerPath 141 3 27 SetMarkerPathFlags 141 3 j SetZone 142 6 SetMarkerPath 142 1 143 SetMarkerPath 142 2 144 SetMarkerPath 142 3 141 SetZone 143 6 SetMarkerPath 143 1 148 SetMarkerPath 143 2 142 SetMarkerPath 143 3 144 SetZone 144 6 SetMarkerPath 144 1 143 SetMarkerPath 144 2 145 SetMarkerPath 144 3 142 SetMarkerPath 144 4 24 SetMarkerPath 144 5 167 SetZone 145 6 SetMarkerPath 145 1 144 SetMarkerPath 145 2 29 SetMarkerPath 145 3 28 SetMarkerPath 145 4 27 SetMarkerPath 145 5 165 SetMarkerPath 145 6 164 SetMarkerPath 145 7 163 SetZone 146 6 SetMarkerPath 146 0 166 SetMarkerPath 146 1 164 SetZone 147 6 SetMarkerPath 147 0 166 SetMarkerPath 147 1 13 SetZone 148 6 SetMarkerPath 148 1 149 SetMarkerPath 148 2 143 SetZone 149 6 SetMarkerPath 149 1 46 SetMarkerPath 149 2 148 SetZone 150 6 SetMarkerPath 150 1 151 SetMarkerPath 150 2 46 SetZone 151 6 SetMarkerPath 151 1 152 SetMarkerPath 151 2 150 SetZone 152 6 SetMarkerPath 152 1 153 SetMarkerPath 152 2 151 SetZone 153 6 SetMarkerPath 153 1 40 SetMarkerPath 153 2 39 SetMarkerPath 153 3 152 SetMarkerPath 153 4 154 SetZone 154 7 SetMarkerPath 154 1 155 SetMarkerPath 154 2 153 SetZone 155 7 SetMarkerPath 155 1 156 SetMarkerPath 155 2 154 SetMarkerPath 155 3 158 SetZone 156 7 SetMarkerPath 156 1 157 SetMarkerPath 156 2 155 SetZone 157 7 SetMarkerPath 157 1 156 SetMarkerPath 157 2 16 SetZone 158 7 SetMarkerPath 158 1 155 SetMarkerPath 158 2 25 SetZone 159 7 SetMarkerPath 159 1 25 SetMarkerPath 159 2 48 SetMarkerPath 159 3 37 SetZone 160 7 SetMarkerPath 160 1 49 SetMarkerPath 160 2 37 SetMarkerPath 160 3 20 SetMarkerPath 160 4 36 SetMarkerPath 160 5 168 SetMarkerPath 160 6 48 SetZone 161 7 SetMarkerPath 161 1 36 SetMarkerPath 161 2 20 SetMarkerPath 161 3 162 SetMarkerPath 161 4 168 SetZone 162 7 SetMarkerPath 162 1 161 SetMarkerPath 162 2 19 SetMarkerPath 162 3 36 SetMarkerPath 162 4 168 SetZone 163 6 SetMarkerPath 163 1 145 SetMarkerPath 163 2 24 SetZone 164 6 SetMarkerPath 164 1 165 SetMarkerPath 164 2 145 SetMarkerPath 164 3 146 SetMarkerPath 164 4 29 SetZone 165 6 SetMarkerPath 165 1 164 SetMarkerPath 165 2 145 SetMarkerPath 165 3 27 SetMarkerPath 165 4 28 SetMarkerPath 165 5 30 SetMarkerPath 165 6 29 SetMarkerPath 165 7 167 SetZone 166 6 SetMarkerPath 166 0 147 SetMarkerPath 166 1 146 SetZone 167 6 SetMarkerPath 167 1 145 SetMarkerPath 167 2 144 SetMarkerPath 167 3 165 SetMarkerPath 167 4 28 SetZone 168 7 SetMarkerPath 168 1 36 SetMarkerPath 168 2 37 SetMarkerPath 168 3 20 SetMarkerPath 168 4 161 SetMarkerPath 168 5 162 SetMarkerPath 168 6 160 SetZone 169 2 SetMarkerPath 169 0 81 SetMarkerPath 169 1 80 SetMarkerPath 169 2 43 SetZone 170 6 SetMarkerPath 170 0 147 SetZone 171 5 SetMarkerPath 171 1 172 SetZone 172 3 SetMarkerPath 172 0 102 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/cmt4.bot000066400000000000000000000432531475442401000256240ustar00rootroot00000000000000CreateMarker -1044 -1366 -488 CreateMarker -1044 -1574 -488 CreateMarker -701 -1244 -456 CreateMarker -720 -1398 -488 CreateMarker -856 -1649 -488 CreateMarker -722 -1642 -488 CreateMarker -625 -1740 -456 CreateMarker -538 -1919 -456 CreateMarker -367 -1757 -456 CreateMarker -392 -1591 -376 CreateMarker -221 -1477 -360 CreateMarker 83 -1319 -360 CreateMarker 240 -1366 -360 CreateMarker 316 -1199 -328 CreateMarker 332 -1034 -264 CreateMarker 67 -1632 -360 CreateMarker 251 -1649 -376 CreateMarker 385 -1635 -408 CreateMarker 592 -1566 -456 CreateMarker 578 -1395 -488 CreateMarker -8 -944 -296 CreateMarker 181 -950 -280 CreateMarker 337 -918 -264 CreateMarker 654 -1068 -264 CreateMarker 852 -1067 -200 CreateMarker 1118 -1085 -152 CreateMarker 1116 -937 -136 CreateMarker 959 -411 -136 CreateMarker 615 -607 -136 CreateMarker 439 -651 -136 CreateMarker 218 -622 -136 CreateMarker 236 -34 -136 CreateMarker 451 1 -136 CreateMarker 626 -250 -136 CreateMarker 211 234 -136 CreateMarker 1 -189 -136 CreateMarker 34 -679 -424 CreateMarker 115 -498 -424 CreateMarker 104 -125 -424 CreateMarker 284 64 -424 CreateMarker 547 -136 -424 CreateMarker 544 -588 -424 CreateMarker 91 100 -424 CreateMarker 532 85 -424 CreateMarker 425 -218 -440 CreateMarker 422 -424 -440 CreateMarker 214 -432 -440 CreateMarker 227 -216 -440 CreateMarker -12 -902 -504 CreateMarker -17 -1100 -600 CreateMarker 141 -1020 -616 CreateMarker -17 -1256 -616 CreateMarker 162 -1328 -616 CreateMarker 325 -1352 -616 CreateMarker 331 -1205 -616 CreateMarker 390 -1041 -616 CreateMarker 477 -891 -616 CreateMarker 616 -947 -616 CreateMarker 567 -1212 -520 CreateMarker 562 -1093 -536 CreateMarker 731 -1297 -520 CreateMarker 684 -1499 -520 CreateMarker 849 -1242 -520 CreateMarker 882 -1588 -520 CreateMarker 913 -1405 -520 CreateMarker 1154 -1350 -520 CreateMarker 1150 -1073 -456 CreateMarker 1051 -870 -456 CreateMarker 1031 -1525 -520 CreateMarker 1053 -1655 -520 CreateMarker 1182 -1644 -520 CreateMarker 1040 -1873 -232 CreateMarker 1005 -892 -552 CreateMarker 874 -648 -552 CreateMarker 873 -312 -552 CreateMarker 713 -308 -552 CreateMarker 100 -308 -552 CreateMarker -230 -312 -552 CreateMarker -85 -303 -552 CreateMarker -200 -453 -584 CreateMarker -612 -527 -456 CreateMarker -414 -480 -456 CreateMarker -189 -689 -584 CreateMarker -208 -952 -619 CreateMarker -206 -1143 -648 CreateMarker -428 -1135 -679 CreateMarker -617 -1141 -744 CreateMarker -701 -1196 -744 CreateMarker -672 -1065 -744 CreateMarker -976 -920 -744 CreateMarker -999 -912 -456 CreateMarker -682 -960 -744 CreateMarker 316 -129 -328 CreateMarker 511 -1090 -264 CreateMarker -20 -525 -424 CreateMarker 877 -495 -552 CreateMarker -827 -1102 -744 CreateMarker -953 -1064 -744 CreateMarker -920 -1169 -744 SetGoal 1 15 SetZone 1 8 SetMarkerPath 1 1 166 SetMarkerPath 1 2 83 SetMarkerPath 1 3 137 SetMarkerPath 1 4 134 SetMarkerPath 1 5 135 SetMarkerPath 1 6 136 SetGoal 2 12 SetZone 2 4 SetMarkerPath 2 1 47 SetMarkerPath 2 2 125 SetGoal 3 17 SetZone 3 7 SetMarkerPath 3 1 169 SetMarkerPath 3 2 171 SetMarkerPath 3 3 172 SetGoal 4 17 SetZone 4 7 SetMarkerPath 4 1 171 SetMarkerPath 4 2 172 SetGoal 5 16 SetZone 5 7 SetMarkerPath 5 1 6 SetMarkerPath 5 2 4 SetGoal 6 17 SetZone 6 7 SetMarkerPath 6 1 5 SetMarkerPath 6 2 170 SetGoal 7 21 SetZone 7 5 SetMarkerPath 7 1 132 SetMarkerPath 7 2 15 SetMarkerPath 7 3 8 SetGoal 8 14 SetZone 8 5 SetMarkerPath 8 1 71 SetMarkerPath 8 2 7 SetMarkerPath 8 3 132 SetGoal 9 12 SetZone 9 4 SetMarkerPath 9 1 45 SetMarkerPath 9 2 54 SetMarkerPath 9 3 120 SetGoal 10 8 SetZone 10 3 SetMarkerPath 10 1 91 SetMarkerPath 10 2 93 SetMarkerPath 10 3 41 SetMarkerPath 10 4 90 SetMarkerPath 10 5 94 SetMarkerPath 10 6 95 SetGoal 11 8 SetZone 11 3 SetMarkerPath 11 1 93 SetMarkerPath 11 2 12 SetGoal 12 8 SetZone 12 3 SetMarkerPath 12 1 96 SetMarkerPath 12 2 11 SetMarkerPath 12 3 95 SetGoal 13 8 SetZone 13 3 SetMarkerPath 13 1 17 SetMarkerPath 13 2 98 SetMarkerPath 13 3 97 SetGoal 14 8 SetZone 14 3 SetMarkerPath 14 1 96 SetMarkerPath 14 2 97 SetZone 15 5 SetMarkerPath 15 1 7 SetMarkerPath 15 2 69 SetMarkerPath 15 3 129 SetZone 16 2 SetMarkerPath 16 1 100 SetMarkerPath 16 2 99 SetGoal 17 8 SetZone 17 3 SetMarkerPath 17 1 13 SetMarkerPath 17 2 98 SetGoal 18 9 SetZone 18 2 SetMarkerPath 18 1 183 SetMarkerPath 18 2 113 SetMarkerPath 18 3 31 SetMarkerPath 18 4 108 SetGoal 19 9 SetZone 19 2 SetMarkerPath 19 1 30 SetMarkerPath 19 2 20 SetMarkerPath 19 3 113 SetMarkerPath 19 4 183 SetGoal 20 9 SetZone 20 2 SetMarkerPath 20 1 19 SetMarkerPath 20 2 183 SetMarkerPath 20 3 112 SetGoal 21 1 SetZone 21 1 SetMarkerPath 21 1 159 SetMarkerPath 21 2 31 SetMarkerPathFlags 21 2 j SetMarkerPath 21 3 22 SetMarkerPath 21 4 28 SetMarkerPathFlags 21 4 6 SetZone 22 1 SetMarkerPath 22 1 63 SetMarkerPath 22 2 153 SetGoal 23 4 SetZone 23 1 SetMarkerPath 23 1 24 SetMarkerPath 23 2 57 SetMarkerPath 23 3 59 SetGoal 24 4 SetZone 24 1 SetMarkerPath 24 1 23 SetMarkerPath 24 2 57 SetMarkerPath 24 3 59 SetMarkerPath 24 4 31 SetMarkerPath 24 5 21 SetMarkerPath 24 6 107 SetMarkerPathFlags 24 6 j SetGoal 26 21 SetZone 26 6 SetMarkerPath 26 1 27 SetMarkerPath 26 2 147 SetMarkerPath 26 3 37 SetGoal 27 21 SetZone 27 6 SetMarkerPath 27 1 26 SetMarkerPath 27 2 37 SetGoal 28 1 SetZone 28 1 SetMarkerPath 28 1 21 SetZone 29 6 SetMarkerPath 29 1 145 SetMarkerPath 29 2 146 SetZone 30 2 SetMarkerPath 30 1 113 SetMarkerPath 30 2 19 SetGoal 31 2 SetZone 31 1 SetMarkerPath 31 1 21 SetMarkerPathFlags 31 1 j SetGoal 32 3 SetZone 32 1 SetMarkerPath 32 1 152 SetMarkerPath 32 2 33 SetGoal 33 3 SetZone 33 1 SetMarkerPath 33 1 32 SetMarkerPath 33 2 152 SetMarkerPath 33 3 156 SetGoal 34 20 SetZone 34 6 SetMarkerPath 34 1 141 SetMarkerPath 34 2 142 SetGoal 35 21 SetZone 35 6 SetMarkerPath 35 1 36 SetGoal 36 21 SetZone 36 6 SetMarkerPath 36 1 37 SetMarkerPath 36 2 35 SetGoal 37 21 SetZone 37 6 SetMarkerPath 37 1 27 SetMarkerPath 37 2 36 SetMarkerPath 37 3 26 SetMarkerPath 37 4 147 SetGoal 38 3 SetZone 38 1 SetMarkerPath 38 1 158 SetGoal 39 18 SetZone 39 7 SetMarkerPath 39 1 180 SetMarkerPath 39 2 58 SetGoal 40 7 SetZone 40 3 SetMarkerPath 40 1 91 SetMarkerPath 40 2 72 SetMarkerPath 40 3 90 SetGoal 41 7 SetZone 41 3 SetMarkerPath 41 1 92 SetMarkerPath 41 2 42 SetMarkerPath 41 3 10 SetGoal 42 7 SetZone 42 3 SetMarkerPath 42 1 72 SetMarkerPath 42 2 41 SetGoal 43 18 SetZone 43 7 SetMarkerPath 43 1 181 SetGoal 44 18 SetZone 44 7 SetMarkerPath 44 1 181 SetMarkerPath 44 2 179 SetMarkerPath 44 3 186 SetZone 45 4 SetMarkerPath 45 1 120 SetMarkerPath 45 2 9 SetZone 46 4 SetMarkerPath 46 1 122 SetMarkerPath 46 2 123 SetGoal 47 12 SetZone 47 4 SetMarkerPath 47 1 61 SetMarkerPath 47 2 2 SetGoal 48 12 SetZone 48 4 SetMarkerPath 48 1 121 SetMarkerPath 48 2 125 SetGoal 49 10 SetZone 49 4 SetMarkerPath 49 1 50 SetMarkerPath 49 2 53 SetGoal 50 10 SetZone 50 4 SetMarkerPath 50 1 117 SetMarkerPath 50 2 49 SetGoal 51 10 SetZone 51 4 SetMarkerPath 51 1 52 SetMarkerPath 51 2 80 SetGoal 52 10 SetZone 52 4 SetMarkerPath 52 1 84 SetMarkerPath 52 2 51 SetGoal 53 11 SetZone 53 4 SetMarkerPath 53 1 49 SetMarkerPath 53 2 123 SetMarkerPath 53 3 87 SetMarkerPath 53 4 73 SetGoal 54 12 SetZone 54 4 SetMarkerPath 54 1 125 SetMarkerPath 54 2 9 SetZone 55 9 SetGoal 57 4 SetZone 57 1 SetMarkerPath 57 1 24 SetMarkerPath 57 2 161 SetMarkerPath 57 3 23 SetZone 58 7 SetMarkerPath 58 0 61 SetMarkerPath 58 1 39 SetMarkerPath 58 2 180 SetMarkerPath 58 3 2 SetZone 59 1 SetMarkerPath 59 0 60 SetMarkerPath 59 1 23 SetMarkerPath 59 2 24 SetZone 60 3 SetMarkerPath 60 1 91 SetZone 61 4 SetMarkerPath 61 1 47 SetGoal 62 3 SetZone 62 1 SetMarkerPath 62 1 156 SetMarkerPath 62 2 157 SetGoal 63 2 SetZone 63 1 SetMarkerPath 63 1 151 SetMarkerPath 63 2 22 SetGoal 64 5 SetZone 64 2 SetMarkerPath 64 1 101 SetMarkerPath 64 2 100 SetMarkerPath 64 3 105 SetGoal 65 5 SetZone 65 2 SetMarkerPath 65 1 103 SetMarkerPath 65 2 102 SetZone 66 9 SetZone 67 9 SetGoal 68 13 SetZone 68 5 SetMarkerPath 68 1 130 SetMarkerPath 68 2 78 SetGoal 69 14 SetZone 69 5 SetMarkerPath 69 1 15 SetMarkerPath 69 2 70 SetGoal 70 14 SetZone 70 5 SetMarkerPath 70 1 69 SetMarkerPath 70 2 77 SetMarkerPathFlags 70 2 v SetZone 71 5 SetMarkerPath 71 0 72 SetMarkerPath 71 1 8 SetMarkerPath 71 2 90 SetZone 72 3 SetMarkerPath 72 1 42 SetMarkerPath 72 2 40 SetMarkerPath 72 3 90 SetGoal 73 13 SetZone 73 5 SetMarkerPath 73 1 131 SetMarkerPath 73 2 82 SetMarkerPath 73 3 136 SetMarkerPath 73 4 127 SetGoal 74 12 SetZone 74 4 SetMarkerPath 74 1 124 SetGoal 75 14 SetZone 75 5 SetMarkerPath 75 1 85 SetMarkerPath 75 2 128 SetMarkerPath 75 3 132 SetGoal 76 3 SetZone 76 8 SetMarkerPath 76 1 163 SetMarkerPath 76 2 162 SetZone 77 5 SetMarkerPath 77 1 74 SetGoal 78 13 SetZone 78 5 SetMarkerPath 78 1 68 SetMarkerPath 78 2 79 SetGoal 79 13 SetZone 79 5 SetMarkerPath 79 1 78 SetMarkerPath 79 2 131 SetZone 80 4 SetMarkerPath 80 1 51 SetMarkerPath 80 2 117 SetZone 81 6 SetMarkerPath 81 1 139 SetMarkerPath 81 2 140 SetMarkerPath 81 3 141 SetZone 82 5 SetMarkerPath 82 1 73 SetMarkerPath 82 2 126 SetMarkerPath 82 3 131 SetGoal 83 15 SetZone 83 8 SetMarkerPath 83 1 1 SetMarkerPath 83 2 165 SetGoal 84 10 SetZone 84 4 SetMarkerPath 84 1 116 SetMarkerPath 84 2 52 SetGoal 85 14 SetZone 85 5 SetMarkerPath 85 1 127 SetMarkerPath 85 2 75 SetMarkerPath 85 3 184 SetMarkerPath 85 4 128 SetZone 86 1 SetMarkerPath 86 1 161 SetGoal 87 11 SetZone 87 4 SetMarkerPath 87 1 88 SetMarkerPath 87 2 118 SetMarkerPath 87 3 53 SetGoal 88 11 SetZone 88 4 SetMarkerPath 88 1 118 SetMarkerPath 88 2 87 SetGoal 89 20 SetZone 89 6 SetMarkerPath 89 1 140 SetZone 90 3 SetMarkerPath 90 1 10 SetMarkerPath 90 2 40 SetMarkerPath 90 3 91 SetMarkerPath 90 4 72 SetZone 91 3 SetMarkerPath 91 1 10 SetMarkerPath 91 2 40 SetMarkerPath 91 3 60 SetMarkerPath 91 4 94 SetMarkerPath 91 5 90 SetZone 92 3 SetMarkerPath 92 1 93 SetMarkerPath 92 2 41 SetZone 93 3 SetMarkerPath 93 1 10 SetMarkerPath 93 2 11 SetMarkerPath 93 3 92 SetMarkerPath 93 4 95 SetZone 94 3 SetMarkerPath 94 1 91 SetMarkerPath 94 2 95 SetMarkerPath 94 3 10 SetZone 95 3 SetMarkerPath 95 1 94 SetMarkerPath 95 2 93 SetMarkerPath 95 3 12 SetMarkerPath 95 4 96 SetMarkerPath 95 5 10 SetZone 96 3 SetMarkerPath 96 1 14 SetMarkerPath 96 2 97 SetMarkerPath 96 3 12 SetMarkerPath 96 4 95 SetZone 97 3 SetMarkerPath 97 1 98 SetMarkerPath 97 2 96 SetMarkerPath 97 3 14 SetMarkerPath 97 4 13 SetZone 98 3 SetMarkerPath 98 1 17 SetMarkerPath 98 2 99 SetMarkerPath 98 3 13 SetMarkerPath 98 4 97 SetZone 99 3 SetMarkerPath 99 1 98 SetMarkerPath 99 2 16 SetMarkerPath 99 3 100 SetZone 100 2 SetMarkerPath 100 1 64 SetMarkerPath 100 2 16 SetMarkerPath 100 3 99 SetZone 101 2 SetMarkerPath 101 1 102 SetMarkerPath 101 2 64 SetZone 102 2 SetMarkerPath 102 1 65 SetMarkerPath 102 2 101 SetZone 103 2 SetMarkerPath 103 1 104 SetMarkerPath 103 2 65 SetZone 104 2 SetMarkerPath 104 1 112 SetMarkerPath 104 2 103 SetMarkerPath 104 3 111 SetZone 105 2 SetMarkerPath 105 1 64 SetMarkerPath 105 2 106 SetZone 106 2 SetMarkerPath 106 1 105 SetMarkerPath 106 2 107 SetZone 107 2 SetMarkerPath 107 1 106 SetMarkerPath 107 2 108 SetZone 108 2 SetMarkerPath 108 1 107 SetMarkerPath 108 2 109 SetZone 109 2 SetMarkerPath 109 1 108 SetMarkerPath 109 2 148 SetMarkerPath 109 3 150 SetZone 110 2 SetMarkerPath 110 1 111 SetZone 111 2 SetMarkerPath 111 1 112 SetMarkerPath 111 2 110 SetMarkerPath 111 3 104 SetZone 112 2 SetMarkerPath 112 1 104 SetMarkerPath 112 2 111 SetMarkerPath 112 3 20 SetZone 113 2 SetMarkerPath 113 1 183 SetMarkerPath 113 2 18 SetMarkerPath 113 3 30 SetMarkerPath 113 4 19 SetMarkerPath 113 5 114 SetZone 114 4 SetMarkerPath 114 1 113 SetMarkerPath 114 2 115 SetZone 115 4 SetMarkerPath 115 1 114 SetMarkerPath 115 2 116 SetZone 116 4 SetMarkerPath 116 1 115 SetMarkerPath 116 2 84 SetZone 117 4 SetMarkerPath 117 1 80 SetMarkerPath 117 2 50 SetZone 118 4 SetMarkerPath 118 1 88 SetMarkerPath 118 2 119 SetMarkerPath 118 3 87 SetZone 119 4 SetMarkerPath 119 1 118 SetMarkerPath 119 2 120 SetZone 120 4 SetMarkerPath 120 1 119 SetMarkerPath 120 2 45 SetMarkerPath 120 3 9 SetMarkerPath 120 4 127 SetZone 121 4 SetMarkerPath 121 1 48 SetMarkerPath 121 2 124 SetMarkerPath 121 3 122 SetMarkerPath 121 4 182 SetZone 122 4 SetMarkerPath 122 1 121 SetMarkerPath 122 2 46 SetZone 123 4 SetMarkerPath 123 1 46 SetMarkerPath 123 2 53 SetZone 124 4 SetMarkerPath 124 1 121 SetMarkerPath 124 2 74 SetZone 125 4 SetMarkerPath 125 1 54 SetMarkerPath 125 2 2 SetMarkerPath 125 3 48 SetMarkerPath 125 4 136 SetZone 126 5 SetMarkerPath 126 1 82 SetMarkerPath 126 2 127 SetMarkerPath 126 3 184 SetMarkerPath 126 4 138 SetZone 127 5 SetMarkerPath 127 1 126 SetMarkerPath 127 2 85 SetMarkerPath 127 3 136 SetMarkerPath 127 4 73 SetMarkerPath 127 5 184 SetZone 128 5 SetMarkerPath 128 1 75 SetMarkerPath 128 2 137 SetMarkerPath 128 3 132 SetMarkerPath 128 4 129 SetMarkerPath 128 5 85 SetZone 129 5 SetMarkerPath 129 1 133 SetMarkerPath 129 2 128 SetMarkerPath 129 3 132 SetMarkerPath 129 4 15 SetZone 130 5 SetMarkerPath 130 1 133 SetMarkerPath 130 2 68 SetMarkerPath 130 3 134 SetZone 131 5 SetMarkerPath 131 1 79 SetMarkerPath 131 2 73 SetMarkerPath 131 3 135 SetMarkerPath 131 4 82 SetZone 132 5 SetMarkerPath 132 1 128 SetMarkerPath 132 2 7 SetMarkerPath 132 3 129 SetMarkerPath 132 4 75 SetMarkerPath 132 5 8 SetZone 133 5 SetMarkerPath 133 1 130 SetMarkerPath 133 2 129 SetMarkerPath 133 3 77 SetMarkerPathFlags 133 3 v SetZone 134 5 SetMarkerPath 134 1 130 SetMarkerPath 134 2 1 SetZone 135 5 SetMarkerPath 135 1 136 SetMarkerPath 135 2 131 SetMarkerPath 135 3 1 SetZone 136 5 SetMarkerPath 136 1 127 SetMarkerPath 136 2 135 SetMarkerPath 136 3 73 SetMarkerPath 136 4 137 SetMarkerPath 136 5 1 SetZone 137 5 SetMarkerPath 137 1 136 SetMarkerPath 137 2 128 SetMarkerPath 137 3 1 SetZone 138 6 SetMarkerPath 138 1 126 SetMarkerPath 138 2 139 SetZone 139 6 SetMarkerPath 139 1 138 SetMarkerPath 139 2 141 SetMarkerPath 139 3 81 SetMarkerPath 139 4 140 SetZone 140 6 SetMarkerPath 140 1 81 SetMarkerPath 140 2 89 SetMarkerPath 140 3 139 SetZone 141 6 SetMarkerPath 141 1 139 SetMarkerPath 141 2 142 SetMarkerPath 141 3 34 SetMarkerPath 141 4 81 SetZone 142 6 SetMarkerPath 142 1 141 SetMarkerPath 142 2 143 SetMarkerPath 142 3 34 SetZone 143 6 SetMarkerPath 143 1 142 SetMarkerPath 143 2 144 SetZone 144 6 SetMarkerPath 144 1 143 SetMarkerPath 144 2 145 SetZone 145 6 SetMarkerPath 145 1 144 SetMarkerPath 145 2 29 SetMarkerPath 145 3 146 SetMarkerPath 145 4 149 SetZone 146 6 SetMarkerPath 146 1 29 SetMarkerPath 146 2 145 SetMarkerPath 146 3 147 SetZone 147 6 SetMarkerPath 147 1 146 SetMarkerPath 147 2 26 SetMarkerPath 147 3 37 SetZone 148 1 SetMarkerPath 148 1 150 SetMarkerPath 148 2 109 SetMarkerPath 148 3 149 SetZone 149 6 SetMarkerPath 149 1 145 SetMarkerPath 149 2 148 SetMarkerPath 149 3 147 SetZone 150 1 SetMarkerPath 150 1 154 SetMarkerPath 150 2 148 SetMarkerPath 150 3 152 SetMarkerPath 150 4 151 SetMarkerPath 150 5 109 SetZone 151 1 SetMarkerPath 151 1 150 SetMarkerPath 151 2 63 SetZone 152 1 SetMarkerPath 152 1 32 SetMarkerPath 152 2 33 SetMarkerPath 152 3 150 SetMarkerPath 152 4 154 SetZone 153 1 SetMarkerPath 153 1 158 SetMarkerPath 153 2 154 SetMarkerPath 153 3 22 SetZone 154 1 SetMarkerPath 154 1 153 SetMarkerPath 154 2 150 SetMarkerPath 154 3 158 SetMarkerPath 154 4 152 SetMarkerPath 154 5 155 SetZone 155 1 SetMarkerPath 155 1 158 SetMarkerPath 155 2 156 SetMarkerPath 155 3 160 SetMarkerPath 155 4 154 SetZone 156 1 SetMarkerPath 156 1 155 SetMarkerPath 156 2 62 SetMarkerPath 156 3 33 SetMarkerPath 156 4 38 SetMarkerPathFlags 156 4 j SetZone 157 1 SetMarkerPath 157 1 62 SetMarkerPath 157 2 76 SetZone 158 1 SetMarkerPath 158 1 160 SetMarkerPath 158 2 155 SetMarkerPath 158 3 153 SetMarkerPath 158 4 159 SetMarkerPath 158 5 154 SetZone 159 1 SetMarkerPath 159 1 86 SetMarkerPathFlags 159 1 v SetMarkerPath 159 2 21 SetMarkerPath 159 3 160 SetMarkerPath 159 4 158 SetZone 160 1 SetMarkerPath 160 1 86 SetMarkerPathFlags 160 1 v SetMarkerPath 160 2 159 SetMarkerPath 160 3 158 SetMarkerPath 160 4 155 SetZone 161 1 SetMarkerPath 161 1 57 SetZone 162 8 SetMarkerPath 162 1 76 SetMarkerPath 162 2 157 SetZone 163 8 SetMarkerPath 163 1 164 SetMarkerPath 163 2 185 SetMarkerPath 163 3 76 SetZone 164 8 SetMarkerPath 164 1 165 SetMarkerPath 164 2 163 SetMarkerPath 164 3 185 SetZone 165 8 SetMarkerPath 165 1 83 SetMarkerPath 165 2 164 SetZone 166 8 SetMarkerPath 166 1 1 SetMarkerPath 166 2 168 SetZone 167 8 SetMarkerPath 167 1 169 SetMarkerPath 167 2 168 SetZone 168 8 SetMarkerPath 168 1 167 SetMarkerPath 168 2 166 SetZone 169 7 SetMarkerPath 169 1 172 SetMarkerPath 169 2 3 SetMarkerPath 169 3 167 SetZone 170 7 SetMarkerPath 170 1 6 SetMarkerPath 170 2 171 SetZone 171 7 SetMarkerPath 171 1 170 SetMarkerPath 171 2 4 SetMarkerPath 171 3 3 SetZone 172 7 SetMarkerPath 172 1 173 SetMarkerPath 172 2 169 SetMarkerPath 172 3 4 SetMarkerPath 172 4 3 SetZone 173 7 SetMarkerPath 173 1 172 SetMarkerPath 173 2 174 SetZone 174 7 SetMarkerPath 174 1 173 SetMarkerPath 174 2 175 SetZone 175 7 SetMarkerPath 175 1 174 SetMarkerPath 175 2 176 SetZone 176 7 SetMarkerPath 176 1 175 SetMarkerPath 176 2 177 SetMarkerPath 176 3 178 SetZone 177 7 SetMarkerPath 177 1 176 SetMarkerPath 177 2 178 SetMarkerPath 177 3 186 SetZone 178 7 SetMarkerPath 178 1 177 SetMarkerPath 178 2 181 SetMarkerPath 178 3 176 SetMarkerPath 178 4 186 SetZone 179 7 SetMarkerPath 179 1 44 SetMarkerPath 179 2 180 SetMarkerPath 179 3 187 SetZone 180 7 SetMarkerPath 180 1 39 SetMarkerPath 180 2 58 SetMarkerPath 180 3 179 SetZone 181 7 SetMarkerPath 181 1 178 SetMarkerPath 181 2 43 SetMarkerPath 181 3 44 SetZone 182 5 SetMarkerPath 182 1 129 SetZone 183 2 SetMarkerPath 183 1 18 SetMarkerPath 183 2 113 SetMarkerPath 183 3 20 SetMarkerPath 183 4 19 SetZone 184 5 SetMarkerPath 184 1 85 SetMarkerPath 184 2 126 SetMarkerPath 184 3 127 SetZone 185 8 SetMarkerPath 185 1 164 SetMarkerPath 185 2 163 SetZone 186 7 SetMarkerPath 186 1 188 SetMarkerPath 186 2 187 SetMarkerPath 186 3 44 SetMarkerPath 186 4 177 SetMarkerPath 186 5 178 SetZone 187 7 SetMarkerPath 187 1 186 SetMarkerPath 187 2 188 SetMarkerPath 187 3 179 SetMarkerPath 187 4 180 SetZone 188 7 SetMarkerPath 188 1 186 SetMarkerPath 188 2 187 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dm2dmm4.bot000066400000000000000000000063411475442401000262160ustar00rootroot00000000000000CreateMarker -1556 -444 344 CreateMarker -1157 -339 20 CreateMarker -1147 -485 20 CreateMarker -1124 -633 20 CreateMarker -1315 -611 20 CreateMarker -1508 -618 20 CreateMarker -1528 -462 20 CreateMarker -1526 -316 20 CreateMarker -1337 -461 20 CreateMarker -1127 -788 88 CreateMarker -957 -652 152 CreateMarker -961 -484 200 CreateMarker -1500 -771 88 CreateMarker -1699 -645 152 CreateMarker -1696 -458 200 CreateMarker -1316 -907 24 CreateMarker -1316 -985 24 CreateMarker -1308 -766 20 CreateMarker -1326 -178 20 CreateMarker -1040 -528 140 CreateMarker -1616 -528 136 SetZone 1 1 SetMarkerPath 1 0 28 SetMarkerPath 1 2 27 SetMarkerPath 1 3 33 SetMarkerPath 1 4 34 SetMarkerPath 1 5 32 SetMarkerPath 1 6 44 SetZone 3 2 SetMarkerPath 3 0 1 SetMarkerPath 3 1 12 SetZone 4 3 SetMarkerPath 4 0 1 SetMarkerPath 4 1 11 SetZone 6 3 SetMarkerPath 6 0 38 SetMarkerPath 6 1 39 SetZone 7 2 SetMarkerPath 7 1 35 SetMarkerPath 7 2 36 SetZone 8 1 SetMarkerPath 8 0 2 SetMarkerPath 8 1 44 SetGoal 11 1 SetZone 11 3 SetMarkerPath 11 1 34 SetMarkerPath 11 2 4 SetGoal 12 2 SetZone 12 2 SetMarkerPath 12 1 34 SetMarkerPath 12 2 3 SetZone 13 8 SetMarkerPath 13 0 6 SetMarkerPath 13 1 38 SetZone 14 8 SetMarkerPath 14 0 13 SetZone 15 7 SetMarkerPath 15 0 17 SetMarkerPath 15 1 2 SetZone 16 7 SetMarkerPath 16 0 15 SetZone 17 1 SetMarkerPath 17 0 44 SetZone 18 1 SetMarkerPath 18 0 42 SetZone 19 1 SetZone 20 4 SetMarkerPath 20 1 26 SetZone 21 6 SetMarkerPath 21 0 19 SetMarkerPath 21 1 41 SetZone 22 6 SetMarkerPath 22 0 21 SetZone 23 5 SetMarkerPath 23 0 20 SetMarkerPath 23 1 26 SetZone 24 5 SetMarkerPath 24 0 23 SetZone 25 4 SetMarkerPath 25 1 30 SetZone 26 4 SetMarkerPath 26 1 20 SetMarkerPath 26 2 34 SetZone 27 1 SetMarkerPath 27 0 34 SetMarkerPath 27 1 1 SetMarkerPath 27 2 28 SetZone 28 1 SetMarkerPath 28 0 1 SetMarkerPath 28 1 34 SetMarkerPath 28 2 27 SetMarkerPath 28 3 30 SetMarkerPath 28 4 29 SetZone 29 1 SetMarkerPath 29 0 34 SetMarkerPath 29 1 30 SetMarkerPath 29 2 28 SetZone 30 1 SetMarkerPath 30 0 43 SetMarkerPath 30 1 34 SetMarkerPath 30 2 28 SetMarkerPath 30 3 29 SetMarkerPath 30 4 31 SetZone 31 1 SetMarkerPath 31 1 32 SetMarkerPath 31 2 34 SetMarkerPath 31 3 30 SetZone 32 1 SetMarkerPath 32 0 1 SetMarkerPath 32 1 33 SetMarkerPath 32 2 34 SetMarkerPath 32 3 31 SetZone 33 1 SetMarkerPath 33 1 1 SetMarkerPath 33 2 32 SetMarkerPath 33 3 34 SetZone 34 1 SetMarkerPath 34 0 27 SetMarkerPath 34 1 32 SetMarkerPath 34 2 1 SetMarkerPath 34 3 33 SetMarkerPath 34 4 28 SetMarkerPath 34 5 30 SetMarkerPath 34 6 31 SetMarkerPath 34 7 29 SetZone 35 2 SetMarkerPath 35 0 43 SetMarkerPath 35 2 7 SetMarkerPath 35 3 29 SetZone 36 2 SetMarkerPath 36 1 7 SetMarkerPath 36 2 37 SetZone 37 2 SetMarkerPath 37 1 36 SetMarkerPath 37 2 12 SetZone 38 3 SetMarkerPath 38 0 6 SetMarkerPath 38 2 31 SetMarkerPath 38 3 43 SetZone 39 3 SetMarkerPath 39 0 6 SetMarkerPath 39 1 40 SetZone 40 3 SetMarkerPath 40 0 39 SetMarkerPath 40 1 11 SetZone 41 1 SetMarkerPath 41 0 43 SetMarkerPath 41 2 42 SetZone 42 1 SetMarkerPath 42 1 41 SetMarkerPath 43 0 41 SetMarkerPath 43 1 38 SetMarkerPath 43 2 30 SetMarkerPath 43 3 29 SetMarkerPath 43 4 31 SetMarkerPath 43 5 35 SetMarkerPath 44 2 1 SetMarkerPath 45 0 29 SetMarkerPath 45 1 28 SetMarkerPath 45 2 30 SetMarkerPath 46 0 32 SetMarkerPath 46 1 31 SetMarkerPath 46 2 34 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dm3.bot000066400000000000000000001267141475442401000254440ustar00rootroot00000000000000CreateMarker 1615 263 -213 CreateMarker 666 32 -182 CreateMarker 1970 428 -88 CreateMarker 1740 440 -88 CreateMarker 1982 45 -168 CreateMarker 1984 -108 -168 CreateMarker 1360 -33 -24 CreateMarker 1839 -33 -168 CreateMarker 1979 221 -88 CreateMarker 1959 -425 -24 CreateMarker 1974 -264 -88 CreateMarker 1837 -444 -24 CreateMarker 1132 -645 -24 CreateMarker 1088 -30 -168 CreateMarker 1620 -32 -168 CreateMarker 1626 -448 -24 CreateMarker 1241 -32 -168 CreateMarker 1446 -375 -24 CreateMarker 1371 -187 -24 CreateMarker 819 897 -274 CreateMarker 631 919 24 CreateMarker 633 754 -104 CreateMarker 817 752 -273 CreateMarker 512 944 40 CreateMarker 670 -107 -183 CreateMarker 473 -35 -189 CreateMarker -288 513 -16 CreateMarker 372 -203 56 CreateMarker 372 143 56 CreateMarker 792 -217 56 CreateMarker 789 149 56 CreateMarker -335 512 120 CreateMarker -416 208 -16 CreateMarker -463 218 176 CreateMarker -739 218 184 CreateMarker -784 219 -16 CreateMarker -217 263 -8 CreateMarker -310 -702 -16 CreateMarker -222 -704 152 CreateMarker -299 -577 -16 CreateMarker -789 90 184 CreateMarker -853 298 184 CreateMarker 560 613 216 CreateMarker 497 613 56 CreateMarker 1357 106 -24 CreateMarker 1542 828 -296 CreateMarker -798 286 -16 CreateMarker -854 240 -16 CreateMarker -739 289 184 CreateMarker -735 412 184 CreateMarker 504 486 56 CreateMarker 511 678 216 CreateMarker 490 308 56 CreateMarker 363 -31 -200 CreateMarker 580 -304 -200 CreateMarker 579 240 -200 CreateMarker 347 97 -200 CreateMarker 348 -164 -200 CreateMarker 1329 -378 -24 CreateMarker 1218 -662 -24 CreateMarker 1249 -514 -24 CreateMarker 1384 -469 -24 CreateMarker 1278 -737 -24 CreateMarker 1760 -886 -24 CreateMarker 1756 -787 -24 CreateMarker 1363 -944 -24 CreateMarker 1433 -797 -24 CreateMarker 1514 -735 -24 CreateMarker 672 -624 88 CreateMarker 822 -659 88 CreateMarker 1077 -891 88 CreateMarker 1447 -896 88 CreateMarker 1621 -893 56 CreateMarker 1254 -896 88 CreateMarker 667 -372 56 CreateMarker 652 -501 88 CreateMarker 1112 624 56 CreateMarker 1116 642 80 CreateMarker 627 358 56 CreateMarker 654 439 56 CreateMarker 655 280 56 CreateMarker 1316 336 56 CreateMarker 1354 218 24 CreateMarker 1204 488 56 CreateMarker 870 447 56 CreateMarker 992 534 56 CreateMarker 1032 427 56 CreateMarker 1151 386 56 CreateMarker 943 147 56 CreateMarker 908 -176 56 CreateMarker 983 -32 -184 CreateMarker 998 -216 -184 CreateMarker 994 143 -184 CreateMarker 826 -253 -184 CreateMarker 828 197 -184 CreateMarker 912 -199 -184 CreateMarker 907 141 -184 CreateMarker 891 -34 -184 CreateMarker 391 221 -200 CreateMarker 387 -278 -200 CreateMarker 573 112 -200 CreateMarker 584 -176 -200 CreateMarker 282 -107 -176 CreateMarker 279 37 -176 CreateMarker 273 -32 -176 CreateMarker -152 -232 -176 CreateMarker 185 -144 -176 CreateMarker -42 -191 -176 CreateMarker -173 -336 -144 CreateMarker 39 -444 -32 CreateMarker -68 -437 -64 CreateMarker 477 -549 56 CreateMarker 318 -782 -16 CreateMarker 45 -560 -16 CreateMarker -143 -561 -16 CreateMarker -478 -702 -16 CreateMarker -673 -289 -16 CreateMarker -635 -448 -16 CreateMarker -927 16 -16 CreateMarker -851 36 -16 CreateMarker -886 -94 -16 CreateMarker -833 147 -16 CreateMarker -590 317 184 CreateMarker -590 219 176 CreateMarker -620 477 120 CreateMarker -473 514 120 CreateMarker -848 558 -16 CreateMarker -638 617 184 CreateMarker -676 540 120 CreateMarker -937 546 120 CreateMarker -929 294 104 CreateMarker -934 172 40 CreateMarker -936 418 120 CreateMarker -929 671 120 CreateMarker -848 671 -16 CreateMarker -798 413 -16 CreateMarker -799 550 -16 CreateMarker -636 770 -16 CreateMarker -758 857 120 CreateMarker -732 752 -16 CreateMarker -563 846 120 CreateMarker -506 589 120 CreateMarker 8 664 40 CreateMarker -172 847 120 CreateMarker -75 750 104 CreateMarker -416 843 120 CreateMarker -417 758 -16 CreateMarker -288 762 -16 CreateMarker 138 590 56 CreateMarker 6 538 40 CreateMarker -107 395 24 CreateMarker -76 608 40 CreateMarker -182 683 8 CreateMarker -193 504 -8 CreateMarker 327 569 56 CreateMarker 479 -416 56 CreateMarker 407 -328 56 CreateMarker 220 -127 56 CreateMarker 257 156 56 CreateMarker -564 614 -16 CreateMarker -531 236 -16 CreateMarker -659 396 -16 CreateMarker -528 380 -16 CreateMarker -588 459 -16 CreateMarker -421 386 -16 CreateMarker -457 316 120 CreateMarker -460 272 144 CreateMarker -427 617 -16 CreateMarker 18 -867 0 CreateMarker 18 -806 -16 CreateMarker 481 -867 56 CreateMarker 134 -805 -16 CreateMarker 129 -866 16 CreateMarker 301 -869 32 CreateMarker 477 -705 56 CreateMarker 319 -630 -16 CreateMarker 172 -631 -16 CreateMarker -208 -880 -16 CreateMarker -202 -739 -16 CreateMarker -222 -544 152 CreateMarker 140 -543 152 CreateMarker 292 -545 88 CreateMarker -49 -543 152 CreateMarker 352 -864 264 CreateMarker 181 -868 232 CreateMarker 4 -862 152 CreateMarker 352 -705 264 CreateMarker 146 -705 328 CreateMarker 156 -541 264 CreateMarker -155 -696 328 CreateMarker -153 -548 328 CreateMarker 1 -543 328 CreateMarker -1 -702 328 CreateMarker 1843 962 -213 CreateMarker 1852 800 -202 CreateMarker 923 1105 -264 CreateMarker 1134 1106 -264 CreateMarker 1404 1097 -240 CreateMarker 1623 1068 -213 CreateMarker 1357 861 -296 CreateMarker 1146 825 -296 CreateMarker 1142 964 -296 CreateMarker 707 692 -264 CreateMarker 632 1032 24 CreateMarker 527 1032 40 CreateMarker 1363 648 -392 CreateMarker 1360 756 -328 CreateMarker 1360 66 -392 CreateMarker 1356 347 -392 CreateMarker 1832 -386 -211 CreateMarker 1451 -191 -216 CreateMarker 1809 141 -218 CreateMarker 1673 -234 -217 CreateMarker 1366 -436 -206 CreateMarker 1249 -194 -392 CreateMarker 1773 -275 -279 CreateMarker 1523 80 -392 CreateMarker 1196 66 -392 CreateMarker 1532 -368 -208 CreateMarker 1655 243 -392 CreateMarker 1644 100 -219 CreateMarker 1497 61 -210 CreateMarker 1155 -358 -212 CreateMarker 1853 -37 -288 CreateMarker 1808 -148 -215 CreateMarker 1730 383 -64 CreateMarker 1809 307 -260 CreateMarker 1154 122 -208 CreateMarker 1114 -124 -219 CreateMarker 679 -204 56 CreateMarker 479 -201 56 CreateMarker 456 125 56 CreateMarker 668 141 56 CreateMarker 1135 1010 -296 SetGoal 1 17 SetZone 1 1 SetMarkerPath 1 0 45 SetMarkerPath 1 1 69 SetMarkerPath 1 2 46 SetGoal 2 16 SetZone 2 4 SetMarkerPath 2 0 133 SetMarkerPath 2 1 132 SetMarkerPath 2 2 44 SetGoal 3 15 SetZone 3 7 SetMarkerPath 3 0 166 SetMarkerPath 3 1 67 SetMarkerPath 3 2 90 SetMarkerPath 3 3 167 SetMarkerPath 3 4 91 SetMarkerPath 3 5 165 SetMarkerPath 3 6 164 SetGoal 4 14 SetZone 4 12 SetMarkerPath 4 0 5 SetMarkerPath 4 1 98 SetMarkerPath 4 2 99 SetMarkerPathFlags 4 2 r SetRocketJumpPathFields 4 2 80.0 350.0 0 SetGoal 5 14 SetZone 5 12 SetMarkerPath 5 0 102 SetMarkerPath 5 1 98 SetMarkerPath 5 2 4 SetMarkerPath 5 3 99 SetMarkerPathFlags 5 3 r SetRocketJumpPathFields 5 3 63.0 6.0 0 SetGoal 6 13 SetZone 6 13 SetMarkerPath 6 0 106 SetZone 7 16 SetMarkerPath 7 0 268 SetMarkerPath 7 1 87 SetMarkerPath 7 2 88 SetZone 8 16 SetMarkerPath 8 0 87 SetMarkerPath 8 1 86 SetMarkerPath 8 2 85 SetMarkerPath 8 3 88 SetMarkerPath 8 4 64 SetZone 9 16 SetMarkerPath 9 0 89 SetMarkerPath 9 1 52 SetGoal 10 12 SetZone 10 4 SetMarkerPath 10 0 131 SetMarkerPath 10 1 47 SetGoal 11 11 SetZone 11 16 SetMarkerPath 11 0 260 SetMarkerPath 11 1 111 SetGoal 12 1 SetZone 12 15 SetMarkerPath 12 0 227 SetMarkerPath 12 1 226 SetGoal 13 1 SetZone 13 13 SetMarkerPath 13 0 190 SetGoal 14 23 SetZone 14 13 SetMarkerPath 14 0 231 SetMarkerPath 14 1 4 SetMarkerPath 14 3 98 SetMarkerPath 14 4 216 SetMarkerPath 14 5 102 SetGoal 15 23 SetZone 15 15 SetMarkerPath 15 0 230 SetMarkerPath 15 1 233 SetMarkerPath 15 2 55 SetMarkerPathFlags 15 2 r SetRocketJumpPathFields 15 2 80.0 354.0 0 SetGoal 16 24 SetZone 16 15 SetMarkerPath 16 0 203 SetMarkerPath 16 1 225 SetMarkerPath 16 2 206 SetMarkerPathFlags 16 2 r SetRocketJumpPathFields 16 2 73.0 266.0 0 SetGoal 17 10 SetZone 17 15 SetMarkerPath 17 0 202 SetMarkerPath 17 1 200 SetMarkerPath 17 2 18 SetMarkerPath 17 3 193 SetMarkerPathFlags 17 3 r SetRocketJumpPathFields 17 3 78.0 176.0 0 SetGoal 18 10 SetZone 18 15 SetMarkerPath 18 0 202 SetMarkerPath 18 1 200 SetMarkerPath 18 2 17 SetMarkerPath 18 3 205 SetGoal 19 24 SetZone 19 14 SetMarkerPath 19 0 199 SetMarkerPath 19 1 204 SetGoal 20 9 SetZone 20 14 SetMarkerPath 20 0 183 SetMarkerPath 20 1 182 SetMarkerPath 20 2 42 SetMarkerPath 20 3 62 SetGoal 21 23 SetZone 21 14 SetMarkerPath 21 0 181 SetMarkerPath 21 1 51 SetGoal 22 1 SetZone 22 9 SetMarkerPath 22 0 103 SetMarkerPath 22 1 23 SetMarkerPathFlags 22 1 r SetRocketJumpPathFields 22 1 77.0 177.0 0 SetGoal 23 23 SetZone 23 10 SetMarkerPath 23 0 104 SetMarkerPath 23 1 251 SetMarkerPath 23 2 22 SetMarkerPath 23 3 103 SetMarkerPath 23 4 56 SetMarkerPath 23 5 179 SetMarkerPath 23 6 255 SetMarkerPathFlags 23 6 r SetRocketJumpPathFields 23 6 78.3 -1.0 0 SetGoal 24 24 SetZone 24 10 SetMarkerPath 24 0 252 SetMarkerPath 24 1 254 SetMarkerPath 24 2 242 SetMarkerPath 24 3 235 SetMarkerPath 24 4 177 SetGoal 25 1 SetZone 25 11 SetMarkerPath 25 0 223 SetMarkerPath 25 1 50 SetMarkerPath 25 2 222 SetMarkerPath 25 3 93 SetGoal 26 24 SetZone 26 11 SetMarkerPath 26 0 94 SetMarkerPath 26 1 224 SetMarkerPath 26 2 65 SetMarkerPath 26 3 223 SetGoal 27 23 SetZone 27 11 SetMarkerPath 27 0 118 SetMarkerPath 27 1 94 SetMarkerPath 27 2 224 SetMarkerPath 27 3 297 SetGoal 28 23 SetZone 28 5 SetMarkerPath 28 0 146 SetMarkerPath 28 1 96 SetMarkerPath 28 2 154 SetMarkerPath 28 3 63 SetMarkerPath 28 4 298 SetGoal 29 24 SetZone 29 5 SetMarkerPath 29 0 96 SetMarkerPath 29 1 155 SetMarkerPath 29 2 154 SetGoal 30 1 SetZone 30 5 SetMarkerPath 30 0 155 SetMarkerPath 30 1 140 SetMarkerPath 30 2 95 SetGoal 31 24 SetZone 31 9 SetMarkerPath 31 0 178 SetMarkerPath 31 1 241 SetGoal 32 24 SetZone 32 8 SetMarkerPath 32 0 174 SetMarkerPath 32 1 176 SetGoal 33 23 SetZone 33 8 SetMarkerPath 33 0 43 SetMarkerPath 33 1 172 SetMarkerPath 33 2 173 SetGoal 34 24 SetZone 34 4 SetMarkerPath 34 0 135 SetMarkerPath 34 1 136 SetMarkerPath 34 2 128 SetMarkerPath 34 3 78 SetMarkerPath 34 4 125 SetMarkerPath 34 5 126 SetGoal 35 8 SetZone 35 4 SetMarkerPath 35 0 133 SetMarkerPath 35 1 57 SetMarkerPath 35 2 130 SetGoal 36 1 SetZone 36 4 SetMarkerPath 36 0 129 SetMarkerPath 36 1 130 SetMarkerPath 36 2 57 SetGoal 37 23 SetZone 37 2 SetMarkerPath 37 0 80 SetMarkerPath 37 1 82 SetMarkerPath 37 2 59 SetMarkerPath 37 3 285 SetGoal 38 24 SetZone 38 3 SetMarkerPath 38 0 84 SetMarkerPath 38 1 124 SetMarkerPath 38 2 127 SetMarkerPath 38 3 83 SetMarkerPath 38 4 80 SetMarkerPath 38 5 79 SetMarkerPath 38 6 59 SetGoal 39 1 SetZone 39 17 SetMarkerPath 39 0 275 SetMarkerPath 39 1 61 SetGoal 40 23 SetZone 40 17 SetMarkerPath 40 0 285 SetGoal 41 23 SetZone 41 17 SetMarkerPath 41 0 292 SetMarkerPath 41 1 285 SetZone 42 14 SetMarkerPath 42 0 182 SetMarkerPath 42 1 186 SetMarkerPath 42 2 62 SetMarkerPath 42 3 20 SetZone 43 8 SetMarkerPath 43 0 172 SetMarkerPath 43 1 33 SetZone 44 4 SetMarkerPath 44 0 132 SetMarkerPath 44 1 2 SetMarkerPath 44 2 131 SetZone 45 1 SetMarkerPath 45 0 1 SetMarkerPath 45 1 46 SetMarkerPath 45 2 69 SetGoal 46 23 SetZone 46 1 SetMarkerPath 46 0 45 SetMarkerPath 46 1 69 SetMarkerPath 46 2 1 SetZone 47 6 SetMarkerPath 47 0 48 SetZone 48 6 SetMarkerPath 48 0 149 SetMarkerPath 48 1 147 SetZone 49 11 SetMarkerPath 49 0 50 SetZone 50 11 SetMarkerPath 50 0 25 SetMarkerPath 50 1 222 SetMarkerPath 50 2 93 SetZone 51 14 SetMarkerPath 51 0 181 SetMarkerPath 51 1 21 SetMarkerPath 51 2 183 SetZone 52 16 SetMarkerPath 52 0 9 SetMarkerPath 52 1 117 SetGoal 53 7 SetZone 53 17 SetMarkerPath 53 0 283 SetMarkerPath 53 1 293 SetMarkerPath 53 2 294 SetGoal 54 6 SetZone 54 10 SetMarkerPath 54 0 253 SetMarkerPath 54 1 254 SetMarkerPath 54 2 24 SetMarkerPath 54 3 252 SetMarkerPath 54 4 249 SetMarkerPath 54 5 250 SetMarkerPath 54 6 251 SetGoal 55 20 SetZone 55 13 SetMarkerPath 55 0 191 SetMarkerPath 55 1 207 SetMarkerPath 55 2 231 SetMarkerPath 55 3 230 SetMarkerPath 55 4 227 SetMarkerPath 55 5 225 SetMarkerPath 55 6 226 SetMarkerPath 55 7 228 SetGoal 56 22 SetZone 56 9 SetMarkerPath 56 0 180 SetMarkerPath 56 1 235 SetMarkerPath 56 2 179 SetMarkerPath 56 3 242 SetMarkerPath 56 4 237 SetMarkerPath 56 5 244 SetMarkerPath 56 6 251 SetMarkerPathFlags 56 6 r SetRocketJumpPathFields 56 6 73.0 117.0 0 SetMarkerPath 56 7 23 SetMarkerPathFlags 56 7 r SetRocketJumpPathFields 56 7 61.0 57.0 0 SetGoal 57 21 SetZone 57 4 SetMarkerPath 57 0 35 SetMarkerPath 57 1 36 SetMarkerPath 57 2 130 SetGoal 59 5 SetZone 59 17 SetMarkerPath 59 0 276 SetMarkerPath 59 1 278 SetMarkerPath 59 2 284 SetMarkerPath 59 3 286 SetMarkerPath 59 4 273 SetMarkerPath 59 5 280 SetGoal 60 19 SetZone 60 17 SetMarkerPath 60 0 283 SetMarkerPath 60 1 280 SetMarkerPath 60 2 294 SetMarkerPath 60 3 288 SetMarkerPath 60 4 293 SetGoal 61 19 SetZone 61 17 SetMarkerPath 61 0 281 SetMarkerPath 61 1 39 SetMarkerPath 61 2 275 SetGoal 62 19 SetZone 62 14 SetMarkerPath 62 0 42 SetMarkerPath 62 1 20 SetMarkerPath 62 2 182 SetGoal 63 4 SetZone 63 5 SetMarkerPath 63 0 154 SetMarkerPath 63 1 28 SetMarkerPath 63 2 96 SetGoal 64 3 SetZone 64 16 SetMarkerPath 64 0 266 SetMarkerPath 64 1 88 SetMarkerPath 64 2 85 SetMarkerPath 64 3 267 SetGoal 65 2 SetZone 65 11 SetMarkerPath 65 0 224 SetMarkerPath 65 1 223 SetMarkerPath 65 2 26 SetZone 66 17 SetMarkerPath 66 0 285 SetMarkerPath 66 1 292 SetMarkerPath 66 2 286 SetMarkerPath 66 3 277 SetMarkerPath 66 4 287 SetZone 67 7 SetMarkerPath 67 0 160 SetMarkerPath 67 1 3 SetMarkerPath 67 2 166 SetMarkerPath 67 3 93 SetMarkerPathFlags 67 3 r SetRocketJumpPathFields 67 3 76.0 29.0 0 SetZone 68 1 SetMarkerPath 68 0 69 SetMarkerPath 68 1 74 SetZone 69 1 SetMarkerPath 69 0 45 SetMarkerPath 69 1 46 SetMarkerPath 69 2 1 SetMarkerPath 69 3 68 SetMarkerPath 69 4 291 SetMarkerPathFlags 69 4 j SetZone 70 2 SetMarkerPath 70 0 74 SetMarkerPath 70 1 71 SetMarkerPath 70 2 73 SetZone 71 2 SetMarkerPath 71 0 70 SetMarkerPath 71 1 73 SetMarkerPath 71 2 76 SetZone 72 3 SetMarkerPath 72 0 84 SetMarkerPath 72 1 110 SetMarkerPath 72 2 80 SetMarkerPath 72 3 79 SetMarkerPath 72 4 59 SetZone 73 2 SetMarkerPath 73 0 70 SetMarkerPath 73 1 71 SetMarkerPath 73 2 80 SetMarkerPath 73 3 278 SetZone 74 1 SetMarkerPath 74 0 68 SetMarkerPath 74 1 70 SetZone 75 3 SetMarkerPath 75 0 76 SetMarkerPath 75 1 77 SetZone 76 3 SetMarkerPath 76 0 71 SetMarkerPath 76 1 75 SetZone 77 3 SetMarkerPath 77 0 75 SetMarkerPath 77 1 81 SetMarkerPath 77 2 73 SetMarkerPath 77 3 80 SetMarkerPath 77 4 59 SetZone 78 4 SetMarkerPath 78 0 126 SetMarkerPath 78 1 125 SetMarkerPath 78 2 128 SetMarkerPath 78 3 34 SetMarkerPathFlags 78 3 r SetRocketJumpPathFields 78 3 58.0 27.0 3 SetZone 79 2 SetMarkerPath 79 0 82 SetMarkerPath 79 1 156 SetMarkerPath 79 2 72 SetMarkerPathFlags 79 2 r SetRocketJumpPathFields 79 2 60.0 180.0 0 SetMarkerPath 79 3 84 SetMarkerPathFlags 79 3 r SetRocketJumpPathFields 79 3 60.0 150.0 0 SetMarkerPath 79 4 53 SetZone 80 2 SetMarkerPath 80 0 73 SetMarkerPath 80 1 37 SetMarkerPath 80 2 72 SetMarkerPathFlags 80 2 r SetRocketJumpPathFields 80 2 56.0 360.0 0 SetZone 81 3 SetMarkerPath 81 0 77 SetMarkerPath 81 1 83 SetMarkerPath 81 2 127 SetMarkerPath 81 3 80 SetMarkerPath 81 4 73 SetMarkerPath 81 5 59 SetMarkerPath 81 6 278 SetZone 82 2 SetMarkerPath 82 0 37 SetMarkerPath 82 1 79 SetZone 83 3 SetMarkerPath 83 0 81 SetMarkerPath 83 1 84 SetMarkerPath 83 2 127 SetMarkerPath 83 3 38 SetMarkerPath 83 4 124 SetMarkerPath 83 5 80 SetMarkerPath 83 6 59 SetZone 84 3 SetMarkerPath 84 0 83 SetMarkerPath 84 1 72 SetMarkerPath 84 2 38 SetMarkerPath 84 3 124 SetMarkerPath 84 4 80 SetMarkerPath 84 5 79 SetMarkerPath 84 6 59 SetZone 85 16 SetMarkerPath 85 0 88 SetMarkerPath 85 1 268 SetMarkerPath 85 2 261 SetMarkerPath 85 3 64 SetMarkerPath 85 4 267 SetMarkerPath 85 5 8 SetMarkerPathFlags 85 5 r SetRocketJumpPathFields 85 5 78.3 -1.0 0 SetMarkerPath 85 6 86 SetMarkerPathFlags 85 6 r SetRocketJumpPathFields 85 6 80.0 353.0 0 SetZone 86 16 SetMarkerPath 86 0 8 SetMarkerPath 86 1 269 SetMarkerPath 86 2 85 SetMarkerPath 86 3 64 SetMarkerPath 86 4 267 SetMarkerPath 86 5 88 SetMarkerPath 86 6 87 SetZone 87 16 SetMarkerPath 87 0 7 SetMarkerPath 87 1 8 SetMarkerPath 87 2 88 SetMarkerPath 87 3 85 SetMarkerPath 87 4 64 SetMarkerPath 87 5 268 SetMarkerPath 87 6 86 SetMarkerPathFlags 87 6 r SetRocketJumpPathFields 87 6 69.0 272.0 0 SetZone 88 16 SetMarkerPath 88 0 64 SetMarkerPath 88 1 85 SetMarkerPath 88 2 268 SetMarkerPath 88 3 267 SetMarkerPath 88 4 87 SetMarkerPathFlags 88 4 r SetRocketJumpPathFields 88 4 80.0 360.0 3 SetZone 89 16 SetMarkerPath 89 0 270 SetMarkerPath 89 1 9 SetZone 90 7 SetMarkerPath 90 0 159 SetMarkerPath 90 1 3 SetMarkerPath 90 2 94 SetMarkerPathFlags 90 2 r SetRocketJumpPathFields 90 2 77.0 322.0 0 SetZone 91 7 SetMarkerPath 91 0 119 SetMarkerPath 91 1 3 SetMarkerPath 91 2 167 SetMarkerPath 91 3 166 SetMarkerPath 91 4 96 SetMarkerPathFlags 91 4 r SetRocketJumpPathFields 91 4 75.0 211.0 0 SetMarkerPath 91 5 95 SetMarkerPathFlags 91 5 r SetRocketJumpPathFields 91 5 75.0 145.0 0 SetZone 92 12 SetMarkerPath 92 0 219 SetMarkerPath 92 1 102 SetMarkerPath 92 2 218 SetMarkerPath 92 3 97 SetMarkerPathFlags 92 3 r SetRocketJumpPathFields 92 3 79.0 360.0 0 SetZone 93 11 SetMarkerPath 93 0 223 SetMarkerPath 93 1 222 SetMarkerPath 93 2 50 SetMarkerPath 93 3 25 SetMarkerPath 93 4 91 SetMarkerPath 93 5 3 SetMarkerPath 93 6 167 SetMarkerPath 93 7 166 SetZone 94 11 SetMarkerPath 94 0 118 SetMarkerPath 94 1 27 SetMarkerPath 94 2 224 SetMarkerPath 94 3 26 SetMarkerPath 94 4 91 SetMarkerPath 94 5 3 SetMarkerPath 94 6 166 SetMarkerPath 94 7 167 SetZone 95 5 SetMarkerPath 95 0 140 SetMarkerPath 95 1 30 SetMarkerPath 95 2 155 SetMarkerPath 95 3 90 SetMarkerPath 95 4 3 SetMarkerPath 95 5 119 SetMarkerPath 95 6 67 SetMarkerPath 95 7 167 SetZone 96 5 SetMarkerPath 96 0 28 SetMarkerPath 96 1 29 SetMarkerPath 96 2 154 SetMarkerPath 96 3 63 SetMarkerPath 96 4 146 SetMarkerPath 96 5 67 SetMarkerPath 96 6 3 SetMarkerPath 96 7 119 SetZone 97 13 SetMarkerPath 97 0 191 SetMarkerPath 97 1 219 SetMarkerPath 97 2 92 SetMarkerPath 97 3 216 SetMarkerPath 97 4 215 SetMarkerPath 97 5 217 SetZone 98 12 SetMarkerPath 98 0 5 SetMarkerPath 98 1 4 SetMarkerPath 98 2 102 SetMarkerPath 98 3 99 SetMarkerPathFlags 98 3 r SetRocketJumpPathFields 98 3 78.3 -1.0 0 SetZone 99 13 SetMarkerPath 99 0 189 SetMarkerPath 99 1 188 SetMarkerPath 99 2 14 SetMarkerPath 99 3 55 SetMarkerPath 99 4 98 SetMarkerPath 99 5 4 SetMarkerPath 99 6 5 SetMarkerPath 99 7 102 SetZone 100 13 SetMarkerPath 100 0 114 SetMarkerPath 100 1 189 SetMarkerPath 100 2 188 SetMarkerPath 100 3 227 SetMarkerPath 100 4 190 SetMarkerPath 100 5 197 SetMarkerPath 100 6 113 SetMarkerPath 100 7 101 SetZone 101 15 SetMarkerPath 101 0 113 SetMarkerPath 101 1 112 SetMarkerPath 101 2 187 SetMarkerPath 101 3 100 SetMarkerPathFlags 101 3 r SetRocketJumpPathFields 101 3 80.0 180.0 0 SetZone 102 12 SetMarkerPath 102 0 216 SetMarkerPath 102 1 5 SetMarkerPath 102 2 98 SetMarkerPath 102 3 219 SetMarkerPath 102 4 92 SetZone 103 9 SetMarkerPath 103 0 105 SetMarkerPath 103 1 22 SetMarkerPath 103 2 181 SetMarkerPath 103 3 104 SetMarkerPathFlags 103 3 r SetRocketJumpPathFields 103 3 70.0 180.0 0 SetZone 104 10 SetMarkerPath 104 0 245 SetMarkerPath 104 1 23 SetMarkerPath 104 2 22 SetMarkerPath 104 3 103 SetMarkerPath 104 4 105 SetMarkerPath 104 5 255 SetMarkerPathFlags 104 5 r SetRocketJumpPathFields 104 5 70.0 180.0 0 SetZone 105 9 SetMarkerPath 105 0 180 SetMarkerPath 105 1 103 SetZone 106 13 SetMarkerPath 106 0 6 SetMarkerPath 106 1 107 SetMarkerPath 106 2 197 SetMarkerPath 106 3 184 SetMarkerPath 106 4 113 SetZone 107 13 SetMarkerPath 107 0 106 SetMarkerPath 107 1 114 SetMarkerPath 107 2 115 SetMarkerPath 107 3 201 SetMarkerPath 107 4 196 SetMarkerPath 107 5 185 SetMarkerPath 107 6 198 SetMarkerPath 107 7 187 SetZone 108 16 SetMarkerPath 108 0 117 SetMarkerPath 108 1 109 SetZone 109 12 SetMarkerPath 109 0 220 SetMarkerPath 109 1 116 SetMarkerPath 109 2 108 SetMarkerPathFlags 109 2 r SetRocketJumpPathFields 109 2 80.0 180.0 0 SetZone 110 3 SetMarkerPath 110 0 72 SetMarkerPath 110 1 148 SetMarkerPath 110 2 79 SetMarkerPath 110 3 80 SetZone 111 16 SetMarkerPath 111 0 265 SetMarkerPath 111 1 11 SetMarkerPathFlags 111 1 r SetRocketJumpPathFields 111 1 52.0 150.0 0 SetZone 112 15 SetMarkerPath 112 0 187 SetMarkerPath 112 1 201 SetMarkerPath 112 2 101 SetZone 113 15 SetMarkerPath 113 0 101 SetMarkerPath 113 1 187 SetMarkerPath 113 3 106 SetMarkerPathFlags 113 3 r SetRocketJumpPathFields 113 3 70.0 118.0 0 SetZone 114 13 SetMarkerPath 114 0 107 SetMarkerPath 114 1 100 SetMarkerPath 114 2 188 SetMarkerPath 114 3 115 SetMarkerPath 114 4 189 SetMarkerPath 114 5 190 SetMarkerPath 114 6 227 SetMarkerPath 114 7 197 SetZone 115 13 SetMarkerPath 115 0 188 SetMarkerPath 115 1 107 SetMarkerPath 115 2 114 SetMarkerPath 115 3 193 SetMarkerPath 115 4 201 SetMarkerPath 115 5 227 SetMarkerPath 115 6 13 SetMarkerPath 115 7 190 SetZone 116 12 SetMarkerPath 116 0 220 SetMarkerPath 116 1 118 SetMarkerPath 116 2 109 SetZone 117 16 SetMarkerPath 117 0 52 SetMarkerPath 117 1 108 SetMarkerPath 117 2 109 SetZone 118 11 SetMarkerPath 118 0 116 SetMarkerPath 118 1 27 SetMarkerPath 118 2 94 SetZone 119 7 SetMarkerPath 119 0 167 SetMarkerPath 119 1 166 SetMarkerPath 119 2 170 SetMarkerPath 119 3 123 SetMarkerPath 119 4 122 SetMarkerPath 119 5 91 SetZone 120 7 SetMarkerPath 120 0 165 SetMarkerPath 120 1 159 SetMarkerPath 120 2 167 SetZone 121 7 SetMarkerPath 121 0 164 SetMarkerPath 121 1 160 SetMarkerPath 121 2 166 SetZone 122 7 SetMarkerPath 122 0 119 SetMarkerPath 122 1 164 SetZone 123 7 SetMarkerPath 123 0 119 SetMarkerPath 123 1 165 SetZone 124 3 SetMarkerPath 124 0 38 SetMarkerPath 124 1 83 SetMarkerPath 124 2 84 SetMarkerPath 124 3 127 SetMarkerPath 124 4 126 SetMarkerPath 124 5 79 SetZone 125 4 SetMarkerPath 125 0 128 SetMarkerPath 125 1 126 SetMarkerPath 125 2 78 SetZone 126 3 SetMarkerPath 126 0 125 SetMarkerPath 126 1 127 SetMarkerPath 126 2 124 SetMarkerPath 126 3 78 SetZone 127 3 SetMarkerPath 127 0 81 SetMarkerPath 127 1 126 SetMarkerPath 127 2 83 SetMarkerPath 127 3 38 SetMarkerPath 127 4 124 SetZone 128 4 SetMarkerPath 128 0 133 SetMarkerPath 128 1 125 SetMarkerPath 128 2 78 SetMarkerPath 128 3 132 SetZone 129 4 SetMarkerPath 129 0 138 SetMarkerPath 129 1 36 SetMarkerPath 129 2 130 SetMarkerPath 129 3 35 SetMarkerPath 129 4 133 SetZone 130 4 SetMarkerPath 130 0 36 SetMarkerPath 130 1 133 SetMarkerPath 130 2 129 SetMarkerPath 130 3 57 SetMarkerPath 130 4 35 SetZone 131 4 SetMarkerPath 131 0 44 SetMarkerPath 131 1 10 SetZone 132 4 SetMarkerPath 132 0 128 SetMarkerPath 132 1 133 SetMarkerPath 132 2 2 SetMarkerPath 132 3 44 SetZone 133 4 SetMarkerPath 133 0 130 SetMarkerPath 133 1 128 SetMarkerPath 133 2 132 SetMarkerPath 133 3 35 SetMarkerPath 133 4 2 SetZone 134 4 SetMarkerPath 134 0 141 SetMarkerPath 134 1 135 SetZone 135 4 SetMarkerPath 135 0 134 SetMarkerPath 135 1 34 SetZone 136 4 SetMarkerPath 136 0 34 SetMarkerPath 136 1 139 SetMarkerPath 136 2 128 SetZone 137 4 SetMarkerPath 137 0 139 SetMarkerPath 137 1 138 SetMarkerPath 137 2 132 SetMarkerPath 137 3 133 SetMarkerPath 137 4 35 SetZone 138 4 SetMarkerPath 138 0 137 SetMarkerPath 138 1 129 SetMarkerPath 138 2 133 SetMarkerPath 138 3 35 SetMarkerPath 138 4 57 SetMarkerPath 138 5 36 SetMarkerPath 138 6 130 SetZone 139 4 SetMarkerPath 139 0 136 SetMarkerPath 139 1 137 SetZone 140 5 SetMarkerPath 140 0 30 SetMarkerPath 140 1 141 SetMarkerPath 140 2 95 SetZone 141 4 SetMarkerPath 141 0 140 SetMarkerPath 141 1 134 SetZone 142 6 SetMarkerPath 142 0 151 SetMarkerPath 142 1 149 SetMarkerPath 142 2 153 SetMarkerPath 142 3 152 SetMarkerPath 142 4 143 SetMarkerPathFlags 142 4 j SetZone 143 6 SetMarkerPath 143 0 265 SetMarkerPath 143 1 267 SetMarkerPath 143 2 266 SetMarkerPath 143 3 64 SetMarkerPath 143 4 85 SetMarkerPath 143 5 151 SetMarkerPath 143 6 142 SetZone 144 5 SetMarkerPath 144 0 145 SetMarkerPath 144 1 146 SetZone 145 6 SetMarkerPath 145 0 150 SetMarkerPath 145 1 144 SetZone 146 5 SetMarkerPath 146 0 144 SetMarkerPath 146 1 28 SetMarkerPath 146 2 96 SetZone 147 6 SetMarkerPath 147 0 148 SetMarkerPath 147 1 153 SetMarkerPath 147 2 48 SetMarkerPath 147 3 149 SetZone 148 6 SetMarkerPath 148 0 110 SetMarkerPath 148 1 147 SetZone 149 6 SetMarkerPath 149 0 48 SetMarkerPath 149 1 147 SetMarkerPath 149 2 142 SetMarkerPath 149 3 153 SetMarkerPath 149 4 152 SetMarkerPath 149 5 151 SetZone 150 6 SetMarkerPath 150 0 152 SetMarkerPath 150 1 145 SetMarkerPath 150 2 151 SetZone 151 6 SetMarkerPath 151 0 150 SetMarkerPath 151 1 142 SetMarkerPath 151 2 152 SetMarkerPath 151 3 149 SetMarkerPath 151 4 153 SetZone 152 6 SetMarkerPath 152 0 153 SetMarkerPath 152 1 150 SetMarkerPath 152 2 151 SetMarkerPath 152 3 142 SetMarkerPath 152 4 149 SetZone 153 6 SetMarkerPath 153 0 147 SetMarkerPath 153 1 152 SetMarkerPath 153 2 149 SetMarkerPath 153 3 142 SetMarkerPath 153 4 151 SetZone 154 5 SetMarkerPath 154 0 29 SetMarkerPath 154 1 96 SetMarkerPath 154 2 63 SetMarkerPath 154 3 28 SetZone 155 5 SetMarkerPath 155 0 29 SetMarkerPath 155 1 30 SetMarkerPath 155 2 95 SetMarkerPath 155 3 295 SetZone 156 7 SetMarkerPath 156 0 79 SetMarkerPath 156 1 161 SetMarkerPath 156 2 162 SetMarkerPath 156 3 163 SetMarkerPath 156 4 158 SetMarkerPath 156 5 157 SetZone 157 7 SetMarkerPath 157 0 156 SetMarkerPath 157 1 161 SetMarkerPath 157 2 163 SetZone 158 7 SetMarkerPath 158 0 156 SetMarkerPath 158 1 162 SetMarkerPath 158 2 163 SetZone 159 7 SetMarkerPath 159 0 161 SetMarkerPath 159 1 167 SetMarkerPath 159 2 90 SetMarkerPath 159 3 120 SetZone 160 7 SetMarkerPath 160 0 162 SetMarkerPath 160 1 166 SetMarkerPath 160 2 121 SetMarkerPath 160 3 67 SetZone 161 7 SetMarkerPath 161 0 156 SetMarkerPath 161 1 163 SetMarkerPath 161 2 159 SetMarkerPath 161 3 157 SetZone 162 7 SetMarkerPath 162 0 156 SetMarkerPath 162 1 160 SetMarkerPath 162 2 163 SetMarkerPath 162 3 158 SetZone 163 7 SetMarkerPath 163 0 162 SetMarkerPath 163 1 161 SetMarkerPath 163 2 156 SetMarkerPath 163 3 158 SetMarkerPath 163 4 157 SetZone 164 7 SetMarkerPath 164 0 122 SetMarkerPath 164 1 121 SetMarkerPath 164 2 3 SetZone 165 7 SetMarkerPath 165 0 123 SetMarkerPath 165 1 120 SetMarkerPath 165 2 3 SetZone 166 7 SetMarkerPath 166 0 119 SetMarkerPath 166 1 160 SetMarkerPath 166 2 3 SetMarkerPath 166 3 91 SetMarkerPath 166 4 67 SetMarkerPath 166 5 121 SetMarkerPath 166 6 95 SetMarkerPathFlags 166 6 r SetRocketJumpPathFields 166 6 72.0 131.0 0 SetMarkerPath 166 7 93 SetMarkerPathFlags 166 7 r SetRocketJumpPathFields 166 7 75.0 62.0 0 SetZone 167 7 SetMarkerPath 167 0 159 SetMarkerPath 167 1 119 SetMarkerPath 167 2 3 SetMarkerPath 167 3 90 SetMarkerPath 167 4 91 SetMarkerPath 167 5 120 SetMarkerPath 167 6 94 SetMarkerPathFlags 167 6 r SetRocketJumpPathFields 167 6 75.0 299.0 0 SetMarkerPath 167 7 96 SetMarkerPathFlags 167 7 r SetRocketJumpPathFields 167 7 75.0 236.0 0 SetZone 168 8 SetMarkerPath 168 0 170 SetZone 169 8 SetMarkerPath 169 0 170 SetZone 170 8 SetMarkerPath 170 0 119 SetMarkerPath 170 1 169 SetMarkerPath 170 2 168 SetMarkerPath 170 3 172 SetZone 171 8 SetMarkerPath 171 0 173 SetMarkerPath 171 1 174 SetZone 172 8 SetMarkerPath 172 0 170 SetMarkerPath 172 1 43 SetMarkerPath 172 2 33 SetZone 173 8 SetMarkerPath 173 0 33 SetMarkerPath 173 1 171 SetZone 174 8 SetMarkerPath 174 0 171 SetMarkerPath 174 1 32 SetZone 175 8 SetMarkerPath 175 0 176 SetMarkerPath 175 1 179 SetZone 176 8 SetMarkerPath 176 0 32 SetMarkerPath 176 1 175 SetZone 177 9 SetMarkerPath 177 0 221 SetMarkerPath 177 1 240 SetMarkerPath 177 2 247 SetMarkerPath 177 3 241 SetMarkerPath 177 4 31 SetZone 178 9 SetMarkerPath 178 0 237 SetMarkerPath 178 1 31 SetMarkerPath 178 2 240 SetMarkerPathFlags 178 2 r SetRocketJumpPathFields 178 2 52.0 192.0 4 SetZone 179 9 SetMarkerPath 179 0 175 SetMarkerPath 179 1 180 SetMarkerPath 179 2 56 SetMarkerPath 179 3 242 SetZone 180 9 SetMarkerPath 180 0 179 SetMarkerPath 180 1 105 SetMarkerPath 180 2 244 SetMarkerPath 180 3 56 SetZone 181 14 SetMarkerPath 181 0 103 SetMarkerPath 181 1 51 SetMarkerPath 181 2 21 SetZone 182 14 SetMarkerPath 182 0 183 SetMarkerPath 182 1 20 SetMarkerPath 182 2 42 SetMarkerPath 182 3 62 SetZone 183 14 SetMarkerPath 183 0 51 SetMarkerPath 183 1 182 SetMarkerPath 183 2 20 SetMarkerPath 183 3 49 SetZone 184 14 SetMarkerPath 184 0 186 SetMarkerPath 184 1 197 SetMarkerPath 184 2 185 SetMarkerPath 184 3 187 SetMarkerPath 184 4 106 SetMarkerPathFlags 184 4 r SetRocketJumpPathFields 184 4 68.0 200.0 0 SetZone 185 14 SetMarkerPath 185 0 186 SetMarkerPath 185 1 187 SetMarkerPath 185 2 184 SetMarkerPath 185 3 107 SetMarkerPathFlags 185 3 r SetRocketJumpPathFields 185 3 75.0 276.0 0 SetZone 186 14 SetMarkerPath 186 0 42 SetMarkerPath 186 1 184 SetMarkerPath 186 2 185 SetZone 187 14 SetMarkerPath 187 0 185 SetMarkerPath 187 1 112 SetMarkerPath 187 2 184 SetMarkerPath 187 3 101 SetMarkerPath 187 4 113 SetMarkerPath 187 6 107 SetMarkerPathFlags 187 6 r SetRocketJumpPathFields 187 6 65.0 270.0 0 SetZone 188 13 SetMarkerPath 188 0 189 SetMarkerPath 188 1 99 SetMarkerPath 188 2 115 SetMarkerPath 188 3 114 SetMarkerPath 188 4 100 SetZone 189 13 SetMarkerPath 189 0 100 SetMarkerPath 189 1 99 SetMarkerPath 189 2 188 SetMarkerPath 189 3 114 SetMarkerPath 189 4 231 SetMarkerPath 189 5 232 SetZone 190 13 SetMarkerPath 190 0 191 SetMarkerPath 190 1 194 SetMarkerPath 190 2 13 SetMarkerPath 190 3 207 SetMarkerPath 190 4 228 SetMarkerPath 190 5 227 SetMarkerPath 190 6 225 SetMarkerPath 190 7 231 SetZone 191 13 SetMarkerPath 191 0 207 SetMarkerPath 191 1 97 SetMarkerPath 191 2 55 SetMarkerPath 191 3 190 SetMarkerPath 191 4 231 SetMarkerPath 191 5 233 SetMarkerPath 191 6 225 SetMarkerPath 191 7 230 SetZone 192 15 SetMarkerPath 192 0 202 SetMarkerPath 192 1 200 SetMarkerPath 192 2 195 SetMarkerPathFlags 192 2 r SetRocketJumpPathFields 192 2 66.0 4.0 0 SetZone 193 13 SetMarkerPath 193 0 115 SetMarkerPath 193 1 17 SetMarkerPath 193 2 207 SetMarkerPath 193 3 16 SetMarkerPath 193 4 194 SetMarkerPath 193 5 55 SetMarkerPath 193 6 191 SetZone 194 13 SetMarkerPath 194 0 190 SetMarkerPath 194 1 191 SetZone 195 14 SetMarkerPath 195 0 198 SetMarkerPath 195 1 199 SetMarkerPath 195 2 192 SetZone 196 14 SetMarkerPath 196 0 197 SetMarkerPath 196 1 198 SetZone 197 14 SetMarkerPath 197 0 184 SetMarkerPath 197 1 196 SetMarkerPath 197 2 101 SetMarkerPath 197 3 187 SetMarkerPath 197 4 113 SetMarkerPath 197 5 185 SetZone 198 14 SetMarkerPath 198 0 196 SetMarkerPath 198 1 195 SetMarkerPath 198 2 107 SetMarkerPathFlags 198 2 r SetRocketJumpPathFields 198 2 45.0 138.0 4 SetZone 199 14 SetMarkerPath 199 0 195 SetMarkerPath 199 1 19 SetMarkerPath 199 2 200 SetZone 200 15 SetMarkerPath 200 0 202 SetMarkerPath 200 1 192 SetMarkerPath 200 2 205 SetMarkerPath 200 3 18 SetMarkerPath 200 4 17 SetMarkerPath 200 5 199 SetMarkerPathFlags 200 5 r SetRocketJumpPathFields 200 5 68.0 360.0 0 SetZone 201 15 SetMarkerPath 201 0 112 SetMarkerPath 201 1 202 SetMarkerPath 201 2 115 SetMarkerPathFlags 201 2 r SetRocketJumpPathFields 201 2 77.0 180.0 0 SetZone 202 15 SetMarkerPath 202 0 201 SetMarkerPath 202 1 192 SetMarkerPath 202 2 17 SetMarkerPath 202 3 18 SetMarkerPath 202 4 205 SetMarkerPath 202 5 200 SetZone 203 15 SetMarkerPath 203 0 205 SetMarkerPath 203 1 16 SetZone 204 14 SetMarkerPath 204 0 19 SetMarkerPath 204 1 206 SetMarkerPath 204 2 205 SetZone 205 15 SetMarkerPath 205 0 202 SetMarkerPath 205 1 200 SetMarkerPath 205 2 18 SetMarkerPath 205 3 203 SetMarkerPath 205 4 204 SetMarkerPathFlags 205 4 r SetRocketJumpPathFields 205 4 67.0 271.0 0 SetZone 206 14 SetMarkerPath 206 0 211 SetMarkerPath 206 1 204 SetMarkerPath 206 2 207 SetMarkerPath 206 3 16 SetMarkerPath 206 4 225 SetZone 207 13 SetMarkerPath 207 0 206 SetMarkerPath 207 1 191 SetMarkerPath 207 2 190 SetMarkerPath 207 3 55 SetMarkerPath 207 4 225 SetMarkerPath 207 5 233 SetZone 208 12 SetMarkerPath 208 0 210 SetMarkerPath 208 1 214 SetMarkerPath 208 2 215 SetMarkerPath 208 3 217 SetZone 209 12 SetMarkerPath 209 0 211 SetMarkerPath 209 1 210 SetMarkerPath 209 2 218 SetMarkerPath 209 3 213 SetMarkerPath 209 4 219 SetMarkerPath 209 5 217 SetMarkerPath 209 6 212 SetMarkerPath 209 7 92 SetZone 210 12 SetMarkerPath 210 0 209 SetMarkerPath 210 1 208 SetMarkerPath 210 2 213 SetMarkerPath 210 3 219 SetMarkerPath 210 4 217 SetMarkerPath 210 5 218 SetMarkerPath 210 6 215 SetZone 211 12 SetMarkerPath 211 0 206 SetMarkerPath 211 1 209 SetMarkerPath 211 2 218 SetMarkerPath 211 3 212 SetMarkerPath 211 4 213 SetZone 212 15 SetMarkerPath 212 0 233 SetMarkerPath 212 1 213 SetMarkerPath 212 2 211 SetMarkerPathFlags 212 2 r SetRocketJumpPathFields 212 2 64.0 266.0 0 SetZone 213 12 SetMarkerPath 213 0 212 SetMarkerPath 213 1 218 SetMarkerPath 213 2 219 SetMarkerPath 213 3 209 SetMarkerPathFlags 213 3 r SetRocketJumpPathFields 213 3 66.0 228.0 0 SetMarkerPath 213 4 211 SetMarkerPathFlags 213 4 r SetRocketJumpPathFields 213 4 73.0 324.0 0 SetZone 214 12 SetMarkerPath 214 0 208 SetMarkerPath 214 1 220 SetMarkerPath 214 2 217 SetMarkerPath 214 3 215 SetZone 215 12 SetMarkerPath 215 0 214 SetMarkerPath 215 1 216 SetMarkerPath 215 2 219 SetMarkerPath 215 3 208 SetMarkerPath 215 4 217 SetZone 216 12 SetMarkerPath 216 0 215 SetMarkerPath 216 1 102 SetMarkerPath 216 2 219 SetMarkerPath 216 3 217 SetZone 217 12 SetMarkerPath 217 0 218 SetMarkerPath 217 1 214 SetMarkerPath 217 2 215 SetMarkerPath 217 3 208 SetMarkerPath 217 4 219 SetMarkerPath 217 5 216 SetZone 218 12 SetMarkerPath 218 0 213 SetMarkerPath 218 1 217 SetMarkerPath 218 2 219 SetMarkerPath 218 3 92 SetZone 219 12 SetMarkerPath 219 0 102 SetMarkerPath 219 1 218 SetMarkerPath 219 2 213 SetMarkerPath 219 3 92 SetMarkerPath 219 4 215 SetMarkerPath 219 5 217 SetMarkerPath 219 6 216 SetZone 220 12 SetMarkerPath 220 0 214 SetMarkerPath 220 1 116 SetMarkerPath 220 2 109 SetZone 221 11 SetMarkerPath 221 0 222 SetMarkerPath 221 1 177 SetZone 222 11 SetMarkerPath 222 0 50 SetMarkerPath 222 1 221 SetMarkerPath 222 2 93 SetMarkerPath 222 3 223 SetMarkerPath 222 4 25 SetMarkerPath 222 5 296 SetZone 223 11 SetMarkerPath 223 0 65 SetMarkerPath 223 1 93 SetMarkerPath 223 2 25 SetMarkerPath 223 3 222 SetMarkerPath 223 4 26 SetZone 224 11 SetMarkerPath 224 0 94 SetMarkerPath 224 1 26 SetMarkerPath 224 2 27 SetMarkerPath 224 3 65 SetZone 225 15 SetMarkerPath 225 0 16 SetMarkerPath 225 1 229 SetMarkerPath 225 2 193 SetMarkerPathFlags 225 2 r SetRocketJumpPathFields 225 2 79.0 352.0 0 SetMarkerPath 225 3 207 SetMarkerPathFlags 225 3 r SetRocketJumpPathFields 225 3 79.0 174.0 0 SetMarkerPath 225 4 188 SetMarkerPathFlags 225 4 r SetRocketJumpPathFields 225 4 78.3 -1.0 0 SetMarkerPath 225 5 55 SetMarkerPathFlags 225 5 r SetRocketJumpPathFields 225 5 71.0 117.0 0 SetMarkerPath 225 6 190 SetMarkerPathFlags 225 6 r SetRocketJumpPathFields 225 6 70.0 70.0 0 SetMarkerPath 225 7 206 SetMarkerPathFlags 225 7 r SetRocketJumpPathFields 225 7 65.0 266.0 0 SetZone 226 15 SetMarkerPath 226 0 12 SetMarkerPath 226 1 228 SetZone 227 15 SetMarkerPath 227 0 229 SetMarkerPath 227 1 12 SetMarkerPath 227 2 228 SetMarkerPath 227 3 190 SetMarkerPathFlags 227 3 r SetRocketJumpPathFields 227 3 80.0 250.0 0 SetMarkerPath 227 4 115 SetMarkerPathFlags 227 4 r SetRocketJumpPathFields 227 4 71.0 360.0 0 SetMarkerPath 227 5 188 SetMarkerPathFlags 227 5 r SetRocketJumpPathFields 227 5 78.0 125.0 0 SetZone 228 15 SetMarkerPath 228 0 226 SetMarkerPath 228 1 227 SetMarkerPath 228 2 230 SetMarkerPath 228 3 188 SetMarkerPathFlags 228 3 r SetRocketJumpPathFields 228 3 80.0 41.0 0 SetMarkerPath 228 4 55 SetMarkerPathFlags 228 4 r SetRocketJumpPathFields 228 4 68.0 250.0 0 SetMarkerPath 228 5 115 SetMarkerPathFlags 228 5 r SetRocketJumpPathFields 228 5 65.0 357.0 0 SetMarkerPath 228 6 231 SetMarkerPathFlags 228 6 r SetRocketJumpPathFields 228 6 75.0 129.0 0 SetZone 229 15 SetMarkerPath 229 0 225 SetMarkerPath 229 1 227 SetZone 230 15 SetMarkerPath 230 0 228 SetMarkerPath 230 1 15 SetMarkerPath 230 2 231 SetMarkerPathFlags 230 2 r SetRocketJumpPathFields 230 2 67.0 83.0 1 SetMarkerPath 230 3 55 SetMarkerPathFlags 230 3 r SetRocketJumpPathFields 230 3 68.0 320.0 3 SetZone 231 13 SetMarkerPath 231 0 55 SetMarkerPath 231 1 14 SetMarkerPath 231 2 191 SetMarkerPath 231 3 228 SetMarkerPath 231 4 230 SetMarkerPath 231 5 15 SetMarkerPath 231 6 232 SetMarkerPathFlags 231 6 j SetMarkerPath 231 7 190 SetZone 232 13 SetMarkerPath 232 0 99 SetMarkerPathFlags 232 0 j SetMarkerPath 232 1 14 SetMarkerPath 232 2 231 SetMarkerPath 232 3 55 SetMarkerPath 232 4 228 SetZone 233 15 SetMarkerPath 233 0 15 SetMarkerPath 233 1 212 SetMarkerPath 233 2 207 SetMarkerPathFlags 233 2 r SetRocketJumpPathFields 233 2 76.0 6.0 0 SetMarkerPath 233 3 191 SetMarkerPathFlags 233 3 r SetRocketJumpPathFields 233 3 75.0 64.0 0 SetZone 234 9 SetMarkerPath 234 0 238 SetMarkerPath 234 1 243 SetMarkerPath 234 2 235 SetMarkerPath 234 3 56 SetMarkerPath 234 4 242 SetMarkerPath 234 5 179 SetZone 235 9 SetMarkerPath 235 0 56 SetMarkerPath 235 1 234 SetMarkerPath 235 2 237 SetMarkerPath 235 3 242 SetZone 236 9 SetMarkerPath 236 0 240 SetMarkerPath 236 1 239 SetMarkerPath 236 2 31 SetMarkerPath 236 3 178 SetZone 237 9 SetMarkerPath 237 0 56 SetMarkerPath 237 1 235 SetMarkerPath 237 2 178 SetMarkerPath 237 3 242 SetZone 238 9 SetMarkerPath 238 0 239 SetMarkerPath 238 1 234 SetMarkerPath 238 2 179 SetMarkerPath 238 3 56 SetMarkerPath 238 4 242 SetZone 239 9 SetMarkerPath 239 0 236 SetMarkerPath 239 1 238 SetMarkerPath 239 2 237 SetMarkerPath 239 3 178 SetZone 240 9 SetMarkerPath 240 0 177 SetMarkerPath 240 1 236 SetMarkerPath 240 2 31 SetMarkerPath 240 3 178 SetMarkerPath 240 4 241 SetZone 241 9 SetMarkerPath 241 0 31 SetMarkerPath 241 1 242 SetMarkerPath 241 2 177 SetMarkerPathFlags 241 2 r SetRocketJumpPathFields 241 2 52.0 203.0 4 SetZone 242 9 SetMarkerPath 242 0 56 SetMarkerPath 242 1 241 SetMarkerPath 242 2 237 SetMarkerPath 242 3 179 SetMarkerPath 242 4 235 SetZone 243 9 SetMarkerPath 243 0 234 SetMarkerPath 243 1 244 SetMarkerPath 243 2 56 SetZone 244 9 SetMarkerPath 244 0 243 SetMarkerPath 244 1 180 SetMarkerPath 244 2 56 SetZone 245 10 SetMarkerPath 245 0 248 SetMarkerPath 245 1 104 SetMarkerPath 245 2 105 SetMarkerPath 245 3 103 SetMarkerPath 245 4 22 SetMarkerPath 245 5 56 SetZone 246 10 SetMarkerPath 246 0 247 SetMarkerPath 246 1 248 SetMarkerPath 246 2 242 SetMarkerPath 246 3 238 SetMarkerPath 246 4 56 SetZone 247 10 SetMarkerPath 247 0 177 SetMarkerPath 247 1 246 SetMarkerPath 247 2 241 SetMarkerPath 247 3 242 SetMarkerPath 247 4 31 SetZone 248 10 SetMarkerPath 248 0 246 SetMarkerPath 248 1 245 SetMarkerPath 248 2 235 SetMarkerPath 248 3 56 SetMarkerPath 248 4 242 SetZone 249 10 SetMarkerPath 249 0 250 SetMarkerPath 249 1 252 SetMarkerPath 249 2 56 SetMarkerPath 249 3 236 SetZone 250 10 SetMarkerPath 250 0 251 SetMarkerPath 250 1 249 SetMarkerPath 250 2 237 SetMarkerPath 250 3 56 SetMarkerPath 250 4 180 SetMarkerPath 250 5 179 SetMarkerPath 250 6 242 SetZone 251 10 SetMarkerPath 251 0 23 SetMarkerPath 251 1 250 SetMarkerPath 251 2 180 SetMarkerPath 251 3 56 SetMarkerPath 251 4 179 SetMarkerPath 251 5 242 SetMarkerPath 251 6 244 SetMarkerPath 251 7 54 SetMarkerPathFlags 251 7 r SetRocketJumpPathFields 251 7 62.0 213.0 0 SetZone 252 10 SetMarkerPath 252 0 249 SetMarkerPath 252 1 24 SetMarkerPath 252 2 240 SetMarkerPath 252 3 54 SetMarkerPathFlags 252 3 r SetRocketJumpPathFields 252 3 80.0 2.0 15 SetZone 253 10 SetMarkerPath 253 0 257 SetMarkerPath 253 1 54 SetMarkerPath 253 2 258 SetMarkerPath 253 3 254 SetMarkerPath 253 4 251 SetMarkerPath 253 5 250 SetMarkerPath 253 6 242 SetZone 254 10 SetMarkerPath 254 0 24 SetMarkerPath 254 1 257 SetMarkerPath 254 2 238 SetMarkerPath 254 3 242 SetMarkerPath 254 4 235 SetZone 255 10 SetMarkerPath 255 0 258 SetMarkerPath 255 1 256 SetMarkerPath 255 2 257 SetMarkerPath 255 3 104 SetMarkerPath 255 4 23 SetMarkerPath 255 5 251 SetMarkerPath 255 6 22 SetMarkerPath 255 7 103 SetZone 256 10 SetMarkerPath 256 0 255 SetMarkerPath 256 1 257 SetMarkerPath 256 2 258 SetMarkerPath 256 3 245 SetMarkerPath 256 4 103 SetMarkerPath 256 5 56 SetZone 257 10 SetMarkerPath 257 0 254 SetMarkerPath 257 1 253 SetMarkerPath 257 2 256 SetMarkerPath 257 3 255 SetMarkerPath 257 4 258 SetMarkerPath 257 5 56 SetMarkerPath 257 6 235 SetZone 258 10 SetMarkerPath 258 0 253 SetMarkerPath 258 1 255 SetMarkerPath 258 2 256 SetMarkerPath 258 3 257 SetMarkerPath 258 4 251 SetMarkerPath 258 5 235 SetMarkerPath 258 6 248 SetMarkerPath 258 7 23 SetZone 259 16 SetMarkerPath 259 0 264 SetMarkerPath 259 1 260 SetZone 260 16 SetMarkerPath 260 0 259 SetMarkerPath 260 1 11 SetZone 261 16 SetMarkerPath 261 0 262 SetMarkerPath 261 1 85 SetZone 262 16 SetMarkerPath 262 0 261 SetMarkerPath 262 1 263 SetMarkerPath 262 2 267 SetMarkerPath 262 3 265 SetMarkerPath 262 4 64 SetZone 263 16 SetMarkerPath 263 0 262 SetMarkerPath 263 1 264 SetMarkerPath 263 2 111 SetMarkerPath 263 4 267 SetMarkerPath 263 5 266 SetZone 264 16 SetMarkerPath 264 0 263 SetMarkerPath 264 1 259 SetZone 265 16 SetMarkerPath 265 0 111 SetMarkerPath 265 1 266 SetMarkerPath 265 2 267 SetMarkerPath 265 3 11 SetMarkerPathFlags 265 3 r SetRocketJumpPathFields 265 3 62.0 152.0 0 SetMarkerPath 265 5 272 SetZone 266 16 SetMarkerPath 266 0 265 SetMarkerPath 266 1 64 SetMarkerPath 266 2 267 SetMarkerPath 266 3 85 SetZone 267 16 SetMarkerPath 267 0 265 SetMarkerPath 267 1 261 SetMarkerPath 267 2 266 SetMarkerPath 267 3 64 SetMarkerPath 267 4 85 SetMarkerPath 267 5 88 SetMarkerPath 267 6 299 SetZone 268 16 SetMarkerPath 268 0 88 SetMarkerPath 268 1 7 SetMarkerPath 268 2 85 SetZone 269 16 SetMarkerPath 269 0 86 SetMarkerPath 269 1 270 SetZone 270 16 SetMarkerPath 270 0 269 SetMarkerPath 270 1 89 SetZone 271 17 SetMarkerPath 271 0 274 SetMarkerPath 271 1 272 SetZone 272 17 SetMarkerPath 272 0 271 SetMarkerPath 272 1 265 SetZone 273 17 SetMarkerPath 273 0 282 SetMarkerPath 273 1 274 SetMarkerPath 273 2 283 SetMarkerPath 273 3 287 SetMarkerPath 273 4 59 SetMarkerPath 273 5 276 SetMarkerPath 273 6 293 SetZone 274 17 SetMarkerPath 274 0 273 SetMarkerPath 274 1 271 SetZone 275 17 SetMarkerPath 275 0 281 SetMarkerPath 275 1 61 SetZone 276 17 SetMarkerPath 276 0 59 SetMarkerPath 276 1 37 SetMarkerPath 276 2 280 SetMarkerPath 276 3 80 SetMarkerPath 276 4 278 SetMarkerPath 276 5 294 SetMarkerPath 276 6 284 SetZone 277 17 SetMarkerPath 277 0 73 SetMarkerPath 277 1 292 SetMarkerPath 277 2 289 SetMarkerPath 277 3 285 SetMarkerPath 277 4 286 SetZone 278 17 SetMarkerPath 278 0 59 SetMarkerPath 278 1 73 SetMarkerPath 278 2 284 SetMarkerPath 278 3 276 SetMarkerPath 278 4 80 SetZone 279 17 SetMarkerPath 279 0 284 SetMarkerPath 279 1 288 SetMarkerPath 279 2 280 SetZone 280 17 SetMarkerPath 280 0 276 SetMarkerPath 280 1 294 SetMarkerPath 280 2 279 SetMarkerPath 280 3 59 SetMarkerPath 280 4 288 SetZone 281 17 SetMarkerPath 281 0 278 SetMarkerPath 281 1 61 SetMarkerPath 281 2 290 SetMarkerPath 281 3 275 SetZone 282 17 SetMarkerPath 282 0 273 SetMarkerPath 282 1 287 SetMarkerPath 282 2 285 SetMarkerPath 282 3 286 SetMarkerPath 282 4 40 SetZone 283 17 SetMarkerPath 283 0 294 SetMarkerPath 283 1 273 SetMarkerPath 283 2 293 SetMarkerPath 283 3 53 SetMarkerPath 283 4 287 SetZone 284 17 SetMarkerPath 284 0 276 SetMarkerPath 284 1 278 SetMarkerPath 284 2 279 SetMarkerPath 284 3 59 SetZone 285 17 SetMarkerPath 285 0 282 SetMarkerPath 285 1 286 SetMarkerPath 285 2 66 SetMarkerPath 285 3 292 SetMarkerPath 285 4 277 SetMarkerPath 285 5 40 SetMarkerPath 285 6 41 SetZone 286 17 SetMarkerPath 286 0 277 SetMarkerPath 286 1 80 SetMarkerPath 286 2 287 SetMarkerPath 286 3 282 SetMarkerPath 286 4 66 SetZone 287 17 SetMarkerPath 287 0 286 SetMarkerPath 287 1 37 SetMarkerPath 287 2 293 SetMarkerPath 287 3 80 SetZone 288 17 SetMarkerPath 288 0 279 SetMarkerPath 288 1 294 SetMarkerPath 288 2 60 SetZone 289 17 SetMarkerPath 289 0 290 SetMarkerPath 289 1 277 SetMarkerPath 289 2 281 SetMarkerPath 289 3 61 SetZone 290 17 SetMarkerPath 290 0 73 SetMarkerPath 290 1 281 SetMarkerPath 290 2 289 SetZone 291 17 SetMarkerPath 291 0 69 SetMarkerPath 291 1 285 SetMarkerPath 291 2 282 SetZone 292 17 SetMarkerPath 292 0 277 SetMarkerPath 292 1 66 SetMarkerPath 292 2 285 SetZone 293 17 SetMarkerPath 293 0 287 SetMarkerPath 293 1 79 SetMarkerPath 293 2 82 SetMarkerPath 293 3 60 SetMarkerPath 293 4 283 SetMarkerPath 293 5 273 SetZone 294 17 SetMarkerPath 294 0 79 SetMarkerPath 294 1 276 SetMarkerPath 294 2 82 SetMarkerPath 294 3 283 SetMarkerPath 294 4 288 SetZone 295 5 SetMarkerPath 295 0 296 SetMarkerPathFlags 295 0 j SetZone 296 11 SetMarkerPath 296 0 295 SetMarkerPathFlags 296 0 j SetZone 297 11 SetMarkerPath 297 0 298 SetMarkerPathFlags 297 0 j SetZone 298 5 SetMarkerPath 298 0 297 SetMarkerPathFlags 298 0 j SetZone 299 16 SetMarkerPath 299 0 262 SetMarkerPathFlags 299 0 j QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dm3hill.bot000066400000000000000000000133551475442401000263110ustar00rootroot00000000000000CreateMarker 197 -145 -216 CreateMarker 95 -45 -216 CreateMarker -15 59 -216 CreateMarker -77 164 -216 CreateMarker 3 277 -216 CreateMarker 124 413 -216 CreateMarker 21 504 -216 CreateMarker -82 406 -216 CreateMarker 70 -166 -216 CreateMarker -131 7 -216 CreateMarker 448 419 -216 CreateMarker 550 311 -216 CreateMarker 545 483 -216 CreateMarker 686 462 -216 CreateMarker 683 250 -216 CreateMarker 562 58 -216 CreateMarker 462 -52 -216 CreateMarker 363 -185 -216 CreateMarker 548 -141 -216 CreateMarker 666 -77 -216 CreateMarker 678 87 -216 CreateMarker 608 175 -456 CreateMarker 619 -52 -456 CreateMarker 642 70 -456 CreateMarker 459 -48 -472 CreateMarker 313 -54 -472 CreateMarker 128 -64 -472 CreateMarker 90 170 -472 CreateMarker -71 192 -448 CreateMarker 195 38 -470 CreateMarker 281 162 -440 CreateMarker 75 391 -472 CreateMarker 158 293 -470 CreateMarker 299 404 -472 CreateMarker 295 304 -467 CreateMarker 464 388 -472 CreateMarker 483 232 -472 CreateMarker 463 92 -472 CreateMarker 631 413 -456 CreateMarker 630 300 -456 CreateMarker 353 59 -463 SetZone 1 1 SetMarkerPath 1 0 20 SetMarkerPath 1 1 13 SetMarkerPath 1 2 12 SetMarkerPath 1 3 19 SetMarkerViewOfs 1 20 SetZone 2 3 SetMarkerPath 2 0 1 SetMarkerPath 2 1 39 SetZone 3 2 SetMarkerPath 3 0 7 SetZone 4 3 SetMarkerPath 4 0 3 SetMarkerPath 4 1 10 SetZone 5 1 SetMarkerPath 5 1 16 SetMarkerPath 5 2 17 SetZone 6 1 SetMarkerPath 6 1 13 SetMarkerPath 6 2 12 SetMarkerPath 6 3 19 SetMarkerPath 6 4 20 SetZone 7 2 SetMarkerPath 7 1 28 SetMarkerPath 7 2 9 SetMarkerPath 7 3 32 SetZone 8 2 SetMarkerPath 8 1 21 SetMarkerPath 8 2 23 SetZone 9 2 SetMarkerPath 9 0 10 SetMarkerPath 9 1 7 SetZone 10 3 SetMarkerPath 10 1 34 SetMarkerPath 10 2 32 SetMarkerPath 10 3 50 SetMarkerPath 10 4 4 SetMarkerPath 10 5 28 SetZone 11 1 SetMarkerPath 11 1 12 SetMarkerPath 11 2 19 SetZone 12 1 SetMarkerPath 12 0 1 SetMarkerPath 12 1 6 SetMarkerPath 12 2 11 SetMarkerPath 12 3 19 SetMarkerPath 12 4 13 SetMarkerPath 12 5 41 SetZone 13 1 SetMarkerPath 13 0 1 SetMarkerPath 13 1 14 SetMarkerPath 13 2 6 SetMarkerPath 13 3 12 SetMarkerPath 13 4 20 SetMarkerPath 13 5 41 SetZone 14 1 SetMarkerPath 14 1 15 SetMarkerPath 14 2 18 SetMarkerPath 14 3 13 SetMarkerPath 14 4 20 SetZone 15 1 SetMarkerPath 15 1 18 SetMarkerPath 15 2 16 SetMarkerPath 15 3 14 SetMarkerPath 15 4 41 SetZone 16 1 SetMarkerPath 16 1 5 SetMarkerPath 16 2 17 SetMarkerPath 16 3 15 SetMarkerPath 16 4 18 SetMarkerPath 16 5 41 SetZone 17 1 SetMarkerPath 17 1 16 SetMarkerPath 17 2 5 SetMarkerPath 17 3 18 SetZone 18 1 SetMarkerPath 18 1 17 SetMarkerPath 18 2 15 SetMarkerPath 18 3 16 SetMarkerPath 18 4 14 SetZone 19 1 SetMarkerPath 19 0 1 SetMarkerPath 19 1 11 SetMarkerPath 19 2 12 SetMarkerPath 19 3 6 SetZone 20 1 SetMarkerPath 20 0 1 SetMarkerPath 20 1 6 SetMarkerPath 20 2 14 SetMarkerPath 20 3 13 SetZone 21 2 SetMarkerPath 21 1 8 SetMarkerPath 21 2 23 SetMarkerPath 21 3 22 SetMarkerPath 21 4 41 SetZone 22 2 SetMarkerPath 22 1 21 SetMarkerPath 22 2 23 SetMarkerPath 22 3 24 SetMarkerPath 22 4 25 SetMarkerPath 22 5 41 SetZone 23 2 SetMarkerPath 23 1 21 SetMarkerPath 23 2 8 SetMarkerPath 23 3 24 SetMarkerPath 23 4 22 SetZone 24 2 SetMarkerPath 24 1 23 SetMarkerPath 24 2 22 SetMarkerPath 24 3 25 SetZone 25 2 SetMarkerPath 25 1 24 SetMarkerPath 25 2 22 SetMarkerPath 25 3 31 SetZone 26 2 SetMarkerPath 26 1 31 SetMarkerPath 26 2 30 SetMarkerPath 26 3 27 SetMarkerPath 26 4 29 SetMarkerPath 26 5 41 SetZone 27 2 SetMarkerPath 27 1 29 SetMarkerPath 27 2 26 SetMarkerPath 27 3 28 SetMarkerPath 27 4 41 SetZone 28 2 SetMarkerPath 28 1 29 SetMarkerPath 28 2 27 SetMarkerPath 28 3 7 SetZone 29 2 SetMarkerPath 29 1 30 SetMarkerPath 29 2 27 SetMarkerPath 29 3 28 SetMarkerPath 29 4 26 SetZone 30 2 SetMarkerPath 30 1 26 SetMarkerPath 30 2 29 SetMarkerPath 30 3 31 SetZone 31 2 SetMarkerPath 31 1 25 SetMarkerPath 31 2 26 SetMarkerPath 31 3 30 SetZone 32 3 SetMarkerPath 32 1 50 SetMarkerPath 32 2 34 SetMarkerPath 32 3 10 SetZone 33 3 SetMarkerPath 33 1 34 SetMarkerPath 33 2 35 SetZone 34 3 SetMarkerPath 34 1 32 SetMarkerPath 34 2 33 SetMarkerPath 34 3 10 SetZone 35 3 SetMarkerPath 35 1 36 SetMarkerPath 35 2 48 SetMarkerPath 35 3 41 SetMarkerPath 35 4 33 SetMarkerPath 35 5 51 SetZone 36 3 SetMarkerPath 36 1 40 SetMarkerPath 36 2 37 SetMarkerPath 36 3 35 SetMarkerPath 36 4 41 SetMarkerPath 36 5 51 SetZone 37 3 SetMarkerPath 37 1 40 SetMarkerPath 37 2 36 SetMarkerPath 37 3 38 SetZone 38 3 SetMarkerPath 38 1 39 SetMarkerPath 38 2 43 SetMarkerPath 38 3 41 SetMarkerPath 38 4 40 SetMarkerPath 38 5 37 SetZone 39 3 SetMarkerPath 39 1 2 SetMarkerPath 39 2 38 SetMarkerPath 39 3 12 SetZone 40 3 SetMarkerPath 40 1 38 SetMarkerPath 40 2 37 SetMarkerPath 40 3 36 SetMarkerPath 40 4 51 SetMarkerPath 40 5 41 SetZone 41 3 SetMarkerPath 41 1 45 SetMarkerPath 41 2 38 SetMarkerPath 41 3 48 SetMarkerPath 41 4 43 SetMarkerPath 41 5 47 SetMarkerPath 41 6 36 SetMarkerPath 41 7 35 SetZone 42 3 SetMarkerPath 42 1 43 SetMarkerPath 42 2 44 SetZone 43 3 SetMarkerPath 43 1 38 SetMarkerPath 43 2 42 SetMarkerPath 43 3 44 SetMarkerPath 43 4 45 SetMarkerPath 43 5 41 SetZone 44 3 SetMarkerPath 44 1 42 SetMarkerPath 44 2 43 SetMarkerPath 44 3 46 SetMarkerPath 44 4 45 SetZone 45 3 SetMarkerPath 45 1 43 SetMarkerPath 45 2 41 SetMarkerPath 45 3 47 SetMarkerPath 45 4 46 SetMarkerPath 45 5 44 SetZone 46 3 SetMarkerPath 46 1 47 SetMarkerPath 46 2 44 SetMarkerPath 46 3 45 SetMarkerPath 46 4 49 SetMarkerPath 46 5 41 SetZone 47 3 SetMarkerPath 47 1 48 SetMarkerPath 47 2 45 SetMarkerPath 47 3 46 SetMarkerPath 47 4 41 SetZone 48 3 SetMarkerPath 48 1 35 SetMarkerPath 48 2 47 SetMarkerPath 48 3 41 SetMarkerPath 48 4 51 SetZone 49 3 SetMarkerPath 49 1 46 SetMarkerPath 49 2 50 SetZone 50 3 SetMarkerPath 50 1 49 SetMarkerPath 50 2 32 SetMarkerPath 50 3 10 SetZone 51 3 SetMarkerPath 51 1 41 SetMarkerPath 51 2 40 SetMarkerPath 51 3 35 SetMarkerPath 51 4 48 SetMarkerPath 51 5 36 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dm4.bot000066400000000000000000000334351475442401000254420ustar00rootroot00000000000000CreateMarker 456 -380 -104 CreateMarker 339 -502 24 CreateMarker 152 -478 24 CreateMarker 148 -231 -67 CreateMarker -77 265 -296 CreateMarker -48 81 -296 CreateMarker -25 -232 -296 CreateMarker 185 -242 -296 CreateMarker 375 -202 -296 CreateMarker 610 -222 -296 CreateMarker 627 -5 -296 CreateMarker 616 -175 24 CreateMarker 557 -1 24 CreateMarker 849 -444 24 CreateMarker 752 -538 -115 CreateMarker 778 -652 -168 CreateMarker 112 364 -312 CreateMarker -240 365 -312 CreateMarker -240 148 -312 CreateMarker 112 145 -312 CreateMarker 112 287 -312 CreateMarker 111 222 -312 CreateMarker -235 226 -312 CreateMarker -240 286 -312 CreateMarker -206 328 -360 CreateMarker -199 186 -360 CreateMarker 636 -421 -120 CreateMarker 73 330 -360 CreateMarker 73 186 -360 CreateMarker 333 -523 -104 CreateMarker 335 -776 -104 CreateMarker 224 -942 -104 CreateMarker 150 -1196 -88 CreateMarker 309 -1188 -24 CreateMarker 351 -1051 24 CreateMarker 357 -854 20 CreateMarker -112 -417 -72 CreateMarker 10 494 -296 CreateMarker -135 511 -296 CreateMarker -233 64 -296 CreateMarker 338 -700 24 CreateMarker 473 -238 -296 CreateMarker 94 -241 -296 CreateMarker 1003 -592 24 CreateMarker 573 -321 24 CreateMarker 846 -308 24 CreateMarker 335 -633 -104 CreateMarker -45 -84 -296 CreateMarker 161 -362 -24 CreateMarker -59 450 -296 CreateMarker 204 -107 -386 CreateMarker 170 -346 -389 CreateMarker 358 -348 -387 CreateMarker 112 -176 -387 CreateMarker 120 219 -296 CreateMarker -248 224 -296 CreateMarker 543 -195 -104 CreateMarker 255 -405 -104 CreateMarker 286 -376 -296 CreateMarker 163 -40 -296 CreateMarker 304 -105 -397 CreateMarker 1038 -444 -104 SetZone 1 4 SetMarkerPath 1 0 2 SetZone 2 4 SetMarkerPath 2 0 3 SetMarkerPath 2 1 90 SetMarkerPath 2 2 89 SetMarkerPath 2 3 95 SetZone 3 3 SetMarkerPath 3 0 4 SetZone 4 3 SetMarkerPath 4 0 1 SetMarkerPath 4 1 65 SetMarkerPath 4 2 18 SetMarkerPath 4 3 17 SetZone 5 10 SetMarkerPath 5 0 6 SetZone 6 8 SetMarkerPath 6 0 66 SetMarkerPath 6 1 38 SetZone 7 2 SetMarkerPath 7 0 8 SetZone 8 2 SetMarkerPath 8 0 62 SetMarkerPath 8 1 63 SetMarkerPath 8 2 96 SetMarkerPath 8 3 58 SetMarkerPathFlags 8 3 r SetRocketJumpPathFields 8 3 80.0 360.0 0 SetZone 9 2 SetMarkerPath 9 0 10 SetZone 10 2 SetMarkerPath 10 0 46 SetMarkerPath 10 1 14 SetGoal 11 4 SetZone 11 1 SetMarkerPath 11 0 92 SetMarkerPath 11 1 12 SetMarkerPath 11 2 33 SetGoal 12 13 SetZone 12 1 SetMarkerPath 12 0 11 SetMarkerPath 12 1 93 SetMarkerPath 12 2 33 SetGoal 13 23 SetZone 13 9 SetMarkerPath 13 0 91 SetMarkerPath 13 1 5 SetMarkerPath 13 2 16 SetMarkerPath 13 3 15 SetGoal 14 24 SetZone 14 2 SetMarkerPath 14 0 63 SetMarkerPath 14 1 96 SetMarkerPath 14 2 46 SetMarkerPath 14 3 62 SetMarkerPath 14 4 53 SetMarkerPathFlags 14 4 r SetRocketJumpPathFields 14 4 78.3 -1.0 0 SetMarkerPath 14 5 111 SetMarkerPathFlags 14 5 r SetRocketJumpPathFields 14 5 78.3 -1.0 0 SetMarkerPath 14 6 58 SetMarkerPathFlags 14 6 r SetRocketJumpPathFields 14 6 75.0 45.0 0 SetGoal 15 18 SetZone 15 9 SetMarkerPath 15 0 13 SetMarkerPath 15 1 91 SetMarkerPath 15 2 5 SetMarkerPath 15 3 16 SetGoal 16 18 SetZone 16 9 SetMarkerPath 16 0 91 SetMarkerPath 16 1 13 SetMarkerPath 16 2 5 SetMarkerPath 16 3 15 SetGoal 17 10 SetZone 17 3 SetMarkerPath 17 0 65 SetMarkerPath 17 1 4 SetGoal 18 12 SetZone 18 3 SetMarkerPath 18 0 65 SetMarkerPath 18 1 4 SetGoal 19 15 SetZone 19 5 SetMarkerPath 19 0 85 SetMarkerPath 19 1 86 SetMarkerPath 19 2 20 SetGoal 20 15 SetZone 20 5 SetMarkerPath 20 0 85 SetMarkerPath 20 1 86 SetMarkerPath 20 2 19 SetMarkerPath 20 3 22 SetMarkerPath 20 4 47 SetGoal 21 14 SetZone 21 5 SetMarkerPath 21 0 47 SetMarkerPath 21 1 86 SetMarkerPath 21 2 85 SetMarkerPath 21 3 23 SetMarkerPath 21 4 22 SetMarkerPath 21 5 20 SetGoal 22 14 SetZone 22 5 SetMarkerPath 22 0 85 SetMarkerPath 22 1 86 SetMarkerPath 22 2 21 SetMarkerPath 22 3 23 SetMarkerPath 22 4 47 SetMarkerPath 22 5 20 SetGoal 23 14 SetZone 23 5 SetMarkerPath 23 0 86 SetMarkerPath 23 1 85 SetMarkerPath 23 2 21 SetMarkerPath 23 3 22 SetMarkerPath 23 4 47 SetMarkerPath 23 5 20 SetGoal 24 23 SetZone 24 4 SetMarkerPath 24 0 90 SetMarkerPath 24 1 95 SetMarkerPath 24 2 35 SetGoal 25 8 SetZone 25 10 SetMarkerPath 25 0 98 SetGoal 26 24 SetZone 26 11 SetMarkerPath 26 0 70 SetMarkerPath 26 1 48 SetMarkerPath 26 2 30 SetMarkerPath 26 3 37 SetGoal 27 23 SetZone 27 11 SetMarkerPath 27 0 28 SetMarkerPath 27 1 29 SetMarkerPath 27 2 69 SetMarkerPath 27 3 116 SetGoal 28 11 SetZone 28 11 SetMarkerPath 28 0 27 SetMarkerPath 28 1 29 SetMarkerPath 28 2 116 SetMarkerPath 28 4 98 SetMarkerPathFlags 28 4 r SetRocketJumpPathFields 28 4 73.0 100.0 8 SetGoal 29 11 SetZone 29 11 SetMarkerPath 29 0 27 SetMarkerPath 29 1 28 SetMarkerPath 29 2 69 SetGoal 30 1 SetZone 30 11 SetMarkerPath 30 0 70 SetMarkerPath 30 1 26 SetMarkerPath 30 2 48 SetMarkerPath 30 3 37 SetGoal 31 23 SetZone 31 10 SetMarkerPath 31 0 68 SetMarkerPath 31 1 28 SetMarkerPath 31 2 69 SetMarkerPath 31 3 98 SetGoal 32 17 SetZone 32 8 SetMarkerPath 32 0 56 SetMarkerPath 32 1 99 SetMarkerPath 32 2 53 SetMarkerPath 32 3 39 SetMarkerPath 32 4 63 SetMarkerPath 32 5 62 SetZone 33 1 SetMarkerPath 33 0 12 SetMarkerPath 33 1 11 SetMarkerPath 33 2 92 SetMarkerPath 33 3 93 SetMarkerPath 33 4 104 SetZone 34 12 SetMarkerPath 34 0 58 SetMarkerPath 34 1 91 SetZone 35 4 SetMarkerPath 35 0 89 SetMarkerPath 35 1 90 SetMarkerPath 35 2 24 SetZone 36 5 SetMarkerPath 36 0 87 SetMarkerPath 36 1 86 SetMarkerPath 36 2 42 SetMarkerPath 36 3 47 SetZone 37 11 SetMarkerPath 37 0 30 SetMarkerPath 37 1 26 SetMarkerPath 37 2 48 SetMarkerPath 37 3 70 SetZone 38 10 SetMarkerPath 38 0 52 SetMarkerPath 38 1 6 SetGoal 39 9 SetZone 39 6 SetMarkerPath 39 0 66 SetMarkerPathFlags 39 0 r SetRocketJumpPathFields 39 0 78.3 -1.0 0 SetMarkerPath 39 1 43 SetMarkerPath 39 2 62 SetMarkerPath 39 3 63 SetMarkerPath 39 4 111 SetMarkerPath 39 5 56 SetMarkerPathFlags 39 5 r SetRocketJumpPathFields 39 5 47.0 75.0 0 SetGoal 40 16 SetZone 40 5 SetMarkerPath 40 0 85 SetMarkerPath 40 1 86 SetMarkerPath 40 2 41 SetGoal 41 24 SetZone 41 5 SetMarkerPath 41 0 40 SetMarkerPath 41 1 42 SetMarkerPath 41 2 85 SetMarkerPath 41 3 86 SetGoal 42 23 SetZone 42 5 SetMarkerPath 42 0 86 SetMarkerPath 42 1 87 SetMarkerPath 42 2 85 SetMarkerPath 42 3 41 SetGoal 43 20 SetZone 43 7 SetMarkerPath 43 0 49 SetMarkerPath 43 1 58 SetMarkerPath 43 2 63 SetGoal 44 6 SetZone 44 6 SetMarkerPath 44 0 112 SetGoal 45 3 SetZone 45 1 SetMarkerPath 45 0 60 SetMarkerPath 45 1 59 SetGoal 46 22 SetZone 46 2 SetMarkerPath 46 0 14 SetMarkerPath 46 1 10 SetGoal 47 21 SetZone 47 5 SetMarkerPath 47 0 85 SetMarkerPath 47 1 86 SetMarkerPath 47 2 23 SetMarkerPath 47 3 20 SetGoal 48 2 SetZone 48 11 SetMarkerPath 48 0 9 SetMarkerPath 48 1 30 SetMarkerPath 48 2 26 SetMarkerPath 48 3 37 SetGoal 49 7 SetZone 49 7 SetMarkerPath 49 0 43 SetMarkerPath 49 1 58 SetGoal 51 5 SetZone 51 6 SetMarkerPath 51 0 84 SetMarkerPath 51 1 53 SetMarkerPath 51 2 81 SetMarkerPath 51 3 55 SetMarkerPath 51 4 62 SetMarkerPath 51 5 111 SetGoal 52 19 SetZone 52 10 SetMarkerPath 52 0 38 SetMarkerPath 52 1 100 SetGoal 53 19 SetZone 53 6 SetMarkerPath 53 0 84 SetMarkerPath 53 1 112 SetMarkerPath 53 2 55 SetMarkerPath 53 3 99 SetMarkerPathFlags 53 3 r SetRocketJumpPathFields 53 3 78.3 -1.0 0 SetMarkerPath 53 4 62 SetMarkerPath 53 5 63 SetMarkerPath 53 6 58 SetMarkerPathFlags 53 6 r SetRocketJumpPathFields 53 6 78.3 -1.0 0 SetGoal 54 19 SetZone 54 8 SetMarkerPath 54 0 95 SetMarkerPath 54 1 56 SetZone 55 6 SetMarkerPath 55 0 81 SetMarkerPath 55 1 51 SetMarkerPath 55 2 53 SetMarkerPath 55 3 84 SetMarkerPath 55 4 63 SetMarkerPath 55 5 62 SetMarkerPath 55 6 66 SetMarkerPathFlags 55 6 r SetRocketJumpPathFields 55 6 78.3 -1.0 0 SetZone 56 8 SetMarkerPath 56 0 57 SetMarkerPath 56 1 32 SetMarkerPath 56 2 54 SetMarkerPath 56 3 51 SetMarkerPath 56 4 62 SetMarkerPath 56 5 63 SetMarkerPath 56 6 58 SetZone 57 12 SetMarkerPath 57 0 103 SetMarkerPath 57 1 56 SetMarkerPath 57 2 63 SetZone 58 12 SetMarkerPath 58 0 43 SetMarkerPath 58 1 34 SetMarkerPath 58 2 103 SetMarkerPath 58 3 63 SetMarkerPath 58 4 53 SetMarkerPath 58 5 66 SetMarkerPathFlags 58 5 r SetRocketJumpPathFields 58 5 47.0 185.0 0 SetZone 59 1 SetMarkerPath 59 0 104 SetMarkerPath 59 1 60 SetMarkerPath 59 2 45 SetMarkerPath 59 3 94 SetZone 60 1 SetMarkerPath 60 0 45 SetMarkerPath 60 1 94 SetMarkerPath 60 2 59 SetMarkerPath 60 3 102 SetZone 61 2 SetMarkerPath 61 0 97 SetMarkerPath 61 1 102 SetZone 62 2 SetMarkerPath 62 0 97 SetMarkerPath 62 1 63 SetMarkerPath 62 2 8 SetMarkerPath 62 3 14 SetMarkerPath 62 4 51 SetMarkerPathFlags 62 4 r SetRocketJumpPathFields 62 4 78.3 -1.0 0 SetMarkerPath 62 5 39 SetMarkerPathFlags 62 5 r SetRocketJumpPathFields 62 5 78.3 -1.0 0 SetMarkerPath 62 6 53 SetMarkerPathFlags 62 6 r SetRocketJumpPathFields 62 6 78.3 -1.0 0 SetZone 63 2 SetMarkerPath 63 0 62 SetMarkerPath 63 1 14 SetMarkerPath 63 2 96 SetMarkerPath 63 3 53 SetMarkerPathFlags 63 3 r SetRocketJumpPathFields 63 3 78.3 -1.0 0 SetMarkerPath 63 4 111 SetMarkerPathFlags 63 4 r SetRocketJumpPathFields 63 4 78.3 -1.0 0 SetZone 64 2 SetMarkerPath 64 0 65 SetMarkerPath 64 1 96 SetZone 65 3 SetMarkerPath 65 0 64 SetMarkerPath 65 1 4 SetMarkerPath 65 2 17 SetMarkerPath 65 3 18 SetZone 66 8 SetMarkerPath 66 0 6 SetMarkerPath 66 1 67 SetMarkerPath 66 2 99 SetMarkerPath 66 3 51 SetMarkerPath 66 4 39 SetMarkerPath 66 5 62 SetZone 67 8 SetMarkerPath 67 0 66 SetMarkerPath 67 1 39 SetMarkerPath 67 2 51 SetZone 68 10 SetMarkerPath 68 0 100 SetMarkerPath 68 1 31 SetMarkerPath 68 2 69 SetMarkerPath 68 3 28 SetMarkerPath 68 4 98 SetZone 69 11 SetMarkerPath 69 0 27 SetMarkerPath 69 1 29 SetMarkerPath 69 2 70 SetMarkerPath 69 3 68 SetMarkerPathFlags 69 3 r SetRocketJumpPathFields 69 3 70.0 345.0 0 SetMarkerPathAngleHint 69 3 45 SetZone 70 11 SetMarkerPath 70 0 69 SetMarkerPath 70 1 30 SetMarkerPath 70 2 26 SetMarkerPath 70 3 37 SetZone 71 1 SetMarkerFlag 71 u SetMarkerPath 71 0 104 SetZone 72 1 SetMarkerFlag 72 u SetMarkerPath 72 0 104 SetZone 73 1 SetMarkerFlag 73 u SetMarkerPath 73 0 94 SetZone 74 1 SetMarkerFlag 74 u SetMarkerPath 74 0 45 SetZone 75 1 SetMarkerFlag 75 u SetMarkerPath 75 0 71 SetMarkerPath 75 1 76 SetMarkerPath 75 2 59 SetZone 76 1 SetMarkerFlag 76 u SetMarkerPath 76 0 74 SetMarkerPath 76 1 75 SetMarkerPath 76 2 59 SetZone 77 1 SetMarkerFlag 77 u SetMarkerPath 77 0 73 SetMarkerPath 77 1 78 SetMarkerPath 77 2 59 SetZone 78 1 SetMarkerFlag 78 u SetMarkerPath 78 0 77 SetMarkerPath 78 1 72 SetMarkerPath 78 2 59 SetZone 79 1 SetMarkerFlag 79 u SetMarkerPath 79 0 72 SetMarkerPathFlags 79 0 j SetZone 80 1 SetMarkerFlag 80 u SetMarkerPath 80 0 73 SetMarkerPathFlags 80 0 j SetZone 81 6 SetMarkerPath 81 0 55 SetMarkerPath 81 1 51 SetMarkerPath 81 2 7 SetMarkerPath 81 3 111 SetZone 82 1 SetMarkerFlag 82 u SetMarkerPath 82 0 71 SetMarkerPathFlags 82 0 j SetZone 83 1 SetMarkerFlag 83 u SetMarkerPath 83 0 74 SetMarkerPathFlags 83 0 j SetZone 84 6 SetMarkerPath 84 0 101 SetMarkerPath 84 1 53 SetMarkerPath 84 2 51 SetMarkerPath 84 3 112 SetMarkerPath 84 4 55 SetZone 85 5 SetMarkerPath 85 0 101 SetMarkerPath 85 1 86 SetMarkerPath 85 2 40 SetMarkerPath 85 3 19 SetMarkerPath 85 4 22 SetMarkerPath 85 5 47 SetZone 86 5 SetMarkerPath 86 0 87 SetMarkerPath 86 1 85 SetMarkerPath 86 2 47 SetMarkerPath 86 3 23 SetMarkerPath 86 4 42 SetZone 87 5 SetMarkerPath 87 0 88 SetMarkerPath 87 1 86 SetZone 88 5 SetMarkerPath 88 0 89 SetMarkerPath 88 1 87 SetZone 89 4 SetMarkerPath 89 0 90 SetMarkerPath 89 1 88 SetMarkerPath 89 2 35 SetMarkerPath 89 3 2 SetZone 90 4 SetMarkerPath 90 0 2 SetMarkerPath 90 1 89 SetMarkerPath 90 2 24 SetMarkerPath 90 3 95 SetMarkerPath 90 4 35 SetZone 91 9 SetMarkerPath 91 0 34 SetMarkerPath 91 1 13 SetMarkerPath 91 2 15 SetMarkerPath 91 3 16 SetZone 92 1 SetMarkerPath 92 0 11 SetMarkerPath 92 1 104 SetMarkerPath 92 2 33 SetZone 93 1 SetMarkerPath 93 0 12 SetMarkerPath 93 1 104 SetMarkerPath 93 2 33 SetZone 94 1 SetMarkerPath 94 0 60 SetMarkerPath 94 1 59 SetZone 95 4 SetMarkerPath 95 0 90 SetMarkerPath 95 1 2 SetMarkerPath 95 2 24 SetMarkerPath 95 3 54 SetZone 96 2 SetMarkerPath 96 0 63 SetMarkerPath 96 1 64 SetMarkerPath 96 2 8 SetZone 97 2 SetMarkerPath 97 0 61 SetMarkerPath 97 1 62 SetZone 98 10 SetMarkerPath 98 0 25 SetMarkerPath 98 1 31 SetMarkerPath 98 2 29 SetMarkerPath 98 3 68 SetZone 99 8 SetMarkerPath 99 0 32 SetMarkerPath 99 1 66 SetMarkerPath 99 2 53 SetMarkerPath 99 3 39 SetMarkerPath 99 4 62 SetZone 100 10 SetMarkerPath 100 0 68 SetMarkerPath 100 1 52 SetZone 101 6 SetMarkerPath 101 0 84 SetMarkerPath 101 1 85 SetZone 102 1 SetMarkerPath 102 0 61 SetMarkerPath 102 1 60 SetZone 103 12 SetMarkerPath 103 0 58 SetMarkerPath 103 1 57 SetMarkerPath 103 2 63 SetZone 104 1 SetMarkerPath 104 0 59 SetMarkerPath 104 1 93 SetMarkerPath 104 2 92 SetMarkerPath 104 3 33 SetZone 105 2 SetMarkerFlag 105 u SetMarkerPath 105 0 62 SetMarkerPath 105 1 108 SetMarkerPath 105 2 115 SetZone 106 2 SetMarkerFlag 106 u SetMarkerPath 106 0 62 SetMarkerPathFlags 106 0 r SetRocketJumpPathFields 106 0 80.0 270.0 0 SetMarkerPath 106 1 107 SetZone 107 2 SetMarkerFlag 107 u SetMarkerPath 107 0 8 SetMarkerPathFlags 107 0 r SetRocketJumpPathFields 107 0 80.0 270.0 0 SetMarkerPath 107 1 106 SetZone 108 2 SetMarkerFlag 108 u SetMarkerPath 108 1 62 SetMarkerPathFlags 108 1 r SetRocketJumpPathFields 108 1 75.0 90.0 0 SetZone 109 1 SetMarkerFlag 109 u SetMarkerPath 109 0 76 SetZone 110 1 SetMarkerFlag 110 u SetMarkerPath 110 0 77 SetZone 111 6 SetMarkerPath 111 0 51 SetMarkerPath 111 1 39 SetMarkerPath 111 2 81 SetMarkerPath 111 3 62 SetZone 112 6 SetMarkerPath 112 0 53 SetMarkerPath 112 1 44 SetMarkerPath 112 2 84 SetMarkerPath 112 3 62 SetMarkerPath 112 4 63 SetMarkerPath 112 5 58 SetZone 113 2 SetMarkerFlag 113 u SetMarkerPath 113 0 62 SetMarkerPath 113 1 8 SetZone 114 2 SetMarkerFlag 114 u SetMarkerPath 114 0 62 SetZone 115 2 SetMarkerFlag 115 u SetMarkerPath 115 0 14 SetMarkerPathFlags 115 0 r SetRocketJumpPathFields 115 0 80.0 180.0 0 SetZone 116 11 SetMarkerPath 116 0 28 SetMarkerPath 116 1 27 SetMarkerPath 116 2 68 SetMarkerPathFlags 116 2 r SetRocketJumpPathFields 116 2 70.0 360.0 5 SetMarkerPath 116 3 31 SetMarkerPathFlags 116 3 r SetRocketJumpPathFields 116 3 79.0 40.0 5 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dm6.bot000066400000000000000000000400711475442401000254360ustar00rootroot00000000000000CreateMarker 152 -841 171 CreateMarker 1522 -1090 40 CreateMarker 1145 -1090 -40 CreateMarker 1503 -555 88 CreateMarker 1072 -453 40 CreateMarker 710 -1089 56 CreateMarker 299 -1088 112 CreateMarker 1025 -706 40 CreateMarker 1278 -436 40 CreateMarker 1515 -287 40 CreateMarker 1726 -318 40 CreateMarker 1786 -577 40 CreateMarker 1638 -566 40 CreateMarker 1733 -724 40 CreateMarker 1664 -1023 40 CreateMarker 1354 -342 168 CreateMarker 1627 -313 168 CreateMarker 1740 -793 168 CreateMarker 1392 -1089 247 CreateMarker 1229 -951 256 CreateMarker 1220 -1225 256 CreateMarker 694 -1087 256 CreateMarker 809 -1171 256 CreateMarker 943 -1303 256 CreateMarker 1031 -1472 256 CreateMarker 1038 -1305 256 CreateMarker 1716 -1016 168 CreateMarker 809 -983 256 CreateMarker 481 -1119 256 CreateMarker 431 -1362 256 CreateMarker 424 -1508 256 CreateMarker 429 -1786 184 CreateMarker 87 -1516 40 CreateMarker 87 -1621 40 CreateMarker 797 -1711 40 CreateMarker 74 -1780 40 CreateMarker 596 -1670 40 CreateMarker 998 -1643 40 CreateMarker 1027 -1481 40 CreateMarker 202 -736 136 CreateMarker 304 -736 136 CreateMarker 96 -736 136 CreateMarker 304 -894 136 CreateMarker 96 -888 136 CreateMarker 1022 -1295 -24 CreateMarker 1025 -885 -24 CreateMarker 925 -1088 -40 CreateMarker 1894 -419 168 CreateMarker 1630 -149 168 CreateMarker 424 -1653 232 CreateMarker 1358 -1090 -8 CreateMarker 1189 -1202 -40 CreateMarker 1194 -991 -40 CreateMarker 1300 -538 168 CreateMarker 144 -1966 88 CreateMarker 411 -1945 168 CreateMarker 194 -1786 56 CreateMarker 923 -1199 -40 CreateMarker 1751 -417 168 CreateMarker 1648 -889 40 CreateMarker 888 -1090 -280 CreateMarker 248 -1854 56 CreateMarker 247 -1719 56 CreateMarker 1025 -1015 -32 CreateMarker 1024 -1173 -32 CreateMarker 512 -1938 40 CreateMarker 314 -2064 40 CreateMarker 1383 -438 40 CreateMarker 395 -1087 128 CreateMarker 776 -1085 -40 CreateMarker 554 -1089 113 CreateMarker 410 -1676 40 CreateMarker 248 -843 168 CreateMarker 1528 -1085 207 CreateMarker 1750 -573 168 CreateMarker 1497 -308 168 CreateMarker 1023 -1093 96 SetZone 1 7 SetMarkerPath 1 0 4 SetMarkerPath 1 1 38 SetMarkerPath 1 2 123 SetMarkerPath 1 3 26 SetZone 2 7 SetMarkerPath 2 0 1 SetZone 3 12 SetMarkerPath 3 0 2 SetMarkerPath 3 1 95 SetMarkerPath 3 2 94 SetMarkerPath 3 3 35 SetMarkerPath 3 4 58 SetZone 4 12 SetMarkerPath 4 0 3 SetZone 5 7 SetMarkerPath 5 0 84 SetZone 6 10 SetMarkerPath 6 0 16 SetMarkerPath 6 1 59 SetMarkerPath 6 2 60 SetZone 7 12 SetMarkerFlag 7 u SetMarkerPath 7 0 35 SetZone 8 6 SetMarkerPath 8 0 81 SetMarkerPath 8 1 48 SetMarkerPath 8 2 101 SetMarkerPath 8 3 82 SetZone 9 6 SetMarkerPath 9 0 21 SetMarkerPath 9 1 73 SetMarkerPath 9 2 81 SetMarkerPath 9 3 49 SetGoal 10 14 SetZone 10 5 SetMarkerPath 10 0 79 SetMarkerPath 10 1 11 SetMarkerPath 10 2 103 SetGoal 11 14 SetZone 11 5 SetMarkerPath 11 0 10 SetMarkerPath 11 1 71 SetMarkerPath 11 2 103 SetMarkerPath 11 3 109 SetMarkerPath 11 4 79 SetMarkerPath 11 5 115 SetMarkerPath 11 6 128 SetGoal 12 4 SetZone 12 12 SetMarkerPath 12 0 35 SetMarkerPath 12 1 2 SetGoal 13 15 SetZone 13 13 SetMarkerPath 13 0 65 SetMarkerPath 13 1 66 SetGoal 14 13 SetZone 14 2 SetMarkerPath 14 0 105 SetMarkerPath 14 1 67 SetMarkerPath 14 2 55 SetGoal 15 23 SetZone 15 2 SetMarkerPath 15 0 25 SetGoal 16 12 SetZone 16 10 SetMarkerPath 16 0 17 SetMarkerPath 16 1 56 SetMarkerPath 16 2 59 SetGoal 17 12 SetZone 17 10 SetMarkerPath 17 0 56 SetMarkerPath 17 1 59 SetMarkerPath 17 2 16 SetGoal 18 24 SetZone 18 8 SetMarkerPath 18 0 88 SetMarkerPath 18 1 28 SetMarkerPath 18 2 86 SetGoal 19 24 SetZone 19 7 SetMarkerPath 19 0 117 SetMarkerPath 19 1 118 SetGoal 20 10 SetZone 20 7 SetMarkerPath 20 0 26 SetMarkerPath 20 1 88 SetMarkerPath 20 2 108 SetMarkerPath 20 3 87 SetMarkerPath 20 4 113 SetGoal 21 16 SetZone 21 6 SetMarkerPath 21 0 73 SetMarkerPath 21 1 81 SetMarkerPath 21 2 49 SetZone 22 7 SetMarkerPath 22 0 1 SetGoal 23 11 SetZone 23 9 SetMarkerPath 23 0 41 SetMarkerPath 23 1 97 SetMarkerPath 23 2 104 SetMarkerPath 23 3 29 SetGoal 24 24 SetZone 24 9 SetMarkerPath 24 0 27 SetMarkerPath 24 1 96 SetMarkerPath 24 2 43 SetMarkerPath 24 3 32 SetGoal 25 23 SetZone 25 2 SetMarkerPath 25 0 15 SetMarkerPath 25 1 67 SetMarkerPath 25 2 67 SetMarkerPath 25 3 39 SetMarkerPath 25 4 127 SetGoal 26 10 SetZone 26 7 SetMarkerPath 26 0 20 SetMarkerPath 26 1 1 SetMarkerPath 26 2 118 SetMarkerPath 26 3 113 SetMarkerPath 26 4 117 SetMarkerPath 26 5 123 SetGoal 27 24 SetZone 27 9 SetMarkerPath 27 0 24 SetMarkerPath 27 1 32 SetMarkerPath 27 2 43 SetMarkerPath 27 3 96 SetGoal 28 24 SetZone 28 8 SetMarkerPath 28 0 18 SetMarkerPath 28 1 89 SetMarkerPath 28 2 86 SetGoal 29 11 SetZone 29 9 SetMarkerPath 29 0 23 SetMarkerPath 29 1 98 SetMarkerPath 29 2 41 SetMarkerPath 29 3 115 SetMarkerPath 29 4 97 SetMarkerPath 29 5 112 SetMarkerPathFlags 29 5 6 SetZone 30 5 SetMarkerPath 30 0 76 SetZone 31 11 SetMarkerPath 31 0 99 SetMarkerPath 31 1 100 SetGoal 32 22 SetZone 32 9 SetMarkerPath 32 0 103 SetMarkerPath 32 1 104 SetMarkerPath 32 2 54 SetMarkerPath 32 3 102 SetGoal 33 7 SetZone 33 5 SetMarkerPath 33 0 71 SetMarkerPath 33 1 70 SetMarkerPath 33 2 72 SetMarkerPath 33 3 23 SetMarkerPath 33 4 109 SetMarkerPath 33 5 128 SetMarkerPath 33 6 43 SetMarkerPath 33 7 97 SetGoal 34 20 SetZone 34 6 SetMarkerPath 34 0 40 SetMarkerPath 34 1 4 SetMarkerPath 34 2 83 SetGoal 35 3 SetZone 35 12 SetMarkerPath 35 0 12 SetMarkerPath 35 1 58 SetMarkerPath 35 2 95 SetMarkerPath 35 3 3 SetMarkerPath 35 4 94 SetGoal 36 21 SetZone 36 3 SetMarkerPath 36 0 60 SetMarkerPath 36 1 39 SetMarkerPath 36 2 61 SetGoal 37 24 SetZone 37 4 SetMarkerPath 37 0 69 SetMarkerPath 37 1 78 SetMarkerPath 37 2 125 SetGoal 38 8 SetZone 38 7 SetMarkerPath 38 0 123 SetMarkerPath 38 1 114 SetMarkerPath 38 2 87 SetMarkerPath 38 3 1 SetMarkerPath 38 4 85 SetMarkerPath 38 5 101 SetMarkerPathFlags 38 5 r SetRocketJumpPathFields 38 5 78.3 -1.0 0 SetMarkerPath 38 6 83 SetMarkerPathFlags 38 6 r SetRocketJumpPathFields 38 6 78.3 -1.0 0 SetGoal 39 2 SetZone 39 3 SetMarkerPath 39 0 119 SetMarkerPath 39 1 64 SetMarkerPath 39 2 61 SetMarkerPath 39 3 62 SetMarkerPath 39 4 51 SetMarkerPathFlags 39 4 r SetRocketJumpPathFields 39 4 78.3 -1.0 0 SetMarkerPath 39 5 126 SetMarkerPathFlags 39 5 r SetRocketJumpPathFields 39 5 78.3 -1.0 0 SetMarkerPath 39 6 110 SetMarkerPathFlags 39 6 r SetRocketJumpPathFields 39 6 78.3 -1.0 0 SetGoal 40 9 SetZone 40 7 SetMarkerPath 40 0 87 SetMarkerPath 40 1 106 SetMarkerPath 40 2 101 SetMarkerPathFlags 40 2 r SetRocketJumpPathFields 40 2 72.0 215.0 0 SetZone 41 9 SetMarkerPath 41 0 98 SetMarkerPathFlags 41 0 j SetMarkerPath 41 1 29 SetMarkerPathFlags 41 1 j SetMarkerPath 41 2 121 SetMarkerPathFlags 41 2 j SetMarkerPath 41 3 96 SetMarkerPathFlags 41 3 j SetMarkerPath 41 4 109 SetMarkerPathFlags 41 4 j SetMarkerPath 41 5 112 SetMarkerPathFlags 41 5 6 SetMarkerFlag 41 6 SetZone 42 9 SetMarkerPath 42 0 43 SetZone 43 9 SetMarkerPath 43 0 22 SetMarkerPath 43 1 54 SetMarkerPath 43 2 96 SetMarkerPath 43 3 97 SetGoal 44 5 SetZone 44 1 SetMarkerPath 44 0 46 SetMarkerPath 44 1 112 SetGoal 45 19 SetZone 45 1 SetMarkerPath 45 0 46 SetMarkerPath 45 1 47 SetGoal 46 19 SetZone 46 1 SetMarkerPath 46 0 44 SetMarkerPath 46 1 45 SetGoal 47 6 SetZone 47 1 SetMarkerPath 47 0 42 SetMarkerPath 47 1 45 SetGoal 48 19 SetZone 48 6 SetMarkerPath 48 0 49 SetMarkerPath 48 1 83 SetMarkerPath 48 2 82 SetMarkerPath 48 3 81 SetMarkerPath 48 4 80 SetGoal 49 19 SetZone 49 6 SetMarkerPath 49 0 48 SetMarkerPath 49 1 81 SetMarkerPath 49 2 80 SetMarkerPath 49 3 82 SetGoal 51 1 SetZone 51 11 SetMarkerPath 51 0 110 SetMarkerPath 51 1 68 SetMarkerPath 51 2 39 SetZone 52 12 SetMarkerFlag 52 u SetMarkerPath 52 0 95 SetZone 53 13 SetMarkerPath 53 0 102 SetMarkerPath 53 1 66 SetMarkerPath 53 2 13 SetZone 54 9 SetMarkerPath 54 0 96 SetMarkerPath 54 1 97 SetMarkerPath 54 2 43 SetMarkerPath 54 3 103 SetMarkerPath 54 4 104 SetMarkerPath 54 5 32 SetZone 55 2 SetMarkerPath 55 0 64 SetMarkerPath 55 1 39 SetMarkerPath 55 2 119 SetMarkerPath 55 3 105 SetZone 56 10 SetMarkerPath 56 0 16 SetMarkerPath 56 1 60 SetMarkerPath 56 2 59 SetMarkerPath 56 3 17 SetMarkerPath 56 4 6 SetZone 57 12 SetMarkerPath 57 0 122 SetMarkerPath 57 1 23 SetMarkerPath 57 2 121 SetMarkerPath 57 3 109 SetMarkerPath 57 4 41 SetZone 58 12 SetMarkerPath 58 0 35 SetMarkerPath 58 1 94 SetMarkerPath 58 2 12 SetMarkerPath 58 3 3 SetMarkerPath 58 4 120 SetMarkerPath 58 5 95 SetZone 59 10 SetMarkerPath 59 0 17 SetMarkerPath 59 1 56 SetMarkerPath 59 2 97 SetZone 60 3 SetMarkerPath 60 0 56 SetMarkerPath 60 1 119 SetZone 61 3 SetMarkerPath 61 0 39 SetMarkerPath 61 1 62 SetMarkerPath 61 2 64 SetMarkerPath 61 3 60 SetZone 62 3 SetMarkerPath 62 0 61 SetMarkerPath 62 1 63 SetMarkerPath 62 2 64 SetMarkerPath 62 3 39 SetZone 63 3 SetMarkerPath 63 0 62 SetMarkerPath 63 1 64 SetMarkerPath 63 2 65 SetMarkerPath 63 3 39 SetZone 64 3 SetMarkerPath 64 0 65 SetMarkerPath 64 1 55 SetMarkerPath 64 2 39 SetMarkerPath 64 3 63 SetMarkerPath 64 4 62 SetMarkerPath 64 5 61 SetMarkerPath 64 6 68 SetMarkerPathFlags 64 6 r SetRocketJumpPathFields 64 6 78.3 -1.0 0 SetMarkerPath 64 7 127 SetMarkerPathFlags 64 7 r SetRocketJumpPathFields 64 7 78.3 -1.0 0 SetZone 65 3 SetMarkerPath 65 0 64 SetMarkerPath 65 1 13 SetMarkerPath 65 2 66 SetMarkerPath 65 3 63 SetMarkerPath 65 4 111 SetZone 66 13 SetMarkerPath 66 0 65 SetMarkerPath 66 1 102 SetMarkerPath 66 2 13 SetMarkerPath 66 3 111 SetZone 67 2 SetMarkerPath 67 0 127 SetMarkerPath 67 1 105 SetMarkerPath 67 2 39 SetMarkerPath 67 3 15 SetMarkerPath 67 4 55 SetMarkerPath 67 5 25 SetZone 68 11 SetMarkerPath 68 0 51 SetMarkerPath 68 1 127 SetMarkerPath 68 2 100 SetMarkerPath 68 3 64 SetMarkerPath 68 4 39 SetMarkerPath 68 5 55 SetZone 69 11 SetMarkerPath 69 0 78 SetMarkerPath 69 1 126 SetMarkerPath 69 2 64 SetMarkerPath 69 3 111 SetZone 70 4 SetMarkerPath 70 0 33 SetMarkerPath 70 1 71 SetMarkerPath 70 2 72 SetMarkerPath 70 3 125 SetZone 71 5 SetMarkerPath 71 0 70 SetMarkerPath 71 1 33 SetMarkerPath 71 2 11 SetMarkerPath 71 3 96 SetMarkerPath 71 4 128 SetMarkerPath 71 5 54 SetMarkerPath 71 6 43 SetZone 72 5 SetMarkerPath 72 0 77 SetMarkerPath 72 1 33 SetMarkerPath 72 2 70 SetMarkerPath 72 3 97 SetMarkerPath 72 4 128 SetMarkerPath 72 5 43 SetZone 73 5 SetMarkerPath 73 0 21 SetMarkerPath 73 1 74 SetMarkerPath 73 2 79 SetMarkerPath 73 3 80 SetMarkerPath 73 4 128 SetMarkerPath 73 5 98 SetZone 74 5 SetMarkerPath 74 0 73 SetMarkerPath 74 1 75 SetMarkerPath 74 2 79 SetMarkerPath 74 3 97 SetMarkerPath 74 4 128 SetZone 75 5 SetMarkerPath 75 0 74 SetMarkerPath 75 1 72 SetMarkerPath 75 2 77 SetMarkerPath 75 3 104 SetZone 76 5 SetMarkerPath 76 0 77 SetMarkerPath 76 1 30 SetZone 77 5 SetMarkerPath 77 0 75 SetMarkerPath 77 1 72 SetMarkerPath 77 2 76 SetMarkerPath 77 3 29 SetMarkerPath 77 4 104 SetMarkerPath 77 5 116 SetMarkerPath 77 6 128 SetZone 78 4 SetMarkerPath 78 0 37 SetMarkerPath 78 1 125 SetMarkerPath 78 2 69 SetMarkerPath 78 3 111 SetZone 79 5 SetMarkerPath 79 0 73 SetMarkerPath 79 1 74 SetMarkerPath 79 2 10 SetMarkerPath 79 3 96 SetMarkerPath 79 4 11 SetMarkerPath 79 5 128 SetZone 80 6 SetMarkerPath 80 0 73 SetMarkerPath 80 1 21 SetMarkerPath 80 2 49 SetMarkerPath 80 3 81 SetMarkerPath 80 4 9 SetZone 81 6 SetMarkerPath 81 0 80 SetMarkerPath 81 1 21 SetMarkerPath 81 2 82 SetMarkerPath 81 3 49 SetMarkerPath 81 4 48 SetZone 82 6 SetMarkerPath 82 0 101 SetMarkerPath 82 1 81 SetMarkerPath 82 2 48 SetMarkerPath 82 3 8 SetZone 83 6 SetMarkerPath 83 0 107 SetMarkerPath 83 1 101 SetMarkerPath 83 2 20 SetMarkerPath 83 3 4 SetMarkerPath 83 4 1 SetZone 84 7 SetMarkerPath 84 0 85 SetMarkerPath 84 1 5 SetZone 85 7 SetMarkerPath 85 0 84 SetMarkerPath 85 1 38 SetMarkerPath 85 2 87 SetMarkerPath 85 3 108 SetZone 86 8 SetMarkerPath 86 0 38 SetMarkerPath 86 1 88 SetMarkerPath 86 2 89 SetMarkerPath 86 3 18 SetMarkerPath 86 4 28 SetZone 87 7 SetMarkerPath 87 0 85 SetMarkerPath 87 1 40 SetMarkerPath 87 2 106 SetMarkerPath 87 3 38 SetMarkerPath 87 4 108 SetMarkerPath 87 5 20 SetZone 88 8 SetMarkerPath 88 0 18 SetMarkerPath 88 1 86 SetMarkerPath 88 2 123 SetZone 89 8 SetMarkerPath 89 0 86 SetMarkerPath 89 1 90 SetMarkerPath 89 2 28 SetZone 90 8 SetMarkerPath 90 0 89 SetMarkerPath 90 1 96 SetZone 91 12 SetMarkerPath 91 0 92 SetMarkerPath 91 1 93 SetMarkerPath 91 2 2 SetZone 92 12 SetMarkerPath 92 0 94 SetMarkerPath 92 1 91 SetZone 93 12 SetMarkerPath 93 0 91 SetMarkerPath 93 1 95 SetZone 94 12 SetMarkerPath 94 0 35 SetMarkerPath 94 1 92 SetMarkerPath 94 2 3 SetMarkerPath 94 3 58 SetZone 95 12 SetMarkerPath 95 0 93 SetMarkerPath 95 1 3 SetMarkerPath 95 2 35 SetMarkerPath 95 3 58 SetZone 96 9 SetMarkerPath 96 0 90 SetMarkerPath 96 1 98 SetMarkerPath 96 2 54 SetMarkerPath 96 3 103 SetMarkerPath 96 4 109 SetMarkerPath 96 5 116 SetZone 97 9 SetMarkerPath 97 0 59 SetMarkerPath 97 1 29 SetMarkerPath 97 2 54 SetMarkerPath 97 3 104 SetMarkerPath 97 4 23 SetMarkerPath 97 5 115 SetZone 98 9 SetMarkerPath 98 0 41 SetMarkerPath 98 1 29 SetMarkerPath 98 2 109 SetMarkerPath 98 3 22 SetMarkerPath 98 4 112 SetMarkerPathFlags 98 4 6 SetZone 99 11 SetMarkerPath 99 0 110 SetMarkerPath 99 1 31 SetZone 100 11 SetMarkerPath 100 0 68 SetMarkerPath 100 1 31 SetZone 101 6 SetMarkerPath 101 0 82 SetMarkerPath 101 1 83 SetMarkerPath 101 2 85 SetMarkerPath 101 3 38 SetMarkerPath 101 4 1 SetMarkerPath 101 5 114 SetZone 102 9 SetMarkerPath 102 0 53 SetMarkerPath 102 1 103 SetMarkerPath 102 2 104 SetMarkerPath 102 3 32 SetMarkerPath 102 4 27 SetZone 103 9 SetMarkerPath 103 0 102 SetMarkerPath 103 1 96 SetMarkerPath 103 2 54 SetMarkerPath 103 3 24 SetMarkerPath 103 4 32 SetMarkerPath 103 5 116 SetZone 104 9 SetMarkerPath 104 0 32 SetMarkerPath 104 1 102 SetMarkerPath 104 2 97 SetMarkerPath 104 3 54 SetMarkerPath 104 4 115 SetZone 105 2 SetMarkerPath 105 0 67 SetMarkerPath 105 1 55 SetMarkerPath 105 2 14 SetMarkerPath 105 3 39 SetZone 106 7 SetMarkerPath 106 0 40 SetMarkerPath 106 1 87 SetMarkerPath 106 2 107 SetMarkerPath 106 3 108 SetZone 107 6 SetMarkerPath 107 0 106 SetMarkerPath 107 1 34 SetMarkerPath 107 2 83 SetMarkerPath 107 3 20 SetMarkerPath 107 4 1 SetMarkerPath 107 5 113 SetZone 108 7 SetMarkerPath 108 0 38 SetMarkerPath 108 1 20 SetMarkerPath 108 2 87 SetMarkerPath 108 3 4 SetMarkerPath 108 4 85 SetZone 109 9 SetMarkerPath 109 0 41 SetMarkerPath 109 1 98 SetMarkerPath 109 2 96 SetMarkerPath 109 3 116 SetMarkerPath 109 4 112 SetMarkerPathFlags 109 4 6 SetZone 110 11 SetMarkerPath 110 0 51 SetMarkerPath 110 1 126 SetMarkerPath 110 2 55 SetMarkerPath 110 3 39 SetMarkerPath 110 4 99 SetMarkerPath 110 5 64 SetZone 111 3 SetMarkerPath 111 0 66 SetMarkerPath 111 1 65 SetMarkerPath 111 2 110 SetMarkerPathFlags 111 2 r SetRocketJumpPathFields 111 2 55.0 315.0 0 SetZone 112 1 SetMarkerPath 112 0 44 SetZone 113 7 SetMarkerPath 113 0 20 SetMarkerPath 113 1 26 SetMarkerPath 113 2 1 SetMarkerPath 113 3 108 SetMarkerPath 113 4 87 SetZone 114 7 SetMarkerPath 114 0 38 SetMarkerPath 114 1 108 SetMarkerPath 114 2 1 SetMarkerPath 114 3 87 SetMarkerPath 114 4 88 SetMarkerPath 114 5 85 SetZone 115 9 SetMarkerPath 115 0 98 SetMarkerPath 115 1 29 SetMarkerPath 115 2 43 SetMarkerPath 115 3 104 SetMarkerPath 115 4 97 SetZone 116 9 SetMarkerPath 116 0 96 SetMarkerPath 116 1 109 SetMarkerPath 116 2 43 SetMarkerPath 116 3 98 SetMarkerPath 116 4 103 SetZone 117 7 SetMarkerPath 117 0 26 SetMarkerPath 117 1 88 SetZone 118 7 SetMarkerPath 118 0 19 SetMarkerPath 118 1 26 SetZone 119 3 SetMarkerPath 119 0 60 SetMarkerPath 119 1 61 SetMarkerPath 119 2 39 SetMarkerPath 119 3 36 SetZone 120 12 SetMarkerPath 120 0 122 SetMarkerPath 120 1 58 SetZone 121 9 SetMarkerPath 121 0 57 SetMarkerPathFlags 121 0 j SetMarkerPath 121 1 41 SetMarkerPath 121 2 23 SetMarkerPath 121 3 112 SetMarkerPathFlags 121 3 6 SetZone 122 12 SetMarkerPath 122 0 57 SetMarkerPath 122 1 120 SetZone 123 7 SetMarkerPath 123 0 1 SetMarkerPath 123 1 38 SetMarkerPath 123 2 114 SetMarkerPath 123 3 88 SetMarkerPath 123 4 26 SetZone 124 12 SetMarkerFlag 124 u SetMarkerPath 124 0 94 SetZone 125 4 SetMarkerPath 125 0 70 SetMarkerPath 125 1 78 SetZone 126 11 SetMarkerPath 126 0 69 SetMarkerPath 126 1 110 SetMarkerPath 126 2 39 SetMarkerPath 126 3 55 SetMarkerPath 126 4 111 SetMarkerPath 126 5 64 SetZone 127 11 SetMarkerPath 127 0 64 SetMarkerPath 127 1 39 SetMarkerPath 127 2 119 SetMarkerPath 127 3 55 SetMarkerPath 127 4 68 SetMarkerPath 127 5 67 SetZone 128 14 SetMarkerPath 128 0 43 SetMarkerPath 128 1 98 SetMarkerPath 128 2 32 SetMarkerPath 128 3 96 SetMarkerPath 128 4 97 SetMarkerPath 128 5 54 SetMarkerPath 128 6 29 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dmm4_1.bot000066400000000000000000000051441475442401000260330ustar00rootroot00000000000000CreateMarker 1057 170 152 CreateMarker 614 191 104 CreateMarker 703 421 104 CreateMarker 941 564 104 CreateMarker 1194 536 104 CreateMarker 1387 382 104 CreateMarker 1447 113 104 CreateMarker 1345 -132 104 CreateMarker 1118 -247 104 CreateMarker 881 -228 104 CreateMarker 682 -52 104 CreateMarker 791 205 152 CreateMarker 814 38 152 CreateMarker 948 -64 152 CreateMarker 1100 -84 152 CreateMarker 1219 -25 152 CreateMarker 1285 147 152 CreateMarker 1271 290 152 CreateMarker 1157 404 152 CreateMarker 976 421 152 CreateMarker 844 341 152 CreateMarker 997 256 152 CreateMarker 959 89 152 CreateMarker 1128 88 152 CreateMarker 1151 252 152 SetZone 1 6 SetMarkerPath 1 1 16 SetZone 2 5 SetMarkerPath 2 1 5 SetZone 3 4 SetMarkerPath 3 1 24 SetZone 4 3 SetMarkerPath 4 1 5 SetZone 5 2 SetMarkerPath 5 1 26 SetMarkerPath 5 2 28 SetMarkerPath 5 3 29 SetMarkerPath 5 4 27 SetZone 6 1 SetMarkerPath 6 1 16 SetZone 7 1 SetMarkerPath 7 1 25 SetZone 8 1 SetMarkerPath 8 1 24 SetZone 9 1 SetMarkerPath 9 1 23 SetZone 10 1 SetMarkerPath 10 1 22 SetZone 11 1 SetMarkerPath 11 1 21 SetZone 12 1 SetMarkerPath 12 1 20 SetZone 13 1 SetMarkerPath 13 1 19 SetZone 14 1 SetMarkerPath 14 1 18 SetZone 15 1 SetMarkerPath 15 1 17 SetZone 16 2 SetMarkerPath 16 1 17 SetMarkerPath 16 2 25 SetMarkerPath 16 3 27 SetMarkerPath 16 4 26 SetZone 17 2 SetMarkerPath 17 1 18 SetMarkerPath 17 2 16 SetMarkerPath 17 3 27 SetZone 18 2 SetMarkerPath 18 1 19 SetMarkerPath 18 2 17 SetMarkerPath 18 3 27 SetZone 19 2 SetMarkerPath 19 1 20 SetMarkerPath 19 2 18 SetMarkerPath 19 3 28 SetZone 20 2 SetMarkerPath 20 1 21 SetMarkerPath 20 2 19 SetMarkerPath 20 3 28 SetZone 21 2 SetMarkerPath 21 1 22 SetMarkerPath 21 2 20 SetMarkerPath 21 3 28 SetMarkerPath 21 4 29 SetZone 22 2 SetMarkerPath 22 1 21 SetMarkerPath 22 2 23 SetMarkerPath 22 3 29 SetZone 23 2 SetMarkerPath 23 1 24 SetMarkerPath 23 2 22 SetMarkerPath 23 3 29 SetMarkerPath 23 4 26 SetZone 24 2 SetMarkerPath 24 1 25 SetMarkerPath 24 2 23 SetMarkerPath 24 3 26 SetZone 25 2 SetMarkerPath 25 1 16 SetMarkerPath 25 2 24 SetMarkerPath 25 3 26 SetZone 26 2 SetMarkerPath 26 1 24 SetMarkerPath 26 2 29 SetMarkerPath 26 3 25 SetMarkerPath 26 4 5 SetMarkerPath 26 5 16 SetMarkerPath 26 6 23 SetMarkerPath 26 7 27 SetZone 27 2 SetMarkerPath 27 1 16 SetMarkerPath 27 2 17 SetMarkerPath 27 3 28 SetMarkerPath 27 4 5 SetMarkerPath 27 5 18 SetMarkerPath 27 6 26 SetZone 28 2 SetMarkerPath 28 1 27 SetMarkerPath 28 2 5 SetMarkerPath 28 3 29 SetMarkerPath 28 4 20 SetMarkerPath 28 5 21 SetMarkerPath 28 6 19 SetZone 29 2 SetMarkerPath 29 1 22 SetMarkerPath 29 2 23 SetMarkerPath 29 3 26 SetMarkerPath 29 4 5 SetMarkerPath 29 5 28 SetMarkerPath 29 6 21 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/dmm4_3.bot000066400000000000000000000044301475442401000260320ustar00rootroot00000000000000CreateMarker 360 100 88 CreateMarker 674 86 88 CreateMarker 501 102 56 CreateMarker 368 545 88 CreateMarker 662 548 88 CreateMarker 513 529 56 CreateMarker 358 396 56 CreateMarker 527 393 56 CreateMarker 669 404 56 CreateMarker 344 229 56 CreateMarker 493 209 56 CreateMarker 666 212 56 CreateMarker 813 314 184 CreateMarker 802 190 152 CreateMarker 811 437 152 CreateMarker 224 440 152 CreateMarker 219 331 184 CreateMarker 219 194 152 SetZone 1 3 SetMarkerPath 1 1 5 SetMarkerPath 1 2 22 SetMarkerPath 1 3 15 SetMarkerPathFlags 1 3 j SetZone 2 3 SetMarkerPath 2 1 20 SetMarkerPath 2 2 8 SetZone 3 2 SetMarkerPath 3 1 18 SetMarkerPath 3 2 6 SetZone 4 2 SetMarkerPath 4 1 9 SetMarkerPath 4 2 19 SetZone 5 3 SetMarkerPath 5 1 15 SetMarkerPath 5 2 7 SetMarkerPath 5 3 1 SetZone 6 2 SetMarkerPath 6 1 15 SetMarkerPathFlags 6 1 j SetMarkerPath 6 2 7 SetMarkerPath 6 3 3 SetZone 7 1 SetMarkerPath 7 1 15 SetMarkerPath 7 2 6 SetMarkerPath 7 3 5 SetZone 8 3 SetMarkerPath 8 1 12 SetMarkerPathFlags 8 1 j SetMarkerPath 8 2 10 SetMarkerPath 8 3 2 SetZone 9 2 SetMarkerPath 9 1 13 SetMarkerPath 9 2 10 SetMarkerPath 9 3 12 SetMarkerPathFlags 9 3 j SetMarkerPath 9 4 4 SetZone 10 1 SetMarkerPath 10 1 12 SetMarkerPath 10 2 9 SetMarkerPath 10 3 8 SetMarkerPath 10 4 11 SetMarkerPath 10 5 13 SetZone 11 1 SetMarkerPath 11 1 12 SetMarkerPath 11 2 14 SetMarkerPath 11 3 10 SetZone 12 1 SetMarkerPath 12 1 10 SetMarkerPath 12 2 13 SetMarkerPath 12 3 9 SetMarkerPath 12 4 8 SetMarkerPath 12 5 11 SetMarkerPath 12 6 15 SetMarkerPath 12 7 16 SetZone 13 1 SetMarkerPath 13 1 12 SetMarkerPath 13 2 10 SetMarkerPath 13 3 16 SetZone 14 1 SetMarkerPath 14 1 11 SetMarkerPath 14 2 15 SetMarkerPath 14 3 12 SetZone 15 1 SetMarkerPath 15 1 6 SetMarkerPath 15 2 5 SetMarkerPath 15 3 14 SetMarkerPath 15 4 12 SetMarkerPath 15 5 16 SetMarkerPath 15 6 7 SetZone 16 1 SetMarkerPath 16 1 12 SetMarkerPath 16 2 13 SetMarkerPath 16 3 15 SetZone 17 2 SetMarkerPath 17 1 19 SetMarkerPath 17 2 18 SetMarkerPath 17 3 12 SetMarkerPath 17 4 15 SetZone 18 2 SetMarkerPath 18 1 17 SetMarkerPath 18 2 3 SetZone 19 2 SetMarkerPath 19 1 4 SetMarkerPath 19 2 17 SetZone 20 3 SetMarkerPath 20 1 21 SetMarkerPath 20 2 2 SetZone 21 3 SetMarkerPath 21 1 22 SetMarkerPath 21 2 20 SetMarkerPath 21 3 12 SetMarkerPath 21 4 15 SetZone 22 3 SetMarkerPath 22 1 1 SetMarkerPath 22 2 21 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/e1m2.bot000066400000000000000000000452741475442401000255260ustar00rootroot00000000000000CreateMarker 434 -76 227 CreateMarker 444 152 92 CreateMarker 428 323 92 CreateMarker 723 328 92 CreateMarker 890 260 89 CreateMarker 972 248 88 CreateMarker 1428 308 88 CreateMarker 1632 316 88 CreateMarker 1750 149 137 CreateMarker 1794 34 168 CreateMarker 1918 363 148 CreateMarker 1987 -99 168 CreateMarker 2015 -369 168 CreateMarker 1752 -372 168 CreateMarker 1402 -468 168 CreateMarker 1550 -413 168 CreateMarker 1190 -488 168 CreateMarker 910 -415 168 CreateMarker 1567 -565 182 CreateMarker 704 588 248 CreateMarker 635 504 264 CreateMarker 416 416 264 CreateMarker 828 993 148 CreateMarker 821 1145 80 CreateMarker 1194 1154 80 CreateMarker 1364 1180 152 CreateMarker 1514 1049 204 CreateMarker 1486 1487 264 CreateMarker 1458 1665 288 CreateMarker 1290 1717 264 CreateMarker 1320 1515 264 CreateMarker 904 710 148 CreateMarker 1064 661 88 CreateMarker 1121 364 88 CreateMarker 1197 257 88 CreateMarker 1410 46 320 CreateMarker 1101 40 308 CreateMarker 1098 228 308 CreateMarker 1106 512 308 CreateMarker 1194 653 312 CreateMarker 1353 654 296 CreateMarker 1484 791 248 CreateMarker 1317 1118 80 CreateMarker 1387 -102 320 CreateMarker 1116 -133 320 CreateMarker 917 -123 320 CreateMarker 1415 398 320 CreateMarker 1760 378 312 CreateMarker 1793 107 312 CreateMarker 1823 -86 312 CreateMarker 1745 -362 312 CreateMarker 1498 -362 312 CreateMarker 1354 -402 312 CreateMarker 2031 -368 312 CreateMarker 1343 -456 340 CreateMarker 2091 -187 312 CreateMarker 1339 -480 372 CreateMarker 1150 -413 312 CreateMarker 1346 -691 312 CreateMarker 1345 -632 340 CreateMarker 1342 -608 372 CreateMarker 1529 -713 328 CreateMarker 1667 -710 360 CreateMarker 1689 -896 408 CreateMarker 1464 -911 440 CreateMarker 1339 -1083 448 CreateMarker 1211 -925 440 CreateMarker 1113 -1030 440 CreateMarker 877 -973 440 CreateMarker 882 -746 440 CreateMarker 883 -491 432 CreateMarker 713 -1220 432 CreateMarker 550 -1117 432 CreateMarker 396 -1208 432 CreateMarker 396 -996 432 CreateMarker 573 -781 432 CreateMarker 578 -656 392 CreateMarker 577 -560 344 CreateMarker 566 -401 320 CreateMarker 406 -399 320 CreateMarker 432 -251 324 CreateMarker 261 -295 320 CreateMarker 655 -128 320 CreateMarker 177 66 320 CreateMarker 7 148 320 CreateMarker -92 37 320 CreateMarker -203 141 320 CreateMarker -372 54 320 CreateMarker -95 -190 320 CreateMarker -90 -320 352 CreateMarker -259 -497 384 CreateMarker -363 -476 448 CreateMarker -478 -669 480 CreateMarker -520 -367 480 CreateMarker -88 431 320 CreateMarker 1556 413 320 CreateMarker 1456 -572 168 CreateMarker 1250 -565 168 CreateMarker 910 -535 168 CreateMarker 2109 -240 168 CreateMarker 1094 265 88 CreateMarker 1052 32 92 CreateMarker 800 115 92 CreateMarker 1197 740 88 CreateMarker 1093 534 88 CreateMarker 585 330 92 CreateMarker -428 312 332 SetGoal 1 19 SetZone 1 2 SetMarkerPath 1 0 2 SetMarkerPath 1 1 167 SetGoal 2 24 SetZone 2 2 SetMarkerPath 2 0 166 SetMarkerPath 2 1 1 SetGoal 3 18 SetZone 3 3 SetMarkerPath 3 0 171 SetMarkerPath 3 1 172 SetGoal 4 18 SetZone 4 3 SetMarkerPath 4 0 171 SetGoal 5 24 SetZone 5 4 SetMarkerPath 5 0 223 SetGoal 6 24 SetZone 6 5 SetMarkerPath 6 0 185 SetMarkerPath 6 1 72 SetMarkerPath 6 2 7 SetGoal 7 17 SetZone 7 5 SetMarkerPath 7 0 72 SetMarkerPath 7 1 6 SetMarkerPath 7 2 186 SetGoal 8 24 SetZone 8 1 SetMarkerPath 8 0 68 SetMarkerPath 8 1 86 SetMarkerPath 8 2 90 SetMarkerPath 8 3 92 SetGoal 9 16 SetZone 9 6 SetMarkerPath 9 0 196 SetMarkerPath 9 1 10 SetGoal 10 16 SetZone 10 6 SetMarkerPath 10 0 194 SetMarkerPath 10 1 9 SetGoal 11 15 SetZone 11 8 SetMarkerPath 11 0 209 SetMarkerPath 11 1 67 SetGoal 12 24 SetZone 12 10 SetMarkerPath 12 0 220 SetGoal 13 14 SetZone 13 10 SetMarkerPath 13 0 217 SetMarkerPath 13 1 14 SetMarkerPath 13 2 87 SetGoal 14 14 SetZone 14 10 SetMarkerPath 14 0 13 SetMarkerPath 14 1 89 SetZone 15 3 SetMarkerPath 15 0 16 SetGoal 16 13 SetZone 16 3 SetMarkerPath 16 0 15 SetMarkerPath 16 1 100 SetMarkerPath 16 2 165 SetMarkerPathFlags 16 2 j SetMarkerPath 16 3 133 SetZone 17 12 SetMarkerPath 17 0 15 SetGoal 18 12 SetZone 18 12 SetMarkerPath 18 0 146 SetMarkerPath 18 1 107 SetMarkerFlag 21 f SetGoal 22 2 SetZone 22 5 SetMarkerPath 22 0 6 SetMarkerPathFlags 22 0 j SetMarkerPath 22 1 189 SetMarkerPathFlags 22 1 j SetMarkerPath 22 2 179 SetMarkerPathFlags 22 2 j SetMarkerPath 22 3 7 SetMarkerPath 22 4 224 SetMarkerPath 22 5 225 SetMarkerPath 25 0 26 SetMarkerPath 27 0 28 SetMarkerFlag 29 f SetMarkerFlag 31 f SetMarkerFlag 36 f SetZone 41 9 SetMarkerPath 41 0 57 SetZone 42 9 SetMarkerPath 42 0 113 SetZone 43 9 SetMarkerPath 43 0 116 SetMarkerPath 43 1 42 SetZone 44 9 SetMarkerViewOfs 44 185 SetMarkerPath 44 0 214 SetMarkerPath 44 1 41 SetMarkerFlag 51 f SetGoal 52 11 SetZone 52 7 SetMarkerPath 52 0 53 SetMarkerPath 52 1 73 SetGoal 53 11 SetZone 53 7 SetMarkerPath 53 0 54 SetMarkerPath 53 1 52 SetMarkerPath 53 2 73 SetGoal 54 11 SetZone 54 7 SetMarkerPath 54 0 202 SetMarkerPath 54 1 53 SetMarkerPath 54 2 73 SetMarkerPath 54 3 203 SetGoal 56 10 SetZone 56 9 SetMarkerPath 56 0 57 SetMarkerPath 56 1 88 SetGoal 57 10 SetZone 57 9 SetMarkerPath 57 0 41 SetMarkerPath 57 1 56 SetMarkerPath 57 2 61 SetGoal 58 24 SetZone 58 8 SetMarkerPath 58 0 210 SetGoal 59 24 SetZone 59 9 SetMarkerPath 59 0 66 SetGoal 60 9 SetZone 60 9 SetMarkerPath 60 0 61 SetMarkerPath 60 1 211 SetMarkerPath 60 2 57 SetMarkerPathFlags 60 2 r SetRocketJumpPathFields 60 2 68.0 345.0 0 SetGoal 61 9 SetZone 61 9 SetMarkerPath 61 0 209 SetMarkerPath 61 1 60 SetGoal 62 8 SetZone 62 1 SetMarkerPath 62 0 63 SetMarkerPath 62 1 158 SetGoal 63 8 SetZone 63 1 SetMarkerPath 63 0 157 SetMarkerPath 63 1 62 SetGoal 64 7 SetZone 64 13 SetMarkerPath 64 0 65 SetGoal 65 7 SetZone 65 13 SetMarkerPath 65 0 64 SetMarkerPath 65 1 147 SetZone 66 9 SetMarkerPath 66 0 215 SetMarkerPath 66 1 59 SetZone 67 8 SetMarkerPath 67 0 11 SetMarkerPath 67 1 207 SetZone 68 1 SetMarkerPath 68 0 86 SetMarkerPath 68 1 8 SetMarkerPath 68 2 155 SetZone 69 4 SetMarkerPath 69 0 177 SetMarkerPath 69 1 93 SetMarkerPath 69 2 183 SetZone 70 7 SetMarkerPath 70 0 196 SetMarkerPath 70 1 199 SetZone 71 6 SetMarkerPath 71 0 196 SetZone 72 5 SetMarkerPath 72 0 6 SetMarkerPath 72 1 7 SetZone 73 7 SetMarkerPath 73 0 203 SetMarkerPath 73 1 52 SetMarkerPath 73 2 53 SetMarkerPath 73 3 54 SetZone 74 3 SetMarkerPath 74 0 173 SetMarkerPath 74 1 210 SetZone 75 13 SetMarkerPath 75 0 150 SetMarkerPath 75 1 78 SetMarkerPath 75 2 85 SetZone 76 24 SetZone 77 24 SetGoal 78 24 SetZone 78 13 SetMarkerPath 78 0 75 SetMarkerPath 78 1 85 SetGoal 79 21 SetZone 79 3 SetMarkerPath 79 0 112 SetMarkerPath 79 1 163 SetMarkerPath 79 2 174 SetMarkerPath 79 3 165 SetMarkerPath 79 4 162 SetGoal 80 24 SetZone 80 7 SetMarkerPath 80 0 199 SetMarkerPath 80 1 200 SetGoal 85 1 SetZone 85 13 SetMarkerPath 85 0 78 SetMarkerPath 85 1 75 SetMarkerPath 85 2 147 SetMarkerPath 85 3 159 SetGoal 86 22 SetZone 86 1 SetMarkerPath 86 0 68 SetMarkerPath 86 1 154 SetMarkerPath 86 2 153 SetMarkerPath 86 3 8 SetGoal 87 20 SetZone 87 10 SetMarkerPath 87 0 217 SetMarkerPath 87 1 13 SetMarkerPath 87 2 89 SetMarkerPath 87 3 218 SetGoal 88 3 SetZone 88 9 SetMarkerPath 88 0 56 SetMarkerPath 88 1 109 SetMarkerPath 88 2 212 SetMarkerPathFlags 88 2 j SetMarkerPath 88 3 214 SetMarkerPathFlags 88 3 j SetGoal 89 23 SetZone 89 10 SetMarkerPath 89 0 87 SetMarkerPath 89 1 14 SetMarkerPath 89 2 218 SetGoal 90 23 SetZone 90 1 SetMarkerPath 90 0 8 SetMarkerPath 90 1 91 SetGoal 91 23 SetZone 91 1 SetMarkerPath 91 0 90 SetMarkerPath 91 1 92 SetGoal 92 23 SetZone 92 1 SetMarkerPath 92 0 91 SetMarkerPath 92 1 8 SetGoal 93 6 SetZone 93 4 SetMarkerPath 93 0 69 SetMarkerPath 93 1 177 SetMarkerPath 93 2 183 SetGoal 94 5 SetZone 94 6 SetMarkerPath 94 0 108 SetMarkerPath 94 1 120 SetMarkerPath 94 2 195 SetMarkerFlag 95 f SetGoal 100 4 SetZone 100 3 SetMarkerPath 100 0 16 SetMarkerPath 100 1 164 SetMarkerPath 100 2 133 SetZone 101 11 SetMarkerPath 101 0 163 SetMarkerPath 101 1 164 SetMarkerPath 101 2 162 SetMarkerFlag 105 f SetGoal 106 23 SetZone 106 13 SetMarkerPath 106 0 170 SetGoal 107 12 SetZone 107 12 SetMarkerPath 107 0 18 SetMarkerPath 107 1 17 SetGoal 108 23 SetZone 108 6 SetMarkerPath 108 0 120 SetMarkerPath 108 1 94 SetGoal 109 17 SetZone 109 9 SetMarkerPath 109 0 88 SetMarkerPath 109 1 113 SetGoal 112 24 SetZone 112 3 SetMarkerPath 112 0 79 SetMarkerPath 112 1 163 SetGoal 113 23 SetZone 113 9 SetMarkerPath 113 0 109 SetMarkerPath 113 1 42 SetMarkerPath 114 0 117 SetMarkerPath 115 0 116 SetZone 116 9 SetMarkerPath 116 0 212 SetMarkerPath 116 1 43 SetMarkerPath 116 2 211 SetMarkerPath 116 3 222 SetZone 117 9 SetMarkerPath 117 0 234 SetMarkerPath 117 1 214 SetMarkerPath 117 2 215 SetMarkerPath 117 3 222 SetMarkerFlag 118 f SetGoal 119 24 SetZone 119 6 SetMarkerPath 119 0 197 SetMarkerPath 119 1 196 SetGoal 120 1 SetZone 120 6 SetMarkerPath 120 0 193 SetMarkerPath 120 1 108 SetMarkerPath 120 2 94 SetMarkerPath 120 3 195 SetGoal 121 19 SetZone 121 6 SetMarkerPath 121 0 198 SetMarkerPath 121 1 145 SetMarkerFlag 123 f SetGoal 126 20 SetZone 126 7 SetMarkerPath 126 0 201 SetGoal 127 20 SetZone 127 14 SetMarkerPath 127 0 145 SetMarkerPathFlags 127 0 j SetZone 128 11 SetMarkerPath 128 0 208 SetMarkerPath 128 1 129 SetZone 129 11 SetMarkerPath 129 0 128 SetMarkerPath 129 1 130 SetZone 130 11 SetMarkerPath 130 0 129 SetMarkerPath 130 1 233 SetZone 131 11 SetMarkerPath 131 0 132 SetMarkerPath 131 1 233 SetZone 132 11 SetMarkerPath 132 0 133 SetMarkerPath 132 1 131 SetMarkerPath 132 2 230 SetZone 133 11 SetMarkerPath 133 0 132 SetMarkerPath 133 1 161 SetMarkerPath 133 2 162 SetZone 134 11 SetMarkerPath 134 0 162 SetMarkerPath 134 1 135 SetZone 135 11 SetMarkerPath 135 0 134 SetMarkerPath 135 1 136 SetMarkerPath 135 2 138 SetZone 136 11 SetMarkerPath 136 0 135 SetMarkerPath 136 1 137 SetZone 137 11 SetMarkerPath 137 0 136 SetMarkerPath 137 1 139 SetZone 138 11 SetMarkerPath 138 0 135 SetZone 139 12 SetMarkerPath 139 0 137 SetMarkerPath 139 1 140 SetMarkerPath 139 2 227 SetZone 140 12 SetMarkerPath 140 0 139 SetMarkerPath 140 1 141 SetMarkerPath 140 2 227 SetZone 141 12 SetMarkerPath 141 0 140 SetMarkerPath 141 1 143 SetZone 142 12 SetMarkerPath 142 0 143 SetMarkerPath 142 1 146 SetMarkerPath 142 2 144 SetZone 143 12 SetMarkerPath 143 0 141 SetMarkerPath 143 1 142 SetZone 144 12 SetMarkerPath 144 0 142 SetMarkerPath 144 1 145 SetMarkerPath 144 2 225 SetZone 145 12 SetMarkerPath 145 0 144 SetMarkerPath 145 1 226 SetZone 146 12 SetMarkerPath 146 0 142 SetMarkerPath 146 1 18 SetMarkerPath 146 2 224 SetZone 147 13 SetMarkerPath 147 0 85 SetMarkerPath 147 1 65 SetMarkerPath 147 2 148 SetZone 148 13 SetMarkerPath 148 0 147 SetMarkerPath 148 1 149 SetZone 149 13 SetMarkerPath 149 0 148 SetMarkerPath 149 1 129 SetMarkerPath 149 2 233 SetZone 150 13 SetMarkerPath 150 0 151 SetMarkerPath 150 1 75 SetZone 151 13 SetMarkerPath 151 0 152 SetMarkerPath 151 1 150 SetZone 152 13 SetMarkerPath 152 0 153 SetMarkerPath 152 1 151 SetMarkerPath 152 2 170 SetZone 153 13 SetMarkerPath 153 0 154 SetMarkerPath 153 1 86 SetMarkerPath 153 2 152 SetMarkerPath 153 3 170 SetZone 154 1 SetMarkerPath 154 0 86 SetMarkerPath 154 1 153 SetMarkerPath 154 2 169 SetZone 155 1 SetMarkerPath 155 0 68 SetMarkerPath 155 1 156 SetMarkerPath 155 2 158 SetZone 156 1 SetMarkerPath 156 0 155 SetMarkerPath 156 1 157 SetZone 157 1 SetMarkerPath 157 0 156 SetMarkerPath 157 1 63 SetZone 158 1 SetMarkerPath 158 0 62 SetMarkerPath 158 1 155 SetZone 159 13 SetMarkerPath 159 0 75 SetMarkerPath 159 1 85 SetMarkerPath 159 2 160 SetMarkerPath 159 3 232 SetZone 160 11 SetMarkerPath 160 0 161 SetMarkerPath 160 1 159 SetMarkerPath 160 2 231 SetZone 161 11 SetMarkerPath 161 0 160 SetMarkerPath 161 1 162 SetMarkerPath 161 2 133 SetMarkerPath 161 3 228 SetMarkerPath 161 4 232 SetZone 162 11 SetMarkerPath 162 0 161 SetMarkerPath 162 1 101 SetMarkerPathFlags 162 1 v SetMarkerPath 162 2 134 SetMarkerPath 162 3 133 SetMarkerPath 162 4 228 SetZone 163 3 SetMarkerPath 163 0 112 SetMarkerPath 163 1 79 SetMarkerPath 163 2 171 SetZone 164 2 SetMarkerPath 164 0 165 SetMarkerPath 164 1 172 SetMarkerPath 164 2 100 SetZone 165 2 SetMarkerPath 165 0 164 SetMarkerPath 165 1 166 SetMarkerPath 165 2 16 SetMarkerPathFlags 165 2 j SetMarkerPath 165 3 79 SetMarkerPathFlags 165 3 j SetMarkerPath 165 4 132 SetZone 166 2 SetMarkerPath 166 0 165 SetMarkerPath 166 1 2 SetMarkerPath 166 2 167 SetZone 167 2 SetMarkerPath 167 0 1 SetMarkerPath 167 1 166 SetMarkerPath 167 2 168 SetZone 168 2 SetMarkerPath 168 0 167 SetMarkerPath 168 1 169 SetZone 169 2 SetMarkerPath 169 0 168 SetMarkerPath 169 1 154 SetZone 170 13 SetMarkerPath 170 0 152 SetMarkerPath 170 1 153 SetMarkerPath 170 2 106 SetZone 171 3 SetMarkerPath 171 0 163 SetMarkerPath 171 1 4 SetMarkerPath 171 2 3 SetMarkerPath 171 3 172 SetZone 172 3 SetMarkerPath 172 0 164 SetMarkerPath 172 1 3 SetMarkerPath 172 2 171 SetMarkerPath 172 3 173 SetZone 173 3 SetMarkerPath 173 0 172 SetMarkerPath 173 1 74 SetZone 174 3 SetMarkerPath 174 0 79 SetMarkerPath 174 1 223 SetMarkerPath 174 2 162 SetZone 175 4 SetMarkerPath 175 0 223 SetMarkerPath 175 1 176 SetZone 176 4 SetMarkerPath 176 0 175 SetMarkerPath 176 1 177 SetZone 177 4 SetMarkerPath 177 0 176 SetMarkerPath 177 1 69 SetMarkerPath 177 2 93 SetZone 178 4 SetMarkerPath 178 0 181 SetMarkerPath 178 1 179 SetZone 179 4 SetMarkerPath 179 0 178 SetMarkerPath 179 1 180 SetMarkerPath 179 2 224 SetZone 180 5 SetMarkerPath 180 0 179 SetMarkerPath 180 1 182 SetMarkerPathFlags 180 1 j SetMarkerPath 180 2 185 SetMarkerPath 180 3 224 SetZone 181 4 SetMarkerPath 181 0 183 SetMarkerPath 181 1 178 SetZone 182 5 SetMarkerPath 182 0 184 SetMarkerPathFlags 182 0 j SetMarkerPath 182 1 179 SetMarkerPath 182 2 185 SetMarkerPath 182 3 224 SetZone 183 4 SetMarkerPath 183 0 93 SetMarkerPath 183 1 69 SetMarkerPath 183 2 181 SetZone 184 5 SetMarkerPath 184 0 22 SetMarkerPathFlags 184 0 j SetMarkerPath 184 1 179 SetMarkerPath 184 2 185 SetMarkerPath 184 3 224 SetZone 185 5 SetMarkerPath 185 0 6 SetMarkerPath 185 1 180 SetZone 186 5 SetMarkerPath 186 0 7 SetMarkerPath 186 1 187 SetMarkerPathFlags 186 1 j SetMarkerPath 186 2 189 SetMarkerPath 186 3 224 SetZone 187 5 SetMarkerPath 187 0 188 SetMarkerPathFlags 187 0 j SetMarkerPath 187 1 189 SetMarkerPath 187 2 7 SetMarkerPath 187 3 224 SetZone 188 5 SetMarkerPath 188 0 22 SetMarkerPathFlags 188 0 j SetMarkerPath 188 1 189 SetMarkerPath 188 2 7 SetMarkerPath 188 3 224 SetZone 189 5 SetMarkerPath 189 0 186 SetMarkerPath 189 1 190 SetMarkerPath 189 2 224 SetZone 190 6 SetMarkerPath 190 0 189 SetMarkerPath 190 1 191 SetZone 191 6 SetMarkerPath 191 0 190 SetMarkerPath 191 1 192 SetZone 192 6 SetMarkerPath 192 0 191 SetMarkerPath 192 1 194 SetMarkerPath 192 2 193 SetZone 193 6 SetMarkerPath 193 0 194 SetMarkerPath 193 1 192 SetMarkerPath 193 2 120 SetZone 194 6 SetMarkerPath 194 0 193 SetMarkerPath 194 1 192 SetMarkerPath 194 2 195 SetMarkerPath 194 3 10 SetZone 195 6 SetMarkerPath 195 0 94 SetMarkerPath 195 1 120 SetMarkerPath 195 2 194 SetMarkerPath 195 3 196 SetZone 196 6 SetMarkerPath 196 0 195 SetMarkerPath 196 1 9 SetMarkerPath 196 2 197 SetMarkerPath 196 3 71 SetMarkerPath 196 4 119 SetMarkerPath 196 5 70 SetZone 197 6 SetMarkerPath 197 0 119 SetMarkerPath 197 1 196 SetMarkerPath 197 2 198 SetZone 198 6 SetMarkerPath 198 0 197 SetMarkerPath 198 1 121 SetMarkerPath 198 2 127 SetMarkerPathFlags 198 2 j SetZone 199 7 SetMarkerPath 199 0 70 SetMarkerPath 199 1 80 SetMarkerPath 199 2 200 SetZone 200 7 SetMarkerPath 200 0 80 SetMarkerPath 200 1 199 SetMarkerPath 200 2 201 SetMarkerPath 200 3 202 SetMarkerPath 200 4 203 SetZone 201 7 SetMarkerPath 201 0 200 SetMarkerPath 201 1 126 SetMarkerPath 201 2 202 SetZone 202 7 SetMarkerPath 202 0 201 SetMarkerPath 202 1 200 SetMarkerPath 202 2 203 SetMarkerPath 202 3 54 SetZone 203 7 SetMarkerPath 203 0 200 SetMarkerPath 203 1 73 SetMarkerPath 203 2 202 SetMarkerPath 203 3 54 SetMarkerPath 203 4 204 SetZone 204 7 SetMarkerPath 204 0 203 SetMarkerPath 204 1 205 SetZone 205 7 SetMarkerPath 205 0 204 SetMarkerPath 205 1 206 SetZone 206 8 SetMarkerPath 206 0 205 SetMarkerPath 206 1 207 SetMarkerPath 206 2 210 SetMarkerPath 206 3 208 SetZone 207 8 SetMarkerPath 207 0 206 SetMarkerPath 207 1 208 SetMarkerPath 207 2 67 SetMarkerPath 207 3 209 SetZone 208 8 SetMarkerPath 208 0 207 SetMarkerPath 208 1 206 SetMarkerPath 208 2 128 SetZone 209 8 SetMarkerPath 209 0 11 SetMarkerPath 209 1 207 SetMarkerPath 209 2 61 SetZone 210 8 SetMarkerPath 210 0 58 SetMarkerPath 210 1 206 SetMarkerPath 210 2 74 SetZone 211 9 SetMarkerPath 211 0 60 SetMarkerPath 211 1 212 SetMarkerPath 211 2 43 SetMarkerPath 211 3 88 SetMarkerPathFlags 211 3 r SetRocketJumpPathFields 211 3 65.0 11.0 0 SetMarkerPath 211 4 116 SetZone 212 9 SetMarkerPath 212 0 211 SetMarkerPath 212 1 43 SetMarkerPath 212 2 214 SetMarkerPath 212 3 222 SetMarkerPath 212 4 116 SetMarkerPath 212 5 213 SetZone 213 9 SetMarkerPath 213 0 212 SetMarkerPath 213 1 214 SetMarkerPath 213 2 216 SetMarkerPath 213 3 222 SetZone 214 9 SetMarkerPath 214 0 44 SetMarkerPath 214 1 212 SetMarkerPath 214 2 215 SetMarkerPath 214 3 222 SetMarkerPath 214 4 88 SetMarkerPathFlags 214 4 r SetRocketJumpPathFields 214 4 75.0 119.0 0 SetMarkerPath 214 5 113 SetMarkerPathFlags 214 5 r SetRocketJumpPathFields 214 5 68.0 61.0 0 SetMarkerPath 214 6 213 SetMarkerPath 214 7 117 SetZone 215 9 SetMarkerPath 215 0 66 SetMarkerPath 215 1 214 SetMarkerPath 215 2 117 SetMarkerPath 215 3 234 SetZone 216 9 SetMarkerPath 216 0 213 SetMarkerPath 216 1 217 SetZone 217 9 SetMarkerPath 217 0 216 SetMarkerPath 217 1 87 SetMarkerPath 217 2 13 SetZone 218 10 SetMarkerPath 218 0 87 SetMarkerPath 218 1 89 SetMarkerPath 218 2 219 SetZone 219 10 SetMarkerPath 219 0 218 SetMarkerPath 219 1 220 SetMarkerPath 219 2 221 SetZone 220 10 SetMarkerPath 220 0 219 SetMarkerPath 220 1 12 SetMarkerPath 220 2 221 SetZone 221 10 SetMarkerPath 221 0 219 SetMarkerPath 221 1 220 SetZone 222 9 SetMarkerPath 222 0 214 SetMarkerPath 222 1 212 SetMarkerPath 222 2 116 SetMarkerPath 222 3 117 SetMarkerPath 222 4 213 SetZone 223 4 SetMarkerPath 223 0 174 SetMarkerPath 223 1 175 SetMarkerPath 223 2 5 SetZone 224 12 SetMarkerPath 224 0 189 SetMarkerPathFlags 224 0 r SetRocketJumpPathFields 224 0 78.0 100.0 3 SetMarkerPath 224 1 180 SetMarkerPathFlags 224 1 r SetRocketJumpPathFields 224 1 75.0 275.0 4 SetMarkerPath 224 2 225 SetMarkerPath 224 3 146 SetZone 225 12 SetMarkerPath 225 0 7 SetMarkerPathFlags 225 0 r SetRocketJumpPathFields 225 0 80.0 76.0 3 SetMarkerPath 225 1 185 SetMarkerPathFlags 225 1 r SetRocketJumpPathFields 225 1 65.0 303.0 2 SetMarkerPath 225 2 144 SetMarkerPath 225 3 224 SetZone 226 12 SetMarkerPath 226 0 127 SetMarkerPathFlags 226 0 r SetRocketJumpPathFields 226 0 44.0 73.0 6 SetMarkerPath 226 1 144 SetZone 227 12 SetMarkerPath 227 0 140 SetMarkerPath 227 1 139 SetZone 228 11 SetMarkerPath 228 0 162 SetMarkerPath 228 1 161 SetZone 229 11 SetMarkerPath 229 0 162 SetMarkerPath 229 1 101 SetZone 230 11 SetMarkerPath 230 0 229 SetZone 231 11 SetMarkerPath 231 0 159 SetZone 232 11 SetMarkerPath 232 0 159 SetZone 233 11 SetMarkerPath 233 0 131 SetMarkerPath 233 1 130 SetZone 234 9 SetMarkerPath 234 0 117 SetMarkerPath 234 1 41 SetMarkerPath 234 2 214 SetMarkerPath 234 3 215 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/endif.bot000066400000000000000000000040431475442401000260340ustar00rootroot00000000000000CreateMarker 528 16 -520 CreateMarker -16 16 -520 CreateMarker -16 -528 -520 CreateMarker 528 -528 -520 CreateMarker 527 -269 -520 CreateMarker 265 15 -520 CreateMarker -16 -247 -520 CreateMarker 241 -527 -520 CreateMarker 121 -378 -520 CreateMarker 133 -135 -520 CreateMarker 371 -140 -520 CreateMarker 369 -369 -520 CreateMarker 260 -250 -520 SetZone 1 2 SetMarkerPath 1 0 11 SetMarkerPath 1 1 10 SetMarkerPath 1 2 9 SetMarkerPath 1 3 8 SetZone 2 2 SetMarkerPath 2 0 17 SetMarkerPath 2 1 10 SetMarkerPath 2 2 8 SetMarkerPath 2 3 7 SetZone 3 2 SetMarkerPath 3 0 8 SetMarkerPath 3 1 7 SetMarkerPath 3 2 14 SetMarkerPath 3 3 15 SetZone 4 2 SetMarkerPath 4 0 9 SetMarkerPath 4 1 6 SetMarkerPath 4 2 13 SetMarkerPath 4 3 12 SetZone 5 1 SetMarkerPath 5 0 9 SetMarkerPath 5 1 15 SetMarkerPath 5 2 10 SetZone 6 1 SetMarkerPath 6 0 10 SetMarkerPath 6 1 14 SetMarkerPath 6 2 11 SetZone 7 1 SetMarkerPath 7 0 11 SetMarkerPath 7 1 13 SetMarkerPath 7 2 12 SetZone 8 1 SetMarkerPath 8 0 12 SetMarkerPath 8 1 16 SetMarkerPath 8 2 9 SetZone 9 1 SetMarkerPath 9 0 8 SetMarkerPath 9 1 16 SetMarkerPath 9 2 17 SetMarkerPath 9 3 15 SetMarkerPath 9 4 5 SetZone 10 1 SetMarkerPath 10 0 5 SetMarkerPath 10 1 15 SetMarkerPath 10 2 17 SetMarkerPath 10 3 14 SetMarkerPath 10 4 6 SetZone 11 1 SetMarkerPath 11 0 6 SetMarkerPath 11 1 14 SetMarkerPath 11 2 17 SetMarkerPath 11 3 13 SetMarkerPath 11 4 7 SetZone 12 1 SetMarkerPath 12 0 8 SetMarkerPath 12 1 7 SetMarkerPath 12 2 13 SetMarkerPath 12 3 17 SetMarkerPath 12 4 16 SetZone 13 1 SetMarkerPath 13 0 11 SetMarkerPath 13 1 7 SetMarkerPath 13 2 12 SetMarkerPath 13 3 17 SetZone 14 1 SetMarkerPath 14 0 10 SetMarkerPath 14 1 6 SetMarkerPath 14 2 11 SetMarkerPath 14 3 17 SetZone 15 1 SetMarkerPath 15 0 9 SetMarkerPath 15 1 5 SetMarkerPath 15 2 10 SetMarkerPath 15 3 17 SetZone 16 1 SetMarkerPath 16 0 8 SetMarkerPath 16 1 9 SetMarkerPath 16 2 12 SetMarkerPath 16 3 17 SetZone 17 1 SetMarkerPath 17 0 9 SetMarkerPath 17 1 10 SetMarkerPath 17 2 11 SetMarkerPath 17 3 12 SetMarkerPath 17 4 15 SetMarkerPath 17 5 16 SetMarkerPath 17 6 13 SetMarkerPath 17 7 14 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/frobodm2.bot000066400000000000000000000411031475442401000264570ustar00rootroot00000000000000CreateMarker 2550 -2264 45 CreateMarker 1720 -1672 24 CreateMarker 1940 -1696 24 CreateMarker 2175 -1701 24 CreateMarker 2375 -1699 24 CreateMarker 2375 -1852 24 CreateMarker 2176 -2295 84 CreateMarker 2182 -1982 72 CreateMarker 2381 -1494 24 CreateMarker 1317 -1215 152 CreateMarker 1312 -1065 200 CreateMarker 2333 -39 -104 CreateMarker 2440 -36 -72 CreateMarker 2634 -34 -72 CreateMarker 2717 -36 -72 CreateMarker 2626 126 -72 CreateMarker 2478 291 -56 CreateMarker 2358 294 -8 CreateMarker 2184 233 24 CreateMarker 2144 -13 24 CreateMarker 2146 134 24 CreateMarker 2263 280 24 CreateMarker 2027 -224 24 CreateMarker 1838 -508 40 CreateMarker 1920 -507 88 CreateMarker 2022 -335 72 CreateMarker 2268 -35 24 CreateMarker 2270 -198 24 CreateMarker 2171 -223 24 CreateMarker 2470 -345 8 CreateMarker 2471 -485 8 CreateMarker 2368 -587 56 CreateMarker 2364 -478 8 CreateMarker 2241 -349 8 CreateMarker 2573 -50 120 CreateMarker 2480 -38 120 CreateMarker 2372 -36 72 CreateMarker 2600 -187 120 CreateMarker 2586 -817 120 CreateMarker 2602 -517 120 CreateMarker 2601 -688 120 CreateMarker 2598 -355 120 CreateMarker 2495 -1109 24 CreateMarker 1539 -511 24 CreateMarker 1700 -683 24 CreateMarker 2432 -831 120 CreateMarker 2495 -871 120 CreateMarker 1696 -1350 20 CreateMarker 1698 -1516 24 CreateMarker 1695 -1024 344 CreateMarker 1695 -1200 20 CreateMarker 2367 -830 56 CreateMarker 2369 -705 56 CreateMarker 1693 -824 184 CreateMarker 1696 -1040 20 CreateMarker 1366 -1312 136 CreateMarker 1516 -1349 88 CreateMarker 1865 -1343 72 CreateMarker 2047 -1220 152 CreateMarker 2046 -1056 200 CreateMarker 2497 -1314 24 CreateMarker 2587 -1414 24 CreateMarker 2494 -1537 24 CreateMarker 2713 -1415 24 CreateMarker 2719 -1857 120 CreateMarker 2723 -1638 120 CreateMarker 2718 -1528 72 CreateMarker 2992 -1871 120 CreateMarker 2992 -1993 120 CreateMarker 2666 -2258 120 CreateMarker 2434 -2299 120 CreateMarker 2551 -2301 120 CreateMarker 2704 -2180 120 CreateMarker 2432 -2062 112 CreateMarker 2432 -2168 112 CreateMarker 2586 -1984 120 CreateMarker 2286 -1981 120 CreateMarker 2319 -2456 168 CreateMarker 2430 -2451 120 CreateMarker 2176 -2396 200 CreateMarker 1396 -1024 344 CreateMarker 1321 -748 344 CreateMarker 1321 -894 344 CreateMarker 1567 -824 184 CreateMarker 1574 -1028 344 CreateMarker 1822 -825 184 CreateMarker 1808 -1023 344 CreateMarker 1950 -1012 344 CreateMarker 1331 -521 184 CreateMarker 1336 -377 184 CreateMarker 1448 -514 184 CreateMarker 1451 -588 184 CreateMarker 1533 -600 184 CreateMarker 1831 -377 184 CreateMarker 1501 -369 184 CreateMarker 1689 -369 184 CreateMarker 1407 -1104 136 CreateMarker 1954 -1104 136 CreateMarker 2541 102 -133 CreateMarker 2309 136 -134 CreateMarker 2415 115 -133 CreateMarker 2330 -2084 45 CreateMarker 2280 -2276 88 CreateMarker 2327 -2198 45 CreateMarker 2551 -2080 45 CreateMarker 2437 -2107 40 CreateMarker 1512 -1045 20 CreateMarker 1846 -1042 20 SetZone 1 7 SetMarkerPath 1 0 2 SetZone 2 7 SetMarkerPath 2 0 104 SetMarkerPath 2 1 94 SetMarkerPath 2 2 156 SetMarkerPath 2 3 157 SetZone 3 7 SetMarkerPath 3 0 2 SetZone 4 10 SetMarkerPath 4 0 5 SetZone 5 10 SetMarkerPath 5 0 130 SetGoal 6 1 SetZone 6 1 SetMarkerPath 6 0 64 SetMarkerPath 6 1 4 SetGoal 7 2 SetZone 7 1 SetMarkerPath 7 0 41 SetMarkerPath 7 1 61 SetZone 8 2 SetMarkerPath 8 0 16 SetZone 9 1 SetMarkerPath 9 0 62 SetMarkerPath 9 1 63 SetZone 10 2 SetMarkerPath 10 0 80 SetGoal 11 23 SetZone 11 2 SetMarkerPath 11 0 79 SetGoal 12 3 SetZone 12 3 SetMarkerPath 12 0 87 SetMarkerPath 12 1 13 SetMarkerPath 12 2 16 SetMarkerPath 12 3 77 SetMarkerPath 12 4 84 SetGoal 13 3 SetZone 13 3 SetMarkerPath 13 0 87 SetMarkerPath 13 1 12 SetMarkerPath 13 2 16 SetMarkerPath 13 3 77 SetMarkerPath 13 4 91 SetGoal 14 4 SetZone 14 1 SetMarkerPath 14 0 65 SetMarkerPath 14 1 66 SetGoal 15 5 SetZone 15 10 SetMarkerPath 15 0 137 SetMarkerPath 15 1 38 SetGoal 16 22 SetZone 16 2 SetMarkerPath 16 0 77 SetMarkerPath 16 1 8 SetGoal 17 6 SetZone 17 9 SetMarkerPath 17 0 141 SetMarkerPath 17 1 39 SetMarkerPath 17 2 142 SetGoal 18 23 SetZone 18 2 SetMarkerPath 18 0 40 SetMarkerPath 18 1 72 SetMarkerPath 18 2 69 SetGoal 19 7 SetZone 19 6 SetMarkerPath 19 0 123 SetMarkerPath 19 1 49 SetMarkerPath 19 2 126 SetGoal 20 8 SetZone 20 5 SetMarkerPath 20 0 58 SetMarkerPath 20 1 21 SetMarkerPath 20 2 111 SetMarkerPath 20 3 112 SetGoal 21 8 SetZone 21 5 SetMarkerPath 21 0 110 SetMarkerPath 21 1 112 SetMarkerPath 21 2 20 SetMarkerPath 21 3 111 SetGoal 22 23 SetZone 22 5 SetMarkerPath 22 0 55 SetMarkerPath 22 1 57 SetZone 23 5 SetMarkerPath 23 0 57 SetMarkerPath 23 1 56 SetMarkerPath 23 2 129 SetMarkerPathFlags 23 2 r SetRocketJumpPathFields 23 2 59.0 167.0 0 SetZone 24 5 SetMarkerPath 24 0 110 SetMarkerPath 24 1 111 SetMarkerPath 24 2 58 SetMarkerPath 24 3 112 SetZone 25 6 SetMarkerPath 25 0 118 SetMarkerPath 25 1 122 SetGoal 26 21 SetZone 26 6 SetMarkerPath 26 0 121 SetMarkerPath 26 1 122 SetMarkerPath 26 2 119 SetGoal 27 9 SetZone 27 6 SetMarkerPath 27 0 127 SetMarkerPath 27 1 129 SetZone 28 8 SetMarkerPath 28 0 94 SetMarkerPath 28 1 93 SetMarkerPath 28 2 73 SetMarkerPath 28 3 140 SetMarkerPathFlags 28 3 r SetRocketJumpPathFields 28 3 66.0 1.0 0 SetMarkerPath 28 4 44 SetMarkerPathFlags 28 4 r SetRocketJumpPathFields 28 4 78.3 -1.0 0 SetZone 29 7 SetMarkerPath 29 0 107 SetMarkerPath 29 1 108 SetZone 30 7 SetMarkerPath 30 0 105 SetMarkerPath 30 1 106 SetZone 31 7 SetMarkerPath 31 0 30 SetGoal 32 10 SetZone 32 5 SetMarkerPath 32 0 55 SetMarkerPath 32 1 112 SetMarkerPath 32 2 54 SetMarkerPath 32 3 58 SetGoal 33 11 SetZone 33 8 SetMarkerPath 33 0 74 SetMarkerPath 33 1 34 SetGoal 34 11 SetZone 34 8 SetMarkerPath 34 0 74 SetMarkerPath 34 1 33 SetMarkerPath 34 2 75 SetMarkerPath 34 3 43 SetMarkerPathFlags 34 3 r SetRocketJumpPathFields 34 3 56.0 116.0 0 SetGoal 35 12 SetZone 35 7 SetMarkerPath 35 0 3 SetMarkerPath 35 1 109 SetMarkerPathFlags 35 1 r SetRocketJumpPathFields 35 1 66.0 85.0 0 SetGoal 36 13 SetZone 36 7 SetMarkerPath 36 0 1 SetMarkerPath 36 1 60 SetMarkerPathFlags 36 1 r SetRocketJumpPathFields 36 1 69.0 88.0 0 SetGoal 37 14 SetZone 37 10 SetMarkerPath 37 0 137 SetMarkerPath 37 1 38 SetGoal 38 15 SetZone 38 10 SetMarkerPath 38 0 137 SetMarkerPath 38 1 15 SetMarkerPath 38 2 37 SetGoal 39 16 SetZone 39 9 SetMarkerPath 39 0 17 SetMarkerPath 39 1 142 SetMarkerPath 39 2 141 SetGoal 40 17 SetZone 40 2 SetMarkerPath 40 0 69 SetMarkerPath 40 1 78 SetMarkerPath 40 2 18 SetMarkerPath 40 3 72 SetZone 41 1 SetMarkerPath 41 0 7 SetMarkerPath 41 1 61 SetGoal 43 18 SetZone 43 9 SetMarkerPath 43 0 45 SetMarkerPath 43 1 44 SetGoal 44 19 SetZone 44 9 SetMarkerPath 44 0 143 SetMarkerPath 44 1 45 SetMarkerPath 44 2 43 SetMarkerPath 44 3 73 SetMarkerPath 44 4 74 SetMarkerPath 44 5 34 SetGoal 45 19 SetZone 45 9 SetMarkerPath 45 0 143 SetMarkerPath 45 1 44 SetMarkerPath 45 2 43 SetMarkerPath 45 3 74 SetMarkerPath 45 4 73 SetMarkerPath 45 5 34 SetZone 46 3 SetMarkerPath 46 0 92 SetMarkerPath 46 1 96 SetZone 47 10 SetMarkerPath 47 0 138 SetMarkerPath 47 1 131 SetGoal 48 20 SetZone 48 4 SetMarkerPath 48 0 102 SetMarkerPath 48 1 81 SetGoal 49 24 SetZone 49 6 SetMarkerPath 49 0 123 SetMarkerPath 49 1 19 SetMarkerPath 49 2 125 SetZone 50 6 SetMarkerPath 50 0 154 SetZone 51 7 SetMarkerPath 51 0 52 SetMarkerPath 51 1 98 SetZone 52 7 SetMarkerPath 52 0 53 SetMarkerPath 52 1 51 SetZone 53 7 SetMarkerPath 53 0 54 SetMarkerPath 53 1 52 SetZone 54 5 SetMarkerPath 54 0 53 SetMarkerPath 54 1 55 SetMarkerPath 54 2 32 SetMarkerPath 54 3 58 SetMarkerPath 54 4 112 SetZone 55 5 SetMarkerPath 55 0 54 SetMarkerPath 55 1 22 SetMarkerPath 55 2 32 SetZone 56 5 SetMarkerPath 56 0 23 SetMarkerPath 56 1 129 SetMarkerPathFlags 56 1 r SetRocketJumpPathFields 56 1 65.0 90.0 0 SetZone 57 5 SetMarkerPath 57 0 22 SetMarkerPath 57 1 23 SetMarkerPath 57 2 126 SetMarkerPathFlags 57 2 r SetRocketJumpPathFields 57 2 46.0 178.0 3 SetZone 58 5 SetMarkerPath 58 0 110 SetMarkerPath 58 1 54 SetMarkerPath 58 2 32 SetMarkerPath 58 3 20 SetMarkerPath 58 4 112 SetMarkerPath 58 5 111 SetZone 59 7 SetMarkerPath 59 0 105 SetMarkerPath 59 1 60 SetZone 60 7 SetMarkerPath 60 0 59 SetMarkerPath 60 1 36 SetZone 61 1 SetMarkerPath 61 0 7 SetMarkerPath 61 1 41 SetMarkerPath 61 2 62 SetZone 62 1 SetMarkerPath 62 0 61 SetMarkerPath 62 1 9 SetZone 63 1 SetMarkerPath 63 0 9 SetMarkerPath 63 1 64 SetMarkerPath 63 2 65 SetZone 64 1 SetMarkerPath 64 0 63 SetMarkerPath 64 1 6 SetZone 65 1 SetMarkerPath 65 0 63 SetMarkerPath 65 1 14 SetZone 66 1 SetMarkerPath 66 0 14 SetMarkerPath 66 1 67 SetZone 67 1 SetMarkerPath 67 0 66 SetMarkerPath 67 1 71 SetZone 68 1 SetMarkerPath 68 0 71 SetMarkerPath 68 1 70 SetZone 69 2 SetMarkerPath 69 0 70 SetMarkerPath 69 1 40 SetMarkerPath 69 2 76 SetMarkerPath 69 3 77 SetMarkerPath 69 4 72 SetMarkerPath 69 5 78 SetZone 70 1 SetMarkerPath 70 0 68 SetMarkerPath 70 1 69 SetZone 71 1 SetMarkerPath 71 0 67 SetMarkerPath 71 1 68 SetZone 72 2 SetMarkerPath 72 0 69 SetMarkerPath 72 1 76 SetMarkerPath 72 2 78 SetMarkerPath 72 3 40 SetMarkerPath 72 4 18 SetMarkerPath 72 5 75 SetZone 73 8 SetMarkerPath 73 0 28 SetMarkerPath 73 1 74 SetMarkerPath 73 2 143 SetMarkerPathFlags 73 2 r SetRocketJumpPathFields 73 2 56.0 270.0 0 SetMarkerPath 73 3 43 SetMarkerPathFlags 73 3 r SetRocketJumpPathFields 73 3 68.0 104.0 0 SetZone 74 8 SetMarkerPath 74 0 73 SetMarkerPath 74 1 34 SetMarkerPath 74 2 33 SetMarkerPath 74 3 45 SetMarkerPathFlags 74 3 r SetRocketJumpPathFields 74 3 54.0 231.0 0 SetMarkerPath 74 4 43 SetMarkerPathFlags 74 4 r SetRocketJumpPathFields 74 4 70.0 88.0 0 SetZone 75 8 SetMarkerPath 75 0 34 SetMarkerPath 75 1 72 SetZone 76 2 SetMarkerPath 76 0 69 SetMarkerPath 76 1 77 SetMarkerPath 76 2 86 SetMarkerPath 76 3 78 SetMarkerPath 76 4 72 SetZone 77 2 SetMarkerPath 77 0 69 SetMarkerPath 77 1 76 SetMarkerPath 77 2 78 SetMarkerPath 77 3 16 SetZone 78 2 SetMarkerPath 78 0 69 SetMarkerPath 78 1 76 SetMarkerPath 78 2 72 SetMarkerPath 78 3 77 SetMarkerPath 78 4 83 SetMarkerPath 78 5 40 SetZone 79 2 SetMarkerPath 79 0 83 SetMarkerPath 79 1 11 SetMarkerPath 79 2 80 SetMarkerPath 79 3 82 SetZone 80 2 SetMarkerPath 80 0 79 SetMarkerPath 80 1 10 SetMarkerPath 80 2 82 SetZone 81 4 SetMarkerPath 81 0 102 SetMarkerPath 81 1 48 SetMarkerPath 81 2 82 SetZone 82 2 SetMarkerPath 82 0 80 SetMarkerPath 82 1 83 SetMarkerPath 82 2 79 SetZone 83 2 SetMarkerPath 83 0 78 SetMarkerPath 83 1 79 SetMarkerPath 83 2 82 SetZone 84 3 SetMarkerPath 84 0 85 SetMarkerPath 84 1 87 SetMarkerPath 84 2 12 SetZone 85 3 SetMarkerPath 85 0 86 SetMarkerPath 85 1 84 SetZone 86 3 SetMarkerPath 86 0 76 SetMarkerPath 86 1 85 SetZone 87 3 SetMarkerPath 87 0 84 SetMarkerPath 87 1 91 SetMarkerPath 87 2 12 SetMarkerPath 87 3 13 SetZone 88 3 SetMarkerPath 88 0 90 SetMarkerPath 88 1 95 SetMarkerPath 88 2 96 SetZone 89 3 SetMarkerPath 89 0 91 SetMarkerPath 89 1 90 SetZone 90 3 SetMarkerPath 90 0 89 SetMarkerPath 90 1 88 SetZone 91 3 SetMarkerPath 91 0 87 SetMarkerPath 91 1 89 SetMarkerPath 91 2 13 SetZone 92 5 SetMarkerPath 92 0 46 SetMarkerPathFlags 92 0 v SetMarkerPath 92 1 110 SetZone 93 8 SetMarkerPath 93 0 28 SetZone 94 8 SetMarkerPath 94 0 2 SetMarkerPath 94 1 28 SetZone 95 3 SetMarkerPath 95 0 88 SetMarkerPath 95 1 96 SetMarkerPath 95 2 101 SetZone 96 3 SetMarkerPath 96 0 88 SetMarkerPath 96 1 95 SetMarkerPath 96 2 92 SetZone 97 7 SetMarkerPath 97 0 98 SetMarkerPath 97 1 100 SetMarkerPath 97 2 107 SetMarkerPath 97 3 106 SetZone 98 7 SetMarkerPath 98 0 51 SetMarkerPath 98 1 97 SetZone 99 10 SetMarkerPath 99 0 134 SetMarkerPath 99 1 136 SetMarkerPath 99 2 103 SetMarkerPath 99 3 2 SetMarkerPath 99 4 100 SetZone 100 7 SetMarkerPath 100 0 97 SetMarkerPath 100 1 104 SetMarkerPath 100 2 156 SetMarkerPath 100 3 157 SetZone 101 4 SetMarkerPath 101 0 102 SetMarkerPath 101 1 95 SetMarkerPathFlags 101 1 r SetRocketJumpPathFields 101 1 57.0 180.0 8 SetZone 102 4 SetMarkerPath 102 0 101 SetMarkerPath 102 1 48 SetMarkerPath 102 2 81 SetZone 103 11 SetMarkerPath 103 0 133 SetMarkerPath 103 1 135 SetMarkerPath 103 2 2 SetMarkerPath 103 3 104 SetMarkerPath 103 4 134 SetMarkerPathFlags 103 4 r SetRocketJumpPathFields 103 4 60.0 50.0 0 SetMarkerPath 103 5 136 SetMarkerPathFlags 103 5 r SetRocketJumpPathFields 103 5 60.0 115.0 0 SetZone 104 7 SetMarkerPath 104 0 100 SetMarkerPath 104 1 2 SetMarkerPath 104 2 103 SetMarkerPathFlags 104 2 r SetRocketJumpPathFields 104 2 62.0 266.0 0 SetMarkerPath 104 3 156 SetMarkerPath 104 4 157 SetZone 105 7 SetMarkerPath 105 0 106 SetMarkerPath 105 1 59 SetZone 106 7 SetMarkerPath 106 0 97 SetMarkerPath 106 1 105 SetMarkerPath 106 2 156 SetZone 107 7 SetMarkerPath 107 0 97 SetMarkerPath 107 1 29 SetMarkerPath 107 2 157 SetZone 108 7 SetMarkerPath 108 0 29 SetMarkerPath 108 1 109 SetZone 109 7 SetMarkerPath 109 0 108 SetMarkerPath 109 1 35 SetZone 110 5 SetMarkerPath 110 0 92 SetMarkerPath 110 1 58 SetMarkerPath 110 2 112 SetMarkerPath 110 3 111 SetMarkerPath 110 4 24 SetMarkerPath 110 5 21 SetMarkerPath 110 6 96 SetMarkerPathFlags 110 6 r SetRocketJumpPathFields 110 6 41.0 270.0 0 SetZone 111 5 SetMarkerPath 111 0 110 SetMarkerPath 111 1 24 SetMarkerPath 111 2 58 SetMarkerPath 111 3 112 SetMarkerPath 111 4 113 SetMarkerPath 111 5 21 SetZone 112 5 SetMarkerPath 112 0 110 SetMarkerPath 112 1 32 SetMarkerPath 112 2 54 SetMarkerPath 112 3 58 SetMarkerPath 112 4 111 SetMarkerPath 112 5 21 SetZone 113 5 SetMarkerPath 113 0 111 SetMarkerPath 113 1 116 SetZone 114 6 SetMarkerPath 114 0 115 SetMarkerPath 114 1 117 SetZone 115 6 SetMarkerPath 115 0 116 SetMarkerPath 115 1 114 SetZone 116 6 SetMarkerPath 116 0 113 SetMarkerPath 116 1 115 SetZone 117 6 SetMarkerPath 117 0 114 SetMarkerPath 117 1 118 SetZone 118 6 SetMarkerPath 118 0 117 SetMarkerPath 118 1 25 SetZone 119 6 SetMarkerPath 119 0 122 SetMarkerPath 119 1 121 SetMarkerPath 119 2 26 SetZone 120 6 SetMarkerPath 120 0 121 SetMarkerPath 120 1 124 SetMarkerPath 120 2 128 SetZone 121 6 SetMarkerPath 121 0 119 SetMarkerPath 121 1 26 SetMarkerPath 121 2 120 SetZone 122 6 SetMarkerPath 122 0 25 SetMarkerPath 122 1 119 SetMarkerPath 122 2 26 SetZone 123 6 SetMarkerPath 123 0 124 SetMarkerPath 123 1 19 SetMarkerPath 123 2 49 SetZone 124 6 SetMarkerPath 124 0 120 SetMarkerPath 124 1 123 SetZone 125 6 SetMarkerPath 125 0 49 SetZone 126 6 SetMarkerPath 126 0 19 SetMarkerPath 126 1 57 SetZone 127 6 SetMarkerPath 127 0 128 SetMarkerPath 127 1 27 SetZone 128 6 SetMarkerPath 128 0 120 SetMarkerPath 128 1 127 SetMarkerPath 128 2 31 SetZone 129 6 SetMarkerPath 129 0 27 SetMarkerPath 129 1 56 SetMarkerPath 129 2 23 SetZone 130 10 SetMarkerPath 130 0 132 SetMarkerPath 130 1 134 SetZone 131 10 SetMarkerPath 131 0 132 SetMarkerPath 131 1 138 SetZone 132 10 SetMarkerPath 132 0 130 SetMarkerPath 132 1 131 SetZone 133 11 SetMarkerPath 133 0 103 SetMarkerPath 133 1 104 SetMarkerPath 133 2 2 SetMarkerPath 133 3 134 SetMarkerPathFlags 133 3 r SetRocketJumpPathFields 133 3 63.0 94.0 0 SetMarkerPath 133 4 136 SetMarkerPathFlags 133 4 r SetRocketJumpPathFields 133 4 61.0 135.0 0 SetZone 134 10 SetMarkerPath 134 0 130 SetMarkerPath 134 1 99 SetMarkerPath 134 2 133 SetMarkerPath 134 3 100 SetMarkerPath 134 4 103 SetZone 135 11 SetMarkerPath 135 0 103 SetMarkerPath 135 1 104 SetMarkerPath 135 2 2 SetMarkerPath 135 3 134 SetMarkerPathFlags 135 3 r SetRocketJumpPathFields 135 3 64.0 56.0 0 SetMarkerPath 135 4 136 SetMarkerPathFlags 135 4 r SetRocketJumpPathFields 135 4 62.0 70.0 0 SetZone 136 10 SetMarkerPath 136 0 99 SetMarkerPath 136 1 137 SetMarkerPath 136 2 135 SetMarkerPath 136 3 100 SetMarkerPath 136 4 103 SetZone 137 10 SetMarkerPath 137 0 136 SetMarkerPath 137 1 15 SetMarkerPath 137 2 37 SetMarkerPath 137 3 38 SetZone 138 9 SetMarkerPath 138 0 131 SetMarkerPathFlags 138 0 v SetMarkerPath 138 1 139 SetMarkerPath 138 2 140 SetZone 139 9 SetMarkerPath 139 0 138 SetMarkerPath 139 1 144 SetZone 140 9 SetMarkerPath 140 0 138 SetMarkerPath 140 1 141 SetMarkerPath 140 2 142 SetMarkerPath 140 4 28 SetZone 141 9 SetMarkerPath 141 0 140 SetMarkerPath 141 1 17 SetMarkerPath 141 2 142 SetMarkerPath 141 3 39 SetMarkerPath 141 4 93 SetMarkerPath 141 5 28 SetZone 142 9 SetMarkerPath 142 0 39 SetMarkerPath 142 1 141 SetMarkerPath 142 2 17 SetMarkerPath 142 3 140 SetZone 143 9 SetMarkerPath 143 0 145 SetMarkerPath 143 1 44 SetMarkerPath 143 2 45 SetMarkerPath 143 3 73 SetZone 144 9 SetMarkerPath 144 0 139 SetMarkerPath 144 1 145 SetZone 145 9 SetMarkerPath 145 0 144 SetMarkerPath 145 1 143 SetZone 146 7 SetMarkerPath 146 0 100 SetZone 147 7 SetMarkerPath 147 0 100 SetZone 148 1 SetMarkerPath 148 0 65 SetZone 149 1 SetMarkerPath 149 0 150 SetZone 150 1 SetMarkerPath 150 0 148 SetZone 151 6 SetMarkerPath 151 0 123 SetMarkerPath 151 1 126 SetZone 152 6 SetMarkerPath 152 0 120 SetZone 153 6 SetMarkerPath 153 0 152 SetZone 154 6 SetMarkerPath 154 0 123 SetMarkerPath 154 1 125 SetZone 155 6 SetMarkerPath 155 0 154 SetMarkerPath 155 1 151 SetMarkerPath 155 2 153 SetZone 156 7 SetMarkerPath 156 0 2 SetMarkerPath 156 1 104 SetMarkerPath 156 2 100 SetZone 157 7 SetMarkerPath 157 0 104 SetMarkerPath 157 1 2 SetMarkerPath 157 2 100 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/marena2.bot000066400000000000000000000124201475442401000262720ustar00rootroot00000000000000CreateMarker 369 -311 -744 CreateMarker 34 -511 -744 CreateMarker -312 -365 -744 CreateMarker -507 -10 -744 CreateMarker -359 319 -744 CreateMarker -31 514 -744 CreateMarker 327 350 -744 CreateMarker 228 -66 -744 CreateMarker 240 79 -744 CreateMarker 85 223 -744 CreateMarker -70 239 -744 CreateMarker -265 103 -744 CreateMarker -243 -112 -744 CreateMarker -97 -253 -744 CreateMarker 114 -246 -744 CreateMarker -35 -50 -744 CreateMarker -50 84 -744 CreateMarker 94 86 -744 CreateMarker 94 -52 -744 CreateMarker -227 -577 -744 CreateMarker -476 -524 -744 CreateMarker -569 -306 -744 CreateMarker -707 4 -744 CreateMarker -627 234 -744 CreateMarker -560 449 -744 CreateMarker -330 598 -744 CreateMarker -14 723 -744 CreateMarker 232 605 -744 CreateMarker 485 511 -744 CreateMarker 578 269 -744 CreateMarker 696 -21 -744 CreateMarker 587 -249 -744 CreateMarker 528 -510 -744 CreateMarker 299 -633 -744 CreateMarker 0 -653 -744 SetZone 3 5 SetMarkerPath 3 0 4 SetZone 4 4 SetMarkerPath 4 1 22 SetMarkerPath 4 2 53 SetMarkerPath 4 3 52 SetZone 5 2 SetMarkerPath 5 0 25 SetZone 6 5 SetMarkerPath 6 1 21 SetMarkerPath 6 2 7 SetMarkerPath 6 3 8 SetMarkerPath 6 4 11 SetMarkerPath 6 5 12 SetZone 7 5 SetMarkerPath 7 1 6 SetMarkerPath 7 2 10 SetMarkerPath 7 3 18 SetZone 8 5 SetMarkerPath 8 1 14 SetMarkerPath 8 2 6 SetZone 9 5 SetMarkerPath 9 1 14 SetMarkerPath 9 2 10 SetMarkerPath 9 3 18 SetZone 10 5 SetMarkerPath 10 1 14 SetMarkerPath 10 2 11 SetMarkerPath 10 3 12 SetMarkerPath 10 4 13 SetMarkerPath 10 5 9 SetMarkerPath 10 6 7 SetMarkerPath 10 7 16 SetZone 11 5 SetMarkerPath 11 1 14 SetMarkerPath 11 2 6 SetMarkerPath 11 3 10 SetZone 12 5 SetMarkerPath 12 1 14 SetMarkerPath 12 2 6 SetMarkerPath 12 3 10 SetZone 13 5 SetMarkerPath 13 1 14 SetMarkerPath 13 2 19 SetMarkerPath 13 3 17 SetMarkerPath 13 4 15 SetMarkerPath 13 5 21 SetMarkerPath 13 6 10 SetZone 14 5 SetMarkerPath 14 1 15 SetMarkerPath 14 2 16 SetMarkerPath 14 3 17 SetMarkerPath 14 4 18 SetMarkerPath 14 5 19 SetMarkerPath 14 6 20 SetMarkerPath 14 7 13 SetZone 15 5 SetMarkerPath 15 1 21 SetMarkerPath 15 2 14 SetMarkerPath 15 3 13 SetZone 16 5 SetMarkerPath 16 1 21 SetMarkerPath 16 2 14 SetMarkerPath 16 3 10 SetZone 17 5 SetMarkerPath 17 1 14 SetMarkerPath 17 2 13 SetMarkerPath 17 3 18 SetZone 18 5 SetMarkerPath 18 1 14 SetMarkerPath 18 2 17 SetMarkerPath 18 3 9 SetMarkerPath 18 4 7 SetZone 19 5 SetMarkerPath 19 1 14 SetMarkerPath 19 2 13 SetZone 20 5 SetMarkerPath 20 1 14 SetZone 21 5 SetMarkerPath 21 1 16 SetMarkerPath 21 2 15 SetMarkerPath 21 3 6 SetMarkerPath 21 4 13 SetZone 22 1 SetMarkerPath 22 1 4 SetMarkerPath 22 2 23 SetMarkerPath 22 3 53 SetMarkerPath 22 4 54 SetZone 23 1 SetMarkerPath 23 1 24 SetMarkerPath 23 2 22 SetMarkerPath 23 3 56 SetZone 24 1 SetMarkerPath 24 1 25 SetMarkerPath 24 2 23 SetMarkerPath 24 3 42 SetZone 25 2 SetMarkerPath 25 1 34 SetMarkerPath 25 2 24 SetMarkerPath 25 3 26 SetMarkerPath 25 4 44 SetZone 26 2 SetMarkerPath 26 1 27 SetMarkerPath 26 2 33 SetMarkerPath 26 3 25 SetMarkerPath 26 4 46 SetZone 27 3 SetMarkerPath 27 1 28 SetMarkerPath 27 2 26 SetMarkerPath 27 3 48 SetZone 28 3 SetMarkerPath 28 1 30 SetMarkerPath 28 2 27 SetMarkerPath 28 3 50 SetZone 29 4 SetMarkerPath 29 1 40 SetMarkerPath 29 2 30 SetMarkerPath 29 3 36 SetZone 30 4 SetMarkerPath 30 1 39 SetMarkerPath 30 2 31 SetMarkerPath 30 3 29 SetMarkerPath 30 4 28 SetZone 31 3 SetMarkerPath 31 1 39 SetMarkerPath 31 2 32 SetMarkerPath 31 3 30 SetZone 32 3 SetMarkerPath 32 1 38 SetMarkerPath 32 2 33 SetMarkerPath 32 3 31 SetZone 33 2 SetMarkerPath 33 1 38 SetMarkerPath 33 2 34 SetMarkerPath 33 3 32 SetMarkerPath 33 4 26 SetZone 34 2 SetMarkerPath 34 1 37 SetMarkerPath 34 2 35 SetMarkerPath 34 3 33 SetMarkerPath 34 4 25 SetZone 35 1 SetMarkerPath 35 1 37 SetMarkerPath 35 2 36 SetMarkerPath 35 3 34 SetZone 36 1 SetMarkerPath 36 1 40 SetMarkerPath 36 2 35 SetMarkerPath 36 3 29 SetZone 37 4 SetMarkerPath 37 1 38 SetMarkerPath 37 2 40 SetMarkerPath 37 3 34 SetMarkerPath 37 4 35 SetZone 38 4 SetMarkerPath 38 1 37 SetMarkerPath 38 2 39 SetMarkerPath 38 3 32 SetMarkerPath 38 4 33 SetZone 39 4 SetMarkerPath 39 1 38 SetMarkerPath 39 2 40 SetMarkerPath 39 3 30 SetMarkerPath 39 4 31 SetZone 40 4 SetMarkerPath 40 1 39 SetMarkerPath 40 2 37 SetMarkerPath 40 3 29 SetMarkerPath 40 4 36 SetZone 41 1 SetMarkerPath 41 1 56 SetMarkerPath 41 2 42 SetZone 42 1 SetMarkerPath 42 1 41 SetMarkerPath 42 2 43 SetMarkerPath 42 3 24 SetZone 43 2 SetMarkerPath 43 1 42 SetMarkerPath 43 2 44 SetZone 44 2 SetMarkerPath 44 1 43 SetMarkerPath 44 2 45 SetMarkerPath 44 3 25 SetZone 45 2 SetMarkerPath 45 1 44 SetMarkerPath 45 2 46 SetZone 46 2 SetMarkerPath 46 1 45 SetMarkerPath 46 2 47 SetMarkerPath 46 3 26 SetZone 47 2 SetMarkerPath 47 1 46 SetMarkerPath 47 2 48 SetZone 48 3 SetMarkerPath 48 1 47 SetMarkerPath 48 2 49 SetMarkerPath 48 3 27 SetZone 49 3 SetMarkerPath 49 1 48 SetMarkerPath 49 2 50 SetZone 50 3 SetMarkerPath 50 1 49 SetMarkerPath 50 2 51 SetMarkerPath 50 3 28 SetZone 51 3 SetMarkerPath 51 1 50 SetMarkerPath 51 2 52 SetZone 52 4 SetMarkerPath 52 1 51 SetMarkerPath 52 2 53 SetMarkerPath 52 3 4 SetZone 53 4 SetMarkerPath 53 1 22 SetMarkerPath 53 2 54 SetMarkerPath 53 3 52 SetMarkerPath 53 4 4 SetZone 54 1 SetMarkerPath 54 1 53 SetMarkerPath 54 2 55 SetMarkerPath 54 3 22 SetZone 55 1 SetMarkerPath 55 1 54 SetMarkerPath 55 2 56 SetZone 56 1 SetMarkerPath 56 1 55 SetMarkerPath 56 2 41 SetMarkerPath 56 3 23 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/marena3.bot000066400000000000000000000076371475442401000263110ustar00rootroot00000000000000CreateMarker -217 77 24 CreateMarker 2 -5 -104 CreateMarker 106 196 -232 CreateMarker -69 142 -232 CreateMarker -200 -46 -232 CreateMarker 30 -166 -232 CreateMarker 178 52 -232 CreateMarker 290 83 -232 CreateMarker 266 268 -232 CreateMarker 119 379 -232 CreateMarker -85 362 -232 CreateMarker -208 313 -232 CreateMarker -272 162 -232 CreateMarker -296 38 -232 CreateMarker -334 -85 -232 CreateMarker -286 -304 -232 CreateMarker -97 -381 -232 CreateMarker 72 -371 -232 CreateMarker 217 -323 -232 CreateMarker 258 -198 -232 CreateMarker 304 -88 -232 CreateMarker 350 -258 -184 CreateMarker 419 -120 -136 CreateMarker 416 -12 -72 CreateMarker 402 154 -72 CreateMarker 312 264 -72 CreateMarker 164 387 -72 CreateMarker -17 407 -72 CreateMarker -350 258 -184 CreateMarker -413 134 -136 CreateMarker -427 -14 -72 CreateMarker -400 -180 -72 CreateMarker -221 -366 -72 CreateMarker 49 -409 -72 CreateMarker 224 -88 24 SetZone 1 1 SetMarkerViewOfs 1 25 SetMarkerPath 1 1 3 SetZone 2 1 SetMarkerViewOfs 2 25 SetMarkerPath 2 1 4 SetZone 3 6 SetMarkerPath 3 1 14 SetMarkerPath 3 2 15 SetZone 4 6 SetMarkerPath 4 1 48 SetMarkerPath 4 2 15 SetZone 5 7 SetMarkerViewOfs 5 25 SetMarkerPath 5 0 12 SetMarkerPath 5 1 19 SetZone 6 7 SetMarkerPath 6 1 11 SetMarkerPath 6 2 7 SetZone 7 7 SetMarkerPath 7 1 6 SetMarkerPath 7 2 10 SetZone 8 7 SetMarkerPath 8 1 10 SetMarkerPath 8 2 9 SetMarkerPath 8 3 5 SetZone 9 7 SetMarkerPath 9 1 11 SetMarkerPath 9 2 8 SetMarkerPath 9 3 5 SetZone 10 7 SetMarkerPath 10 1 7 SetMarkerPath 10 2 8 SetZone 11 7 SetMarkerPath 11 1 9 SetMarkerPath 11 2 6 SetZone 12 1 SetMarkerPath 12 1 29 SetMarkerPath 12 2 18 SetMarkerPath 12 3 19 SetZone 13 1 SetMarkerPath 13 0 16 SetMarkerPath 13 1 21 SetMarkerPath 13 2 22 SetZone 14 6 SetMarkerPath 14 1 3 SetMarkerPath 14 2 15 SetZone 15 1 SetMarkerPath 15 1 19 SetMarkerPath 15 2 17 SetZone 16 1 SetMarkerPath 16 1 17 SetMarkerPath 16 2 22 SetMarkerPath 16 3 20 SetZone 17 1 SetMarkerPath 17 1 16 SetMarkerPath 17 2 18 SetZone 18 1 SetMarkerPath 18 1 17 SetMarkerPath 18 2 28 SetMarkerPath 18 3 12 SetZone 19 1 SetMarkerPath 19 1 12 SetMarkerPath 19 2 20 SetZone 20 1 SetMarkerPath 20 1 21 SetMarkerPath 20 2 19 SetMarkerPath 20 3 16 SetZone 21 1 SetMarkerPath 21 0 13 SetMarkerPath 21 1 22 SetMarkerPath 21 2 20 SetMarkerPath 21 3 34 SetMarkerPath 21 4 2 SetZone 22 1 SetMarkerPath 22 0 13 SetMarkerPath 22 1 23 SetMarkerPath 22 2 16 SetMarkerPath 22 3 21 SetZone 23 2 SetMarkerPath 23 1 24 SetMarkerPath 23 2 22 SetZone 24 2 SetMarkerPath 24 1 25 SetMarkerPath 24 2 23 SetZone 25 2 SetMarkerPath 25 1 26 SetMarkerPath 25 2 24 SetMarkerPath 25 3 42 SetZone 26 2 SetMarkerPath 26 1 27 SetMarkerPath 26 2 25 SetZone 27 2 SetMarkerPath 27 1 26 SetMarkerPath 27 2 28 SetZone 28 1 SetMarkerPath 28 1 29 SetMarkerPath 28 2 18 SetMarkerPath 28 3 27 SetMarkerPath 28 4 1 SetZone 29 4 SetMarkerPath 29 1 30 SetMarkerPath 29 2 12 SetMarkerPath 29 3 28 SetZone 30 4 SetMarkerPath 30 1 31 SetMarkerPath 30 2 29 SetZone 31 4 SetMarkerPath 31 1 32 SetMarkerPath 31 2 30 SetZone 32 4 SetMarkerPath 32 1 33 SetMarkerPath 32 2 31 SetMarkerPath 32 3 35 SetZone 33 4 SetMarkerPath 33 1 34 SetMarkerPath 33 2 32 SetZone 34 4 SetMarkerPath 34 1 33 SetMarkerPath 34 2 21 SetZone 35 5 SetMarkerPath 35 1 32 SetMarkerPath 35 2 36 SetZone 36 5 SetMarkerPath 36 1 35 SetMarkerPath 36 2 37 SetZone 37 5 SetMarkerPath 37 1 36 SetMarkerPath 37 2 38 SetZone 38 5 SetMarkerPath 38 1 37 SetMarkerPath 38 2 39 SetZone 39 5 SetMarkerPath 39 1 38 SetMarkerPath 39 2 40 SetZone 40 5 SetMarkerPath 40 1 39 SetMarkerPath 40 2 41 SetZone 41 5 SetMarkerPath 41 1 40 SetMarkerPath 41 2 25 SetZone 42 3 SetMarkerPath 42 1 25 SetMarkerPath 42 2 43 SetZone 43 3 SetMarkerPath 43 1 42 SetMarkerPath 43 2 44 SetZone 44 3 SetMarkerPath 44 1 43 SetMarkerPath 44 2 45 SetZone 45 3 SetMarkerPath 45 1 44 SetMarkerPath 45 2 46 SetZone 46 3 SetMarkerPath 46 1 45 SetMarkerPath 46 2 47 SetZone 47 3 SetMarkerPath 47 1 46 SetMarkerPath 47 2 32 SetZone 48 6 SetMarkerPath 48 1 4 SetMarkerPath 48 2 15 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/monsoon.bot000066400000000000000000000577111475442401000264510ustar00rootroot00000000000000CreateMarker 571 748 296 CreateMarker 637 849 296 CreateMarker 788 852 272 CreateMarker 884 852 224 CreateMarker 1000 734 168 CreateMarker 1006 672 136 CreateMarker 990 601 104 CreateMarker 987 509 88 CreateMarker 925 462 88 CreateMarker 827 539 88 CreateMarker 871 692 88 CreateMarker 738 624 88 CreateMarker 739 761 88 CreateMarker 581 726 120 CreateMarker 614 425 120 CreateMarker 727 465 88 CreateMarker 835 278 88 CreateMarker 837 102 32 CreateMarker 922 50 32 CreateMarker 1024 -229 32 CreateMarker 1058 -347 32 CreateMarker 946 -369 32 CreateMarker 921 -206 32 CreateMarker 807 -323 32 CreateMarker 856 -491 32 CreateMarker 960 -672 32 CreateMarker 793 -657 32 CreateMarker 695 -755 32 CreateMarker 682 -884 32 CreateMarker 590 -710 32 CreateMarker 566 -867 36 CreateMarker 440 -850 56 CreateMarker 343 -853 104 CreateMarker 283 -839 112 CreateMarker 211 -723 152 CreateMarker 213 -625 184 CreateMarker 73 -591 184 CreateMarker 75 -490 184 CreateMarker -62 -500 208 CreateMarker -63 -615 208 CreateMarker -199 -593 216 CreateMarker -190 -492 216 CreateMarker 230 -478 184 CreateMarker 287 -346 184 CreateMarker 52 -349 184 CreateMarker 193 -355 184 CreateMarker 328 -50 152 CreateMarker 312 130 136 CreateMarker 323 249 136 CreateMarker 185 168 136 CreateMarker 89 407 136 CreateMarker 59 228 136 CreateMarker 62 75 76 CreateMarker 93 -77 36 CreateMarker 57 -161 32 CreateMarker 181 -170 32 CreateMarker 200 -50 32 CreateMarker 346 -61 32 CreateMarker 348 -208 32 CreateMarker 351 -336 32 CreateMarker 496 -385 32 CreateMarker 498 -253 32 CreateMarker 496 -133 32 CreateMarker 610 -188 32 CreateMarker 724 -192 32 CreateMarker 841 -126 32 CreateMarker 843 -253 32 CreateMarker 487 488 296 CreateMarker 483 391 296 CreateMarker 522 291 296 CreateMarker 598 232 296 CreateMarker 656 416 296 CreateMarker 666 530 296 CreateMarker 666 690 296 CreateMarker 659 800 296 CreateMarker 575 472 296 CreateMarker 581 610 296 CreateMarker 752 342 296 CreateMarker 881 336 296 CreateMarker 999 340 296 CreateMarker 995 238 296 CreateMarker 974 141 300 CreateMarker 1061 91 296 CreateMarker 1039 -30 296 CreateMarker 899 10 296 CreateMarker 804 -72 296 CreateMarker 784 -195 296 CreateMarker 923 -113 296 CreateMarker 928 -237 296 CreateMarker 792 -527 184 CreateMarker 934 -557 184 CreateMarker 1044 -627 188 CreateMarker 1096 -726 184 CreateMarker 904 -695 188 CreateMarker 820 -654 184 CreateMarker 656 -609 184 CreateMarker 528 -646 184 CreateMarker 618 -499 184 CreateMarker 528 -480 184 CreateMarker 652 -414 184 CreateMarker 535 -356 188 CreateMarker 542 -211 184 CreateMarker 656 -137 184 CreateMarker 558 -112 184 CreateMarker 489 -69 184 CreateMarker 656 11 200 CreateMarker 656 129 264 CreateMarker 563 168 280 CreateMarker 552 35 216 CreateMarker 253 128 312 CreateMarker 52 128 312 CreateMarker -69 128 312 CreateMarker -198 125 312 CreateMarker -276 14 312 CreateMarker -284 -175 312 CreateMarker -416 -194 312 CreateMarker -416 -457 216 CreateMarker -416 -624 216 CreateMarker -103 -231 312 CreateMarker -36 24 312 CreateMarker -86 -165 32 CreateMarker -182 -32 32 CreateMarker -230 -209 32 CreateMarker -393 -220 32 CreateMarker -321 -153 32 CreateMarker -288 -269 32 CreateMarker 813 -842 188 CreateMarker 907 -874 184 CreateMarker 1024 384 88 CreateMarker 376 126 312 SetGoal 1 1 SetZone 1 6 SetMarkerPath 1 0 134 SetMarkerPath 1 1 135 SetMarkerPath 1 2 35 SetMarkerPath 1 3 170 SetMarkerPath 1 4 136 SetMarkerPath 1 5 133 SetGoal 2 15 SetZone 2 13 SetMarkerPath 2 0 68 SetMarkerPath 2 1 67 SetMarkerPath 2 2 69 SetMarkerPath 2 3 70 SetMarkerPath 2 4 71 SetMarkerPath 2 5 32 SetGoal 3 19 SetZone 3 5 SetMarkerPath 3 0 60 SetMarkerPath 3 1 61 SetGoal 4 16 SetZone 4 5 SetMarkerPath 4 0 5 SetMarkerPath 4 1 62 SetMarkerPath 4 2 65 SetMarkerPath 4 3 108 SetGoal 5 16 SetZone 5 5 SetMarkerPath 5 0 6 SetMarkerPath 5 1 4 SetMarkerPath 5 2 108 SetMarkerPath 5 3 65 SetMarkerPath 5 4 60 SetGoal 6 16 SetZone 6 5 SetMarkerPath 6 0 61 SetMarkerPath 6 1 5 SetGoal 7 23 SetZone 7 14 SetMarkerPath 7 0 36 SetMarkerPath 7 1 156 SetMarkerPath 7 2 155 SetMarkerPath 7 3 162 SetMarkerPath 7 4 154 SetMarkerPath 7 5 161 SetMarkerPath 7 6 157 SetGoal 8 20 SetZone 8 12 SetMarkerPath 8 0 87 SetGoal 9 17 SetZone 9 15 SetMarkerPath 9 0 172 SetMarkerPath 9 1 19 SetMarkerPath 9 2 89 SetMarkerPath 9 3 147 SetGoal 10 2 SetZone 10 15 SetMarkerPath 10 0 9 SetMarkerPath 10 1 172 SetGoal 11 18 SetZone 11 12 SetMarkerPath 11 0 12 SetMarkerPath 11 1 76 SetGoal 12 16 SetZone 12 12 SetMarkerPath 12 0 11 SetMarkerPath 12 1 76 SetMarkerPath 12 2 77 SetGoal 13 3 SetZone 13 11 SetMarkerPath 13 1 159 SetMarkerPath 13 2 160 SetMarkerPath 13 3 83 SetMarkerPath 13 4 84 SetGoal 14 16 SetZone 14 10 SetMarkerPath 14 0 15 SetMarkerPath 14 1 167 SetMarkerPath 14 2 166 SetGoal 15 18 SetZone 15 10 SetMarkerPath 15 0 163 SetMarkerPath 15 1 165 SetMarkerPath 15 2 164 SetMarkerPath 15 3 167 SetMarkerPath 15 4 14 SetGoal 16 21 SetZone 16 9 SetMarkerPath 16 0 102 SetMarkerPath 16 1 34 SetMarkerPath 16 2 97 SetMarkerPath 16 3 98 SetMarkerPath 16 4 101 SetGoal 17 16 SetZone 17 8 SetMarkerPath 17 0 93 SetMarkerPath 17 1 38 SetMarkerPath 17 2 18 SetMarkerPath 17 3 91 SetMarkerPath 17 4 92 SetGoal 18 15 SetZone 18 8 SetMarkerPath 18 0 93 SetMarkerPath 18 1 38 SetMarkerPath 18 2 17 SetMarkerPath 18 3 91 SetMarkerPath 18 4 90 SetMarkerPath 18 5 94 SetMarkerPath 18 6 92 SetGoal 19 4 SetZone 19 8 SetMarkerPath 19 0 90 SetMarkerPath 19 1 92 SetMarkerPath 19 2 95 SetMarkerPath 19 3 96 SetMarkerPath 19 4 99 SetMarkerPath 19 5 89 SetMarkerPath 19 6 98 SetGoal 20 19 SetZone 20 7 SetMarkerPath 20 0 21 SetMarkerPath 20 1 142 SetMarkerPath 20 2 143 SetMarkerPath 20 3 144 SetMarkerPath 20 4 102 SetMarkerPath 20 5 42 SetGoal 21 23 SetZone 21 7 SetMarkerPath 21 0 146 SetMarkerPath 21 1 145 SetMarkerPath 21 2 20 SetMarkerPath 21 3 144 SetGoal 22 5 SetZone 22 2 SetMarkerPath 22 0 129 SetMarkerPath 22 1 131 SetMarkerPath 22 2 130 SetMarkerPath 22 3 126 SetGoal 23 16 SetZone 23 1 SetMarkerPath 23 0 120 SetMarkerPath 23 1 24 SetMarkerPath 23 2 121 SetMarkerPath 23 3 122 SetMarkerPath 23 4 123 SetGoal 24 16 SetZone 24 1 SetMarkerPath 24 0 25 SetMarkerPath 24 1 120 SetMarkerPath 24 2 121 SetMarkerPath 24 3 23 SetGoal 25 16 SetZone 25 1 SetMarkerPath 25 0 113 SetMarkerPath 25 1 112 SetMarkerPath 25 2 111 SetMarkerPath 25 3 114 SetMarkerPath 25 4 120 SetMarkerPath 25 5 24 SetGoal 26 18 SetZone 26 1 SetMarkerPath 26 0 110 SetMarkerPath 26 1 27 SetMarkerPath 26 2 119 SetMarkerPath 26 3 115 SetMarkerPath 26 4 118 SetGoal 27 24 SetZone 27 1 SetMarkerPath 27 0 26 SetMarkerPath 27 1 28 SetMarkerPath 27 2 119 SetGoal 28 23 SetZone 28 1 SetMarkerPath 28 0 27 SetMarkerPath 28 1 37 SetMarkerPath 28 2 43 SetMarkerPath 28 3 119 SetGoal 29 22 SetZone 29 3 SetMarkerPath 29 0 46 SetMarkerPath 29 1 47 SetMarkerPath 29 2 53 SetGoal 30 6 SetZone 30 4 SetMarkerPath 30 0 171 SetMarkerPath 30 1 58 SetMarkerPath 30 2 52 SetMarkerPath 30 3 51 SetMarkerPath 30 4 59 SetGoal 31 7 SetZone 31 4 SetMarkerPath 31 0 58 SetMarkerPath 31 1 57 SetMarkerPath 31 2 56 SetMarkerPath 31 3 54 SetMarkerPath 31 4 55 SetMarkerPath 31 5 52 SetZone 32 13 SetMarkerPath 32 0 68 SetMarkerPath 32 1 2 SetZone 33 2 SetMarkerPath 33 0 128 SetMarkerPath 33 1 127 SetMarkerPath 33 2 125 SetZone 34 9 SetMarkerPath 34 0 16 SetMarkerPath 34 1 97 SetMarkerPath 34 2 98 SetZone 35 6 SetMarkerPath 35 0 135 SetMarkerPath 35 1 1 SetMarkerPath 35 2 170 SetZone 36 14 SetMarkerPath 36 0 158 SetMarkerPath 36 1 157 SetMarkerPath 36 2 7 SetMarkerPath 36 3 156 SetMarkerPath 36 4 41 SetZone 37 1 SetMarkerPath 37 0 28 SetMarkerPath 37 1 43 SetMarkerPath 37 2 117 SetMarkerPath 37 3 44 SetZone 38 8 SetMarkerPath 38 0 93 SetMarkerPath 38 1 17 SetMarkerPath 38 2 18 SetZone 39 10 SetMarkerPath 39 0 13 SetZone 40 5 SetMarkerPath 40 0 134 SetZone 41 14 SetMarkerPath 41 0 36 SetMarkerPath 41 1 156 SetMarkerPath 41 2 155 SetZone 42 14 SetMarkerPath 42 0 41 SetZone 43 1 SetMarkerPath 43 0 28 SetMarkerPath 43 1 37 SetMarkerPath 43 2 44 SetMarkerPath 43 3 116 SetMarkerPath 43 4 117 SetMarkerPath 43 5 119 SetZone 44 1 SetMarkerPath 44 0 37 SetMarkerPath 44 1 117 SetMarkerPath 44 2 43 SetMarkerPath 44 3 45 SetZone 45 3 SetMarkerPath 45 0 44 SetMarkerPath 45 1 117 SetMarkerPath 45 2 46 SetMarkerPath 45 3 54 SetMarkerPath 45 4 52 SetMarkerPath 45 5 53 SetZone 46 3 SetMarkerPath 46 0 45 SetMarkerPath 46 1 29 SetMarkerPath 46 2 48 SetMarkerPath 46 3 53 SetMarkerPath 46 4 54 SetZone 47 3 SetMarkerPath 47 0 29 SetMarkerPath 47 1 53 SetMarkerPath 47 2 48 SetZone 48 3 SetMarkerPath 48 0 47 SetMarkerPath 48 1 49 SetMarkerPath 48 2 53 SetZone 49 3 SetMarkerPath 49 0 48 SetMarkerPath 49 1 50 SetMarkerPath 49 2 52 SetMarkerPath 49 3 53 SetMarkerPath 49 4 54 SetZone 50 4 SetMarkerPath 50 0 49 SetMarkerPath 50 1 51 SetMarkerPath 50 2 52 SetMarkerPath 50 3 171 SetZone 51 4 SetMarkerPath 51 0 50 SetMarkerPath 51 1 171 SetMarkerPath 51 2 30 SetMarkerPath 51 3 53 SetMarkerPath 51 4 52 SetMarkerPath 51 5 119 SetMarkerPathFlags 51 5 r SetRocketJumpPathFields 51 5 80.0 328.0 0 SetZone 52 4 SetMarkerPath 52 0 50 SetMarkerPath 52 1 30 SetMarkerPath 52 2 58 SetMarkerPath 52 3 53 SetMarkerPath 52 4 51 SetMarkerPath 52 5 54 SetMarkerPath 52 6 31 SetZone 53 4 SetMarkerPath 53 0 54 SetMarkerPath 53 1 52 SetMarkerPath 53 2 55 SetMarkerPath 53 3 51 SetZone 54 4 SetMarkerPath 54 0 58 SetMarkerPath 54 1 57 SetMarkerPath 54 2 31 SetMarkerPath 54 3 56 SetMarkerPath 54 4 53 SetMarkerPath 54 5 55 SetMarkerPath 54 6 52 SetZone 55 4 SetMarkerPath 55 0 56 SetMarkerPath 55 1 53 SetMarkerPath 55 2 54 SetMarkerPath 55 3 31 SetZone 56 4 SetMarkerPath 56 0 31 SetMarkerPath 56 1 55 SetMarkerPath 56 2 54 SetZone 57 4 SetMarkerPath 57 0 58 SetMarkerPath 57 1 31 SetMarkerPath 57 2 54 SetZone 58 4 SetMarkerPath 58 0 30 SetMarkerPath 58 1 57 SetMarkerPath 58 2 31 SetMarkerPath 58 3 54 SetMarkerPath 58 4 52 SetZone 59 4 SetMarkerPath 59 0 30 SetMarkerPath 59 1 60 SetZone 60 5 SetMarkerPath 60 0 59 SetMarkerPath 60 1 61 SetMarkerPath 60 2 3 SetMarkerPath 60 3 5 SetZone 61 5 SetMarkerPath 61 0 60 SetMarkerPath 61 1 3 SetMarkerPath 61 2 6 SetZone 62 5 SetMarkerPath 62 0 4 SetMarkerPath 62 1 63 SetMarkerPath 62 2 65 SetMarkerPath 62 3 64 SetMarkerPath 62 4 109 SetMarkerPath 62 5 66 SetZone 63 5 SetMarkerPath 63 0 62 SetMarkerPath 63 2 64 SetMarkerPath 63 3 65 SetZone 64 5 SetMarkerPath 64 0 62 SetMarkerPath 64 1 63 SetMarkerPath 64 2 67 SetMarkerPath 64 3 66 SetMarkerPath 64 4 109 SetMarkerPath 64 5 65 SetMarkerPath 64 6 68 SetMarkerPath 64 7 133 SetMarkerPathFlags 64 7 r SetRocketJumpPathFields 64 7 72.0 90.0 0 SetZone 65 5 SetMarkerPath 65 0 5 SetMarkerPath 65 1 4 SetMarkerPath 65 2 62 SetMarkerPath 65 3 63 SetMarkerPath 65 4 64 SetMarkerPath 65 5 109 SetMarkerPath 65 6 107 SetMarkerPath 65 7 108 SetZone 66 5 SetMarkerPath 66 0 64 SetMarkerPath 66 1 109 SetMarkerPath 66 2 67 SetMarkerPath 66 3 62 SetZone 67 13 SetMarkerPath 67 0 64 SetMarkerPath 67 1 68 SetMarkerPath 67 2 66 SetMarkerPath 67 3 2 SetMarkerPath 67 4 69 SetZone 68 13 SetMarkerPath 68 0 64 SetMarkerPath 68 1 32 SetMarkerPath 68 2 2 SetMarkerPath 68 3 69 SetMarkerPath 68 4 67 SetZone 69 13 SetMarkerPath 69 0 68 SetMarkerPath 69 1 67 SetMarkerPath 69 2 2 SetMarkerPath 69 3 70 SetZone 70 13 SetMarkerPath 70 0 2 SetMarkerPath 70 1 71 SetMarkerPath 70 2 73 SetMarkerPath 70 3 72 SetMarkerPath 70 4 69 SetZone 71 13 SetMarkerPath 71 0 2 SetMarkerPath 71 1 70 SetMarkerPath 71 2 72 SetMarkerPath 71 3 73 SetZone 72 13 SetMarkerPath 72 0 71 SetMarkerPath 72 1 73 SetMarkerPath 72 2 70 SetMarkerPath 72 3 74 SetZone 73 13 SetMarkerPath 73 0 71 SetMarkerPath 73 1 72 SetMarkerPath 73 2 70 SetMarkerPath 73 3 74 SetMarkerPath 73 4 169 SetMarkerPathFlags 73 4 r SetRocketJumpPathFields 73 4 67.0 172.0 0 SetZone 74 12 SetMarkerPath 74 0 73 SetMarkerPath 74 1 75 SetMarkerPath 74 2 72 SetZone 75 12 SetMarkerPath 75 0 74 SetMarkerPath 75 1 76 SetZone 76 12 SetMarkerPath 76 0 75 SetMarkerPath 76 1 11 SetMarkerPath 76 2 12 SetZone 77 12 SetMarkerPath 77 0 12 SetMarkerPath 77 1 78 SetZone 78 12 SetMarkerPath 78 0 77 SetMarkerPath 78 1 85 SetMarkerPath 78 2 80 SetMarkerPath 78 3 79 SetZone 79 11 SetMarkerPath 79 0 78 SetMarkerPath 79 1 80 SetMarkerPath 79 2 85 SetMarkerPath 79 3 82 SetMarkerPath 79 4 81 SetZone 80 11 SetMarkerPath 80 0 78 SetMarkerPath 80 1 79 SetMarkerPath 80 2 85 SetMarkerPath 80 3 82 SetMarkerPath 80 4 81 SetZone 81 11 SetMarkerPath 81 0 79 SetMarkerPath 81 1 80 SetMarkerPath 81 2 82 SetMarkerPath 81 3 83 SetMarkerPath 81 4 84 SetZone 82 11 SetMarkerPath 82 0 79 SetMarkerPath 82 1 80 SetMarkerPath 82 2 81 SetMarkerPath 82 3 84 SetZone 83 11 SetMarkerPath 83 0 13 SetMarkerPath 83 1 81 SetMarkerPath 83 2 84 SetZone 84 11 SetMarkerPath 84 1 13 SetMarkerPath 84 2 81 SetMarkerPath 84 3 82 SetMarkerPath 84 4 83 SetZone 85 12 SetMarkerPath 85 0 78 SetMarkerPath 85 1 79 SetMarkerPath 85 2 80 SetMarkerPath 85 3 86 SetMarkerPath 85 4 88 SetZone 86 12 SetMarkerPath 86 0 85 SetMarkerPath 86 1 88 SetMarkerPath 86 2 143 SetMarkerPath 86 3 89 SetMarkerPath 86 4 42 SetMarkerPath 86 5 102 SetMarkerPath 86 6 99 SetMarkerPath 86 7 97 SetZone 87 12 SetMarkerPath 87 0 88 SetMarkerPath 87 1 8 SetMarkerPath 87 2 97 SetMarkerPath 87 3 98 SetZone 88 12 SetMarkerPath 88 0 86 SetMarkerPath 88 1 85 SetMarkerPath 88 2 87 SetMarkerPath 88 3 98 SetMarkerPath 88 4 101 SetMarkerPath 88 5 97 SetZone 89 8 SetMarkerPath 89 0 90 SetMarkerPath 89 1 19 SetMarkerPath 89 2 101 SetMarkerPath 89 3 98 SetMarkerPath 89 4 147 SetZone 90 8 SetMarkerPath 90 0 91 SetMarkerPath 90 1 18 SetMarkerPath 90 2 92 SetMarkerPath 90 3 19 SetMarkerPath 90 4 89 SetZone 91 8 SetMarkerPath 91 0 17 SetMarkerPath 91 1 90 SetMarkerPath 91 2 92 SetMarkerPath 91 3 18 SetZone 92 8 SetMarkerPath 92 0 17 SetMarkerPath 92 1 91 SetMarkerPath 92 2 90 SetMarkerPath 92 3 19 SetMarkerPath 92 4 18 SetMarkerPath 92 5 94 SetMarkerPath 92 6 95 SetZone 93 8 SetMarkerPath 93 0 18 SetMarkerPath 93 1 94 SetMarkerPath 93 2 38 SetMarkerPath 93 3 17 SetZone 94 8 SetMarkerPath 94 0 93 SetMarkerPath 94 1 18 SetMarkerPath 94 2 92 SetMarkerPath 94 3 95 SetZone 95 9 SetMarkerPath 95 0 94 SetMarkerPath 95 1 96 SetZone 96 9 SetMarkerPath 96 0 97 SetMarkerPath 96 1 95 SetMarkerPath 96 2 99 SetMarkerPath 96 3 98 SetZone 97 9 SetMarkerPath 97 0 16 SetMarkerPath 97 1 34 SetMarkerPath 97 2 96 SetMarkerPath 97 3 99 SetMarkerPath 97 4 98 SetMarkerPath 97 5 163 SetZone 98 9 SetMarkerPath 98 0 16 SetMarkerPath 98 1 34 SetMarkerPath 98 2 97 SetMarkerPath 98 3 96 SetMarkerPath 98 4 101 SetMarkerPath 98 5 100 SetMarkerPath 98 6 102 SetMarkerPath 98 7 99 SetZone 99 9 SetMarkerPath 99 0 97 SetMarkerPath 99 1 96 SetMarkerPath 99 2 100 SetMarkerPath 99 3 98 SetZone 100 9 SetMarkerPath 100 0 98 SetMarkerPath 100 1 105 SetMarkerPath 100 2 104 SetMarkerPath 100 3 101 SetMarkerPath 100 4 99 SetZone 101 9 SetMarkerPath 101 0 102 SetMarkerPath 101 1 16 SetMarkerPath 101 2 98 SetMarkerPath 101 3 100 SetMarkerPath 101 4 105 SetMarkerPath 101 5 104 SetMarkerPath 101 6 42 SetMarkerPath 101 7 88 SetMarkerPathFlags 101 7 r SetRocketJumpPathFields 101 7 79.0 42.0 0 SetZone 102 9 SetMarkerPath 102 0 103 SetMarkerPath 102 1 104 SetMarkerPath 102 2 101 SetMarkerPath 102 3 16 SetMarkerPath 102 4 42 SetMarkerPath 102 5 98 SetZone 103 9 SetMarkerPath 103 0 104 SetMarkerPath 103 1 102 SetMarkerPath 103 2 42 SetZone 104 9 SetMarkerPath 104 0 103 SetMarkerPath 104 1 42 SetMarkerPath 104 2 102 SetMarkerPath 104 3 101 SetMarkerPath 104 4 105 SetMarkerPath 104 5 106 SetMarkerPath 104 6 100 SetZone 105 9 SetMarkerPath 105 0 106 SetMarkerPath 105 1 100 SetMarkerPath 105 2 101 SetMarkerPath 105 3 104 SetZone 106 9 SetMarkerPath 106 0 107 SetMarkerPath 106 1 105 SetMarkerPath 106 2 104 SetZone 107 5 SetMarkerPath 107 0 109 SetMarkerPath 107 1 108 SetMarkerPath 107 2 65 SetMarkerPath 107 3 106 SetZone 108 5 SetMarkerPath 108 0 5 SetMarkerPath 108 1 4 SetMarkerPath 108 2 109 SetMarkerPath 108 3 107 SetMarkerPath 108 4 65 SetZone 109 5 SetMarkerPath 109 0 62 SetMarkerPath 109 1 64 SetMarkerPath 109 2 66 SetMarkerPath 109 3 65 SetMarkerPath 109 4 108 SetMarkerPath 109 5 107 SetZone 110 1 SetMarkerPath 110 0 111 SetMarkerPath 110 1 26 SetMarkerPath 110 2 118 SetMarkerPath 110 3 119 SetZone 111 1 SetMarkerPath 111 0 112 SetMarkerPath 111 1 110 SetMarkerPath 111 2 118 SetMarkerPath 111 3 114 SetMarkerPath 111 4 25 SetMarkerPath 111 5 120 SetZone 112 1 SetMarkerPath 112 0 113 SetMarkerPath 112 1 150 SetMarkerPath 112 2 111 SetMarkerPath 112 3 25 SetZone 113 1 SetMarkerPath 113 0 149 SetMarkerPath 113 1 150 SetMarkerPath 113 2 112 SetMarkerPath 113 3 25 SetMarkerPath 113 4 120 SetMarkerPath 113 5 114 SetMarkerPath 113 6 118 SetZone 114 1 SetMarkerPath 114 0 113 SetMarkerPath 114 1 118 SetMarkerPath 114 2 111 SetMarkerPath 114 3 115 SetMarkerPath 114 4 120 SetMarkerPath 114 5 25 SetMarkerPath 114 6 30 SetMarkerPath 114 7 52 SetZone 115 1 SetMarkerPath 115 0 26 SetMarkerPath 115 1 116 SetMarkerPath 115 2 119 SetMarkerPath 115 3 118 SetMarkerPath 115 4 114 SetMarkerPath 115 5 52 SetMarkerPath 115 6 30 SetMarkerPath 115 7 51 SetZone 116 1 SetMarkerPath 116 0 117 SetMarkerPath 116 1 115 SetMarkerPath 116 2 119 SetMarkerPath 116 3 43 SetMarkerPath 116 4 30 SetMarkerPath 116 5 52 SetZone 117 1 SetMarkerPath 117 0 37 SetMarkerPath 117 1 44 SetMarkerPath 117 2 116 SetMarkerPath 117 3 45 SetMarkerPath 117 4 52 SetMarkerPath 117 5 43 SetZone 118 1 SetMarkerPath 118 0 113 SetMarkerPath 118 1 111 SetMarkerPath 118 2 110 SetMarkerPath 118 3 26 SetMarkerPath 118 4 115 SetMarkerPath 118 5 114 SetMarkerPath 118 6 119 SetZone 119 1 SetMarkerPath 119 0 110 SetMarkerPath 119 1 26 SetMarkerPath 119 2 27 SetMarkerPath 119 3 28 SetMarkerPath 119 4 116 SetMarkerPath 119 5 115 SetMarkerPath 119 6 43 SetMarkerPath 119 7 118 SetZone 120 1 SetMarkerPath 120 0 113 SetMarkerPath 120 1 58 SetMarkerPath 120 2 111 SetMarkerPath 120 3 114 SetMarkerPath 120 4 25 SetMarkerPath 120 5 121 SetMarkerPath 120 6 23 SetMarkerPath 120 7 54 SetZone 121 1 SetMarkerPath 121 0 120 SetMarkerPath 121 1 24 SetMarkerPath 121 2 23 SetMarkerPath 121 3 122 SetMarkerPath 121 4 123 SetMarkerPath 121 5 58 SetMarkerPath 121 6 52 SetMarkerPath 121 7 51 SetZone 122 1 SetMarkerPath 122 0 121 SetMarkerPath 122 1 123 SetMarkerPath 122 2 23 SetMarkerPath 122 3 50 SetMarkerPath 122 4 52 SetMarkerPath 122 5 58 SetZone 123 1 SetMarkerPath 123 0 121 SetMarkerPath 123 1 122 SetMarkerPath 123 2 125 SetMarkerPath 123 3 23 SetMarkerPath 123 4 124 SetZone 124 2 SetMarkerPath 124 0 126 SetMarkerPath 124 1 125 SetMarkerPath 124 2 123 SetZone 125 2 SetMarkerPath 125 0 127 SetMarkerPath 125 1 33 SetMarkerPath 125 2 126 SetMarkerPath 125 3 124 SetMarkerPath 125 4 123 SetZone 126 2 SetMarkerPath 126 0 22 SetMarkerPath 126 1 130 SetMarkerPath 126 2 127 SetMarkerPath 126 3 124 SetMarkerPath 126 4 125 SetZone 127 2 SetMarkerPath 127 0 130 SetMarkerPath 127 1 128 SetMarkerPath 127 2 126 SetMarkerPath 127 3 125 SetMarkerPath 127 4 33 SetZone 128 2 SetMarkerPath 128 0 129 SetMarkerPath 128 1 130 SetMarkerPath 128 2 33 SetMarkerPath 128 3 127 SetMarkerPath 128 4 131 SetZone 129 2 SetMarkerPath 129 1 128 SetMarkerPath 129 2 130 SetMarkerPath 129 3 131 SetMarkerPath 129 4 22 SetZone 130 2 SetMarkerPath 130 0 129 SetMarkerPath 130 1 22 SetMarkerPath 130 2 131 SetMarkerPath 130 3 126 SetMarkerPath 130 4 127 SetMarkerPath 130 5 128 SetZone 131 2 SetMarkerPath 131 0 129 SetMarkerPath 131 1 22 SetMarkerPath 131 2 130 SetMarkerPath 131 3 128 SetMarkerPath 131 4 66 SetMarkerPath 131 5 133 SetZone 132 6 SetMarkerPath 132 0 133 SetMarkerPath 132 1 137 SetMarkerPath 132 2 138 SetMarkerPath 132 3 64 SetMarkerPath 132 5 136 SetZone 133 6 SetMarkerPath 133 0 134 SetMarkerPath 133 1 1 SetMarkerPath 133 2 136 SetMarkerPath 133 3 137 SetMarkerPath 133 4 132 SetMarkerPath 133 5 130 SetMarkerPathFlags 133 5 r SetRocketJumpPathFields 133 5 57.0 277.0 0 SetZone 134 6 SetMarkerPath 134 0 135 SetMarkerPath 134 1 1 SetMarkerPath 134 2 136 SetMarkerPath 134 3 133 SetZone 135 6 SetMarkerPath 135 0 134 SetMarkerPath 135 1 35 SetMarkerPath 135 2 1 SetZone 136 6 SetMarkerPath 136 0 134 SetMarkerPath 136 1 1 SetMarkerPath 136 2 170 SetMarkerPath 136 3 133 SetMarkerPath 136 4 132 SetZone 137 6 SetMarkerPath 137 0 133 SetMarkerPath 137 1 132 SetMarkerPath 137 2 138 SetZone 138 6 SetMarkerPath 138 0 137 SetMarkerPath 138 1 139 SetMarkerPath 138 2 141 SetMarkerPath 138 3 140 SetMarkerPath 138 4 132 SetMarkerPath 138 5 71 SetMarkerPath 138 6 73 SetZone 139 6 SetMarkerPath 139 0 138 SetMarkerPath 139 1 141 SetMarkerPath 139 2 140 SetZone 140 7 SetMarkerPath 140 0 138 SetMarkerPath 140 1 143 SetMarkerPath 140 2 141 SetMarkerPath 140 3 139 SetMarkerPath 140 4 142 SetZone 141 7 SetMarkerPath 141 0 138 SetMarkerPath 141 1 143 SetMarkerPath 141 2 140 SetMarkerPath 141 3 142 SetMarkerPath 141 4 139 SetZone 142 7 SetMarkerPath 142 0 20 SetMarkerPath 142 1 143 SetMarkerPath 142 2 141 SetMarkerPath 142 3 140 SetZone 143 7 SetMarkerPath 143 0 20 SetMarkerPath 143 1 86 SetMarkerPath 143 2 144 SetMarkerPath 143 3 142 SetMarkerPath 143 4 140 SetMarkerPath 143 5 141 SetMarkerPath 143 6 42 SetZone 144 7 SetMarkerPath 144 0 146 SetMarkerPath 144 1 145 SetMarkerPath 144 2 21 SetMarkerPath 144 3 20 SetMarkerPath 144 4 101 SetMarkerPath 144 5 143 SetMarkerPath 144 6 102 SetMarkerPath 144 7 42 SetZone 145 7 SetMarkerPath 145 0 146 SetMarkerPath 145 1 148 SetMarkerPath 145 2 21 SetMarkerPath 145 3 144 SetZone 146 7 SetMarkerPath 146 0 147 SetMarkerPath 146 1 144 SetMarkerPath 146 2 21 SetMarkerPath 146 3 145 SetMarkerPath 146 4 148 SetMarkerPath 146 5 151 SetMarkerPath 146 6 102 SetMarkerPath 146 7 79 SetMarkerPathFlags 146 7 r SetRocketJumpPathFields 146 7 40.0 47.0 0 SetZone 147 8 SetMarkerPath 147 0 89 SetMarkerPath 147 1 146 SetMarkerPath 147 2 101 SetZone 148 7 SetMarkerPath 148 0 146 SetMarkerPath 148 1 145 SetMarkerPath 148 2 151 SetMarkerPath 148 3 149 SetMarkerPath 148 4 150 SetZone 149 7 SetMarkerPath 149 0 148 SetMarkerPath 149 1 151 SetMarkerPath 149 2 150 SetMarkerPath 149 3 113 SetZone 150 7 SetMarkerPath 150 0 149 SetMarkerPath 150 1 113 SetMarkerPath 150 2 112 SetMarkerPath 150 3 151 SetMarkerPath 150 4 148 SetZone 151 7 SetMarkerPath 151 0 148 SetMarkerPath 151 1 149 SetMarkerPath 151 2 150 SetMarkerPath 151 3 146 SetZone 152 15 SetMarkerPath 152 0 153 SetMarkerPath 152 1 172 SetMarkerPath 152 2 19 SetMarkerPath 152 3 89 SetZone 153 15 SetMarkerPath 153 0 154 SetMarkerPath 153 1 152 SetMarkerPath 153 2 19 SetMarkerPath 153 3 96 SetZone 154 14 SetMarkerPath 154 0 156 SetMarkerPath 154 1 155 SetMarkerPath 154 2 7 SetMarkerPath 154 3 162 SetMarkerPath 154 4 153 SetMarkerPath 154 5 19 SetZone 155 14 SetMarkerPath 155 0 41 SetMarkerPath 155 1 156 SetMarkerPath 155 2 154 SetMarkerPath 155 3 162 SetMarkerPath 155 4 7 SetZone 156 14 SetMarkerPath 156 0 36 SetMarkerPath 156 1 41 SetMarkerPath 156 2 155 SetMarkerPath 156 3 154 SetMarkerPath 156 4 162 SetMarkerPath 156 5 7 SetMarkerPath 156 6 157 SetZone 157 14 SetMarkerPath 157 0 158 SetMarkerPath 157 1 36 SetMarkerPath 157 2 156 SetMarkerPath 157 3 7 SetMarkerPath 157 4 13 SetZone 158 14 SetMarkerPath 158 0 159 SetMarkerPath 158 1 36 SetMarkerPath 158 2 157 SetZone 159 11 SetMarkerPath 159 0 158 SetMarkerPath 159 1 13 SetMarkerPath 159 2 160 SetZone 160 11 SetMarkerPath 160 0 159 SetMarkerPath 160 1 13 SetZone 161 14 SetMarkerPath 161 0 7 SetMarkerPath 161 1 8 SetZone 162 14 SetMarkerPath 162 0 156 SetMarkerPath 162 1 155 SetMarkerPath 162 2 7 SetMarkerPath 162 3 154 SetMarkerPath 162 4 19 SetZone 163 10 SetMarkerPath 163 0 97 SetMarkerPath 163 1 164 SetMarkerPath 163 2 15 SetMarkerPath 163 3 167 SetMarkerPath 163 4 165 SetZone 164 10 SetMarkerPath 164 0 163 SetMarkerPath 164 1 165 SetMarkerPath 164 2 15 SetMarkerPath 164 3 167 SetZone 165 10 SetMarkerPath 165 0 163 SetMarkerPath 165 1 168 SetMarkerPath 165 2 167 SetMarkerPath 165 3 15 SetMarkerPath 165 4 164 SetMarkerPath 165 5 166 SetZone 166 10 SetMarkerPath 166 0 14 SetMarkerPath 166 1 167 SetMarkerPath 166 2 168 SetMarkerPath 166 4 165 SetZone 167 10 SetMarkerPath 167 0 163 SetMarkerPath 167 1 165 SetMarkerPath 167 2 164 SetMarkerPath 167 3 15 SetMarkerPath 167 4 14 SetMarkerPath 167 5 166 SetMarkerPath 167 6 168 SetZone 168 10 SetMarkerPath 168 0 165 SetMarkerPath 168 1 167 SetMarkerPath 168 2 166 SetZone 169 6 SetMarkerPath 169 0 170 SetMarkerPath 169 1 139 SetMarkerPath 169 3 70 SetZone 170 6 SetMarkerPath 170 0 35 SetMarkerPath 170 1 169 SetMarkerPath 170 2 1 SetMarkerPath 170 3 136 SetZone 171 4 SetMarkerPath 171 0 51 SetMarkerPath 171 1 50 SetMarkerPath 171 2 30 SetZone 172 15 SetMarkerPath 172 0 152 SetMarkerPath 172 1 9 SetMarkerPath 172 2 10 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/nacmidair.bot000066400000000000000000000044061475442401000267010ustar00rootroot00000000000000CreateMarker 320 -320 24 CreateMarker -64 -320 24 CreateMarker -64 64 24 CreateMarker 320 64 24 CreateMarker 118 63 24 CreateMarker 320 -140 24 CreateMarker 119 -320 24 CreateMarker -64 -134 24 CreateMarker 67 -69 24 CreateMarker 54 -203 24 CreateMarker 204 -203 24 CreateMarker 204 -63 24 CreateMarker 144 -140 24 SetZone 1 2 SetMarkerPath 1 0 7 SetMarkerPath 1 1 9 SetMarkerPath 1 2 8 SetMarkerPath 1 3 10 SetMarkerPath 1 4 15 SetZone 2 2 SetMarkerPath 2 0 11 SetMarkerPath 2 1 6 SetMarkerPath 2 2 12 SetMarkerPath 2 3 7 SetMarkerPath 2 4 9 SetZone 3 2 SetMarkerPath 3 0 8 SetMarkerPath 3 1 5 SetMarkerPath 3 2 11 SetMarkerPath 3 3 6 SetMarkerPath 3 4 12 SetZone 4 2 SetMarkerPath 4 0 10 SetMarkerPath 4 1 11 SetMarkerPath 4 2 16 SetMarkerPath 4 3 9 SetMarkerPath 4 4 6 SetZone 5 1 SetMarkerPath 5 0 11 SetMarkerPath 5 1 15 SetMarkerPath 5 2 10 SetZone 6 1 SetMarkerPath 6 0 12 SetMarkerPath 6 1 14 SetMarkerPath 6 2 11 SetZone 7 1 SetMarkerPath 7 0 9 SetMarkerPath 7 1 13 SetMarkerPath 7 2 12 SetZone 8 1 SetMarkerPath 8 0 10 SetMarkerPath 8 1 16 SetMarkerPath 8 2 9 SetZone 9 1 SetMarkerPath 9 0 8 SetMarkerPath 9 1 16 SetMarkerPath 9 2 17 SetMarkerPath 9 3 13 SetMarkerPath 9 4 7 SetZone 10 1 SetMarkerPath 10 0 5 SetMarkerPath 10 1 15 SetMarkerPath 10 2 17 SetMarkerPath 10 3 16 SetMarkerPath 10 4 8 SetZone 11 1 SetMarkerPath 11 0 5 SetMarkerPath 11 1 6 SetMarkerPath 11 2 14 SetMarkerPath 11 3 17 SetMarkerPath 11 4 15 SetZone 12 1 SetMarkerPath 12 0 7 SetMarkerPath 12 1 13 SetMarkerPath 12 2 17 SetMarkerPath 12 3 14 SetMarkerPath 12 4 6 SetZone 13 1 SetMarkerPath 13 0 9 SetMarkerPath 13 1 7 SetMarkerPath 13 2 12 SetMarkerPath 13 3 14 SetMarkerPath 13 4 17 SetMarkerPath 13 5 16 SetZone 14 1 SetMarkerPath 14 0 12 SetMarkerPath 14 1 6 SetMarkerPath 14 2 11 SetMarkerPath 14 3 15 SetMarkerPath 14 4 13 SetMarkerPath 14 5 17 SetZone 15 1 SetMarkerPath 15 0 5 SetMarkerPath 15 1 10 SetMarkerPath 15 2 11 SetMarkerPath 15 3 16 SetMarkerPath 15 4 17 SetMarkerPath 15 5 14 SetZone 16 1 SetMarkerPath 16 0 10 SetMarkerPath 16 1 8 SetMarkerPath 16 2 9 SetMarkerPath 16 3 15 SetMarkerPath 16 4 13 SetMarkerPath 16 5 17 SetZone 17 1 SetMarkerPath 17 0 10 SetMarkerPath 17 1 9 SetMarkerPath 17 2 12 SetMarkerPath 17 3 11 SetMarkerPath 17 4 15 SetMarkerPath 17 5 14 SetMarkerPath 17 6 13 SetMarkerPath 17 7 16 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/noentry.bot000066400000000000000000000073061475442401000264520ustar00rootroot00000000000000CreateMarker 306 -444 88 CreateMarker 315 -262 152 CreateMarker 311 -136 152 CreateMarker 319 20 152 CreateMarker 281 181 88 CreateMarker 83 201 24 CreateMarker -119 192 40 CreateMarker -289 197 88 CreateMarker -315 23 152 CreateMarker -328 -116 152 CreateMarker -301 -278 152 CreateMarker -319 -465 88 CreateMarker -105 -440 24 CreateMarker 108 -438 24 CreateMarker 108 -234 24 CreateMarker 116 -11 24 CreateMarker -107 -18 24 CreateMarker -115 -241 24 CreateMarker -3 -367 24 CreateMarker 7 95 24 CreateMarker 178 -126 24 CreateMarker -183 -127 24 SetZone 1 1 SetMarkerPath 1 0 24 SetMarkerPath 1 1 28 SetMarkerPath 1 2 25 SetGoal 2 1 SetZone 2 1 SetMarkerPath 2 0 26 SetMarkerPath 2 1 22 SetMarkerPath 2 2 27 SetMarkerPath 2 3 24 SetMarkerPath 2 4 23 SetMarkerPath 2 5 25 SetMarkerPath 2 6 21 SetMarkerPath 2 7 28 SetZone 3 1 SetMarkerPath 3 0 28 SetMarkerPath 3 1 23 SetMarkerPath 3 2 26 SetZone 4 1 SetMarkerPath 4 0 22 SetMarkerPath 4 1 26 SetMarkerPath 4 2 27 SetZone 5 1 SetMarkerPath 5 0 25 SetMarkerPath 5 1 21 SetMarkerPath 5 2 27 SetZone 7 2 SetMarkerPath 7 0 8 SetMarkerPath 7 1 20 SetMarkerPath 7 2 21 SetMarkerPath 7 3 5 SetZone 8 2 SetMarkerPath 8 0 9 SetMarkerPath 8 1 7 SetMarkerPath 8 2 25 SetMarkerPath 8 3 2 SetMarkerPath 8 4 22 SetZone 9 2 SetMarkerPath 9 0 10 SetMarkerPath 9 1 8 SetMarkerPath 9 2 21 SetMarkerPath 9 3 2 SetMarkerPath 9 4 22 SetZone 10 2 SetMarkerPath 10 0 11 SetMarkerPath 10 1 9 SetMarkerPath 10 2 26 SetMarkerPath 10 3 2 SetMarkerPath 10 4 21 SetZone 11 2 SetMarkerPath 11 0 12 SetMarkerPath 11 1 4 SetMarkerPath 11 2 10 SetMarkerPath 11 3 26 SetZone 12 1 SetMarkerPath 12 0 26 SetMarkerPath 12 1 4 SetMarkerPath 12 2 22 SetMarkerPath 12 3 13 SetMarkerPath 12 4 11 SetZone 13 1 SetMarkerPath 13 0 14 SetMarkerPath 13 1 26 SetMarkerPath 13 2 12 SetMarkerPath 13 3 23 SetZone 14 3 SetMarkerPath 14 0 3 SetMarkerPath 14 1 15 SetMarkerPath 14 2 13 SetZone 15 3 SetMarkerPath 15 0 14 SetMarkerPath 15 1 16 SetMarkerPath 15 2 26 SetMarkerPath 15 3 23 SetMarkerPath 15 4 2 SetZone 16 3 SetMarkerPath 16 0 17 SetMarkerPath 16 1 15 SetMarkerPath 16 2 23 SetMarkerPath 16 3 2 SetMarkerPath 16 4 24 SetZone 17 3 SetMarkerPath 17 0 18 SetMarkerPath 17 1 16 SetMarkerPath 17 2 23 SetMarkerPath 17 3 2 SetMarkerPath 17 4 25 SetZone 18 3 SetMarkerPath 18 0 19 SetMarkerPath 18 1 17 SetMarkerPath 18 2 1 SetMarkerPath 18 3 25 SetZone 19 1 SetMarkerPath 19 0 20 SetMarkerPath 19 1 18 SetMarkerPath 19 2 24 SetMarkerPath 19 3 25 SetZone 20 1 SetMarkerPath 20 0 7 SetMarkerPath 20 1 19 SetMarkerPath 20 2 25 SetMarkerPath 20 3 21 SetZone 21 1 SetMarkerPath 21 0 5 SetMarkerPath 21 1 20 SetMarkerPath 21 2 22 SetMarkerPath 21 3 27 SetMarkerPath 21 4 24 SetMarkerPath 21 5 2 SetMarkerPath 21 6 25 SetZone 22 1 SetMarkerPath 22 0 4 SetMarkerPath 22 1 26 SetMarkerPath 22 2 12 SetMarkerPath 22 3 27 SetMarkerPath 22 4 2 SetMarkerPath 22 5 23 SetMarkerPath 22 6 21 SetZone 23 1 SetMarkerPath 23 0 3 SetMarkerPath 23 1 26 SetMarkerPath 23 2 22 SetMarkerPath 23 3 2 SetMarkerPath 23 4 28 SetMarkerPath 23 5 24 SetMarkerPath 23 6 13 SetZone 24 1 SetMarkerPath 24 0 1 SetMarkerPath 24 1 19 SetMarkerPath 24 2 2 SetMarkerPath 24 3 28 SetMarkerPath 24 4 21 SetMarkerPath 24 5 25 SetMarkerPath 24 6 23 SetZone 25 1 SetMarkerPath 25 0 5 SetMarkerPath 25 1 1 SetMarkerPath 25 2 20 SetMarkerPath 25 3 19 SetMarkerPath 25 4 24 SetMarkerPath 25 5 2 SetMarkerPath 25 6 21 SetZone 26 1 SetMarkerPath 26 0 4 SetMarkerPath 26 1 3 SetMarkerPath 26 2 22 SetMarkerPath 26 3 2 SetMarkerPath 26 4 23 SetMarkerPath 26 5 13 SetMarkerPath 26 6 12 SetZone 27 1 SetMarkerPath 27 0 4 SetMarkerPath 27 1 5 SetMarkerPath 27 2 22 SetMarkerPath 27 3 21 SetMarkerPath 27 4 2 SetZone 28 1 SetMarkerPath 28 0 1 SetMarkerPath 28 1 3 SetMarkerPath 28 2 24 SetMarkerPath 28 3 23 SetMarkerPath 28 4 2 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/oldcrat.bot000066400000000000000000000243641475442401000264070ustar00rootroot00000000000000CreateMarker -122 -264 -136 CreateMarker -180 -175 -136 CreateMarker -275 -58 -168 CreateMarker -304 55 -168 CreateMarker -271 189 -200 CreateMarker -149 255 -200 CreateMarker 261 52 -200 CreateMarker 226 -132 -200 CreateMarker 358 -157 -200 CreateMarker 144 -255 -168 CreateMarker 26 -291 -168 CreateMarker 181 275 -168 CreateMarker 22 361 -136 CreateMarker -574 113 -104 CreateMarker -439 370 -104 CreateMarker -333 473 -104 CreateMarker -47 576 -104 CreateMarker 124 575 -104 CreateMarker 341 473 -104 CreateMarker 459 340 -104 CreateMarker 463 -351 -104 CreateMarker 575 -125 -104 CreateMarker 372 -440 -104 CreateMarker -380 -434 -104 CreateMarker -526 -287 -104 CreateMarker -557 -115 -104 CreateMarker -365 177 -264 CreateMarker 392 21 -264 CreateMarker -16 -138 -232 CreateMarker -118 -44 -232 CreateMarker -94 94 -232 CreateMarker 41 139 -232 CreateMarker 119 42 -232 CreateMarker 91 -80 -232 CreateMarker -192 -412 -360 CreateMarker -238 -368 -312 CreateMarker -372 -248 -269 CreateMarker -387 -167 -212 CreateMarker -376 -57 -168 CreateMarker -293 -407 -360 CreateMarker -368 -330 -360 CreateMarker -466 -185 -360 CreateMarker -503 -34 -360 CreateMarker -488 119 -360 CreateMarker -403 300 -360 CreateMarker -246 426 -360 CreateMarker -100 484 -360 CreateMarker 78 470 -360 CreateMarker 204 443 -360 CreateMarker 322 330 -360 CreateMarker 456 219 -360 CreateMarker 508 58 -360 CreateMarker 486 -85 -360 CreateMarker 437 -227 -360 CreateMarker 330 -316 -360 CreateMarker 200 -429 -360 CreateMarker 68 -507 -360 CreateMarker -101 -473 -360 CreateMarker -57 -351 -360 CreateMarker -41 -208 -360 CreateMarker 121 -171 -360 CreateMarker 230 -236 -360 CreateMarker 215 -35 -360 CreateMarker 199 135 -360 CreateMarker 42 230 -360 CreateMarker 100 339 -360 CreateMarker -105 322 -360 CreateMarker -111 173 -360 CreateMarker -221 122 -360 CreateMarker -205 -78 -360 CreateMarker -306 -163 -360 CreateMarker -122 -143 -360 CreateMarker 576 131 -104 SetGoal 1 1 SetZone 1 1 SetMarkerPath 1 1 9 SetZone 2 7 SetMarkerPath 2 1 37 SetMarkerPath 2 2 13 SetZone 3 9 SetMarkerPath 3 1 34 SetMarkerPath 3 2 10 SetMarkerPath 3 3 87 SetZone 4 9 SetMarkerPath 4 1 29 SetMarkerPath 4 2 28 SetZone 5 9 SetMarkerPath 5 1 31 SetMarkerPath 5 2 30 SetZone 6 9 SetMarkerPath 6 1 33 SetMarkerPath 6 2 32 SetZone 7 7 SetMarkerPath 7 1 36 SetMarkerPath 7 2 35 SetMarkerPath 7 3 23 SetZone 8 8 SetMarkerPath 8 1 38 SetZone 9 1 SetMarkerPath 9 1 47 SetMarkerPath 9 2 48 SetMarkerPath 9 3 43 SetMarkerPath 9 4 44 SetMarkerPath 9 5 45 SetMarkerPath 9 6 46 SetMarkerPath 9 7 1 SetZone 10 9 SetMarkerPath 10 1 21 SetMarkerPath 10 2 26 SetZone 11 8 SetMarkerPath 11 1 38 SetMarkerPath 11 2 15 SetMarkerPath 11 3 16 SetZone 12 9 SetMarkerPath 12 1 19 SetMarkerPath 12 2 20 SetZone 13 7 SetMarkerPath 13 0 23 SetMarkerPath 13 1 24 SetMarkerPath 13 2 25 SetZone 15 8 SetMarkerPath 15 1 11 SetMarkerPath 15 2 16 SetMarkerPath 15 3 25 SetZone 16 8 SetMarkerPath 16 1 15 SetMarkerPath 16 2 11 SetMarkerPath 16 3 17 SetMarkerPath 16 4 44 SetMarkerPath 16 5 43 SetZone 17 8 SetMarkerPath 17 1 16 SetMarkerPath 17 2 53 SetMarkerPath 17 3 18 SetMarkerPath 17 4 44 SetZone 18 8 SetMarkerPath 18 1 53 SetMarkerPath 18 2 17 SetMarkerPath 18 3 19 SetZone 19 9 SetMarkerPath 19 1 18 SetMarkerPath 19 2 12 SetMarkerPath 19 3 20 SetZone 20 9 SetMarkerPath 20 1 12 SetMarkerPath 20 2 19 SetMarkerPath 20 3 45 SetZone 21 9 SetMarkerPath 21 1 47 SetMarkerPath 21 2 10 SetMarkerPath 21 3 22 SetZone 22 7 SetMarkerPath 22 0 23 SetMarkerPath 22 1 48 SetMarkerPath 22 2 24 SetMarkerPath 22 3 21 SetZone 23 7 SetMarkerPath 23 0 22 SetZone 24 7 SetMarkerPath 24 1 22 SetMarkerPath 24 2 13 SetMarkerPath 24 3 25 SetMarkerPath 24 4 48 SetZone 25 7 SetMarkerPath 25 1 13 SetMarkerPath 25 2 24 SetMarkerPath 25 3 15 SetMarkerPath 25 4 43 SetZone 26 9 SetMarkerPath 26 1 10 SetMarkerPath 26 2 27 SetMarkerPath 26 3 46 SetZone 27 9 SetMarkerPath 27 1 31 SetMarkerPath 27 2 26 SetMarkerPath 27 3 20 SetMarkerPath 27 4 46 SetZone 28 9 SetMarkerPath 28 1 4 SetMarkerPath 28 2 18 SetMarkerPath 28 3 40 SetZone 29 9 SetMarkerPath 29 1 30 SetMarkerPath 29 2 4 SetMarkerPath 29 3 12 SetZone 30 9 SetMarkerPath 30 1 5 SetMarkerPath 30 2 29 SetMarkerPath 30 3 12 SetZone 31 9 SetMarkerPath 31 1 32 SetMarkerPath 31 2 5 SetMarkerPath 31 3 27 SetZone 32 9 SetMarkerPath 32 1 6 SetMarkerPath 32 2 31 SetZone 33 9 SetMarkerPath 33 1 34 SetMarkerPath 33 2 6 SetMarkerPath 33 3 26 SetZone 34 9 SetMarkerPath 34 1 3 SetMarkerPath 34 2 33 SetMarkerPath 34 3 10 SetZone 35 7 SetMarkerPath 35 1 7 SetMarkerPath 35 2 37 SetMarkerPath 35 3 23 SetZone 36 7 SetMarkerPath 36 1 7 SetMarkerPath 36 2 23 SetMarkerPath 36 3 87 SetZone 37 7 SetMarkerPath 37 0 23 SetMarkerPath 37 1 35 SetMarkerPath 37 2 2 SetMarkerPath 37 3 13 SetZone 38 8 SetMarkerPath 38 1 39 SetMarkerPath 38 2 8 SetMarkerPath 38 3 11 SetZone 39 8 SetMarkerPath 39 1 40 SetMarkerPath 39 2 38 SetZone 40 8 SetMarkerPath 40 1 39 SetMarkerPath 40 2 53 SetMarkerPath 40 3 28 SetZone 41 9 SetMarkerPath 41 1 45 SetMarkerPath 41 2 19 SetMarkerPathFlags 41 2 r SetRocketJumpPathFields 41 2 78.3 -1.0 0 SetZone 42 9 SetMarkerPath 42 1 48 SetMarkerPath 42 2 10 SetMarkerPathFlags 42 2 r SetRocketJumpPathFields 42 2 78.3 -1.0 0 SetZone 43 1 SetMarkerPath 43 1 9 SetMarkerPath 43 2 48 SetMarkerPath 43 3 44 SetZone 44 1 SetMarkerPath 44 1 9 SetMarkerPath 44 2 45 SetMarkerPath 44 3 43 SetZone 45 1 SetMarkerPath 45 1 9 SetMarkerPath 45 2 44 SetMarkerPath 45 3 46 SetMarkerPath 45 4 20 SetZone 46 1 SetMarkerPath 46 1 9 SetMarkerPath 46 2 45 SetMarkerPath 46 3 47 SetZone 47 1 SetMarkerPath 47 1 9 SetMarkerPath 47 2 46 SetMarkerPath 47 3 48 SetMarkerPath 47 4 21 SetZone 48 1 SetMarkerPath 48 1 9 SetMarkerPath 48 2 47 SetMarkerPath 48 3 43 SetMarkerPath 48 4 22 SetZone 49 2 SetMarkerPath 49 1 72 SetMarkerPath 49 2 54 SetMarkerPath 49 3 50 SetMarkerPathFlags 49 3 j SetZone 50 6 SetMarkerPath 50 1 51 SetMarkerPathFlags 50 1 j SetZone 51 6 SetMarkerPath 51 1 52 SetMarkerPathFlags 51 1 j SetZone 52 6 SetMarkerPath 52 1 53 SetMarkerPathFlags 52 1 j SetZone 53 8 SetMarkerPath 53 1 17 SetMarkerPath 53 2 18 SetZone 54 2 SetMarkerPath 54 1 49 SetMarkerPath 54 2 55 SetZone 55 2 SetMarkerPath 55 1 54 SetMarkerPath 55 2 56 SetZone 56 2 SetMarkerPath 56 1 55 SetMarkerPath 56 2 57 SetZone 57 2 SetMarkerPath 57 1 56 SetMarkerPath 57 2 58 SetMarkerPath 57 3 53 SetMarkerPathFlags 57 3 r SetRocketJumpPathFields 57 3 78.3 -1.0 0 SetZone 58 2 SetMarkerPath 58 1 57 SetMarkerPath 58 2 59 SetMarkerPath 58 3 41 SetMarkerPathFlags 58 3 r SetRocketJumpPathFields 58 3 78.3 -1.0 0 SetZone 59 2 SetMarkerPath 59 1 58 SetMarkerPath 59 2 60 SetMarkerPath 59 3 12 SetMarkerPathFlags 59 3 r SetRocketJumpPathFields 59 3 78.3 -1.0 0 SetZone 60 2 SetMarkerPath 60 1 59 SetMarkerPath 60 2 61 SetMarkerPath 60 3 81 SetMarkerPath 60 4 12 SetMarkerPathFlags 60 4 r SetRocketJumpPathFields 60 4 78.3 -1.0 0 SetZone 61 3 SetMarkerPath 61 1 60 SetMarkerPath 61 2 62 SetMarkerPath 61 3 81 SetZone 62 3 SetMarkerPath 62 1 61 SetMarkerPath 62 2 63 SetMarkerPath 62 3 80 SetZone 63 3 SetMarkerPath 63 1 62 SetMarkerPath 63 2 64 SetMarkerPath 63 3 80 SetZone 64 3 SetMarkerPath 64 1 63 SetMarkerPath 64 2 65 SetZone 65 3 SetMarkerPath 65 1 64 SetMarkerPath 65 2 66 SetMarkerPath 65 3 10 SetMarkerPathFlags 65 3 r SetRocketJumpPathFields 65 3 78.3 -1.0 0 SetZone 66 3 SetMarkerPath 66 1 65 SetMarkerPath 66 2 67 SetMarkerPath 66 3 42 SetMarkerPathFlags 66 3 r SetRocketJumpPathFields 66 3 78.3 -1.0 0 SetZone 67 3 SetMarkerPath 67 1 68 SetMarkerPath 67 2 66 SetMarkerPath 67 3 42 SetMarkerPathFlags 67 3 r SetRocketJumpPathFields 67 3 78.3 -1.0 0 SetZone 68 3 SetMarkerPath 68 1 67 SetMarkerPath 68 2 69 SetMarkerPath 68 3 23 SetMarkerPathFlags 68 3 r SetRocketJumpPathFields 68 3 78.3 -1.0 0 SetZone 69 4 SetMarkerPath 69 1 68 SetMarkerPath 69 2 70 SetMarkerPath 69 3 76 SetZone 70 4 SetMarkerPath 70 1 69 SetMarkerPath 70 2 71 SetZone 71 4 SetMarkerPath 71 1 70 SetMarkerPath 71 2 72 SetZone 72 4 SetMarkerPath 72 1 71 SetMarkerPath 72 2 49 SetMarkerPath 72 3 73 SetZone 73 5 SetMarkerPath 73 1 72 SetMarkerPath 73 2 74 SetZone 74 5 SetMarkerPath 74 1 75 SetMarkerPath 74 2 86 SetMarkerPath 74 3 73 SetMarkerPath 74 4 43 SetMarkerPathFlags 74 4 r SetRocketJumpPathFields 74 4 78.3 -1.0 0 SetZone 75 5 SetMarkerPath 75 1 74 SetMarkerPath 75 2 77 SetMarkerPath 75 3 76 SetMarkerPath 75 4 48 SetMarkerPathFlags 75 4 r SetRocketJumpPathFields 75 4 78.3 -1.0 0 SetZone 76 5 SetMarkerPath 76 1 69 SetMarkerPath 76 2 75 SetZone 77 5 SetMarkerPath 77 1 78 SetMarkerPath 77 2 75 SetMarkerPath 77 3 47 SetMarkerPathFlags 77 3 r SetRocketJumpPathFields 77 3 78.3 -1.0 0 SetMarkerPath 77 4 48 SetMarkerPathFlags 77 4 r SetRocketJumpPathFields 77 4 78.3 -1.0 0 SetMarkerPath 77 5 21 SetMarkerPathFlags 77 5 r SetRocketJumpPathFields 77 5 78.3 -1.0 0 SetMarkerPath 77 6 22 SetMarkerPathFlags 77 6 r SetRocketJumpPathFields 77 6 78.3 -1.0 0 SetZone 78 5 SetMarkerPath 78 1 79 SetMarkerPath 78 2 77 SetMarkerPath 78 3 47 SetMarkerPathFlags 78 3 r SetRocketJumpPathFields 78 3 78.3 -1.0 0 SetZone 79 5 SetMarkerPath 79 1 82 SetMarkerPath 79 2 78 SetMarkerPath 79 3 81 SetMarkerPath 79 4 80 SetMarkerPath 79 5 46 SetMarkerPathFlags 79 5 r SetRocketJumpPathFields 79 5 78.3 -1.0 0 SetZone 80 5 SetMarkerPath 80 1 62 SetMarkerPath 80 2 63 SetMarkerPath 80 3 79 SetZone 81 5 SetMarkerPath 81 1 60 SetMarkerPath 81 2 61 SetMarkerPath 81 3 82 SetMarkerPath 81 4 79 SetMarkerPath 81 5 20 SetMarkerPathFlags 81 5 r SetRocketJumpPathFields 81 5 78.3 -1.0 0 SetZone 82 5 SetMarkerPath 82 1 83 SetMarkerPath 82 2 79 SetMarkerPath 82 3 81 SetMarkerPath 82 4 20 SetMarkerPathFlags 82 4 r SetRocketJumpPathFields 82 4 78.3 -1.0 0 SetMarkerPath 82 5 45 SetMarkerPathFlags 82 5 r SetRocketJumpPathFields 82 5 78.3 -1.0 0 SetZone 83 5 SetMarkerPath 83 1 84 SetMarkerPath 83 2 82 SetMarkerPath 83 3 45 SetMarkerPathFlags 83 3 r SetRocketJumpPathFields 83 3 78.3 -1.0 0 SetZone 84 5 SetMarkerPath 84 1 86 SetMarkerPath 84 2 83 SetMarkerPath 84 3 85 SetMarkerPath 84 4 44 SetMarkerPathFlags 84 4 r SetRocketJumpPathFields 84 4 78.3 -1.0 0 SetZone 85 5 SetMarkerPath 85 1 84 SetMarkerPath 85 2 17 SetMarkerPathFlags 85 2 r SetRocketJumpPathFields 85 2 78.3 -1.0 0 SetZone 86 5 SetMarkerPath 86 1 74 SetMarkerPath 86 2 84 SetMarkerPath 86 3 43 SetMarkerPathFlags 86 3 r SetRocketJumpPathFields 86 3 78.3 -1.0 0 SetMarkerPath 86 4 44 SetMarkerPathFlags 86 4 r SetRocketJumpPathFields 86 4 78.3 -1.0 0 SetZone 87 9 SetMarkerPath 87 1 3 SetMarkerPath 87 2 36 SetMarkerPath 87 3 10 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/pkeg1.bot000066400000000000000000000173231475442401000257630ustar00rootroot00000000000000CreateMarker 551 -1149 -40 CreateMarker 395 -1020 -40 CreateMarker 232 -1020 8 CreateMarker 31 -1020 24 CreateMarker -125 -817 24 CreateMarker -124 -625 -40 CreateMarker 27 -629 8 CreateMarker -129 -468 -40 CreateMarker -124 -261 -40 CreateMarker -23 -367 -40 CreateMarker -19 -151 -40 CreateMarker 372 -265 -40 CreateMarker 301 -432 -40 CreateMarker 641 -577 -40 CreateMarker 817 -709 -40 CreateMarker 830 -879 -40 CreateMarker 373 -233 -232 CreateMarker 633 -438 -248 CreateMarker 641 -619 -296 CreateMarker 643 -774 -296 CreateMarker 822 -768 -264 CreateMarker 998 -769 -232 CreateMarker 999 -954 -232 CreateMarker 998 -1127 -232 CreateMarker 828 -1320 -232 CreateMarker 641 -1329 -232 CreateMarker 748 -1067 -296 CreateMarker 496 -1047 -296 CreateMarker 483 -824 -296 CreateMarker 307 -817 -296 CreateMarker 128 -631 -280 CreateMarker 128 -474 -248 CreateMarker 222 -480 -232 CreateMarker 543 -463 -232 CreateMarker 480 -1241 -232 SetZone 1 5 SetMarkerPath 1 0 78 SetMarkerPath 1 1 41 SetMarkerPath 1 2 69 SetZone 2 6 SetMarkerPath 2 0 35 SetMarkerPath 2 1 33 SetMarkerPath 2 2 54 SetMarkerPath 2 3 38 SetZone 3 10 SetMarkerPath 3 0 58 SetMarkerPath 3 1 40 SetMarkerPath 3 2 10 SetZone 4 1 SetMarkerPath 4 0 23 SetMarkerPath 4 1 39 SetMarkerPath 4 2 36 SetMarkerPath 4 3 75 SetZone 5 10 SetMarkerPath 5 0 23 SetMarkerPath 5 1 37 SetMarkerPath 5 2 54 SetZone 6 2 SetMarkerPath 6 0 74 SetMarkerPath 6 1 75 SetMarkerPath 6 2 76 SetZone 7 6 SetMarkerPath 7 0 35 SetZone 8 7 SetMarkerPath 8 0 51 SetMarkerPath 8 1 49 SetZone 9 4 SetMarkerPath 9 0 17 SetMarkerPath 9 1 14 SetMarkerPath 9 2 15 SetZone 10 10 SetMarkerPath 10 0 57 SetMarkerPath 10 1 58 SetMarkerPath 10 2 3 SetZone 11 9 SetMarkerPath 11 0 29 SetGoal 12 4 SetZone 12 7 SetMarkerPath 12 0 13 SetMarkerPath 12 1 53 SetMarkerPath 12 2 55 SetMarkerPath 12 3 50 SetGoal 13 18 SetZone 13 6 SetMarkerPath 13 0 23 SetMarkerPath 13 1 53 SetMarkerPath 13 2 55 SetGoal 14 19 SetZone 14 4 SetMarkerPath 14 0 72 SetMarkerPath 14 1 16 SetMarkerPath 14 2 17 SetMarkerPath 14 3 15 SetGoal 15 19 SetZone 15 4 SetMarkerPath 15 0 16 SetMarkerPath 15 1 14 SetMarkerPath 15 2 17 SetMarkerPath 15 3 62 SetGoal 16 19 SetZone 16 4 SetMarkerPath 16 0 15 SetMarkerPath 16 1 17 SetMarkerPath 16 2 14 SetGoal 17 13 SetZone 17 4 SetMarkerPath 17 0 72 SetMarkerPath 17 1 16 SetMarkerPath 17 2 14 SetMarkerPath 17 3 15 SetMarkerPath 17 4 62 SetGoal 18 9 SetZone 18 4 SetMarkerPath 18 0 72 SetMarkerPath 18 1 63 SetMarkerPath 18 2 70 SetMarkerPath 18 3 71 SetMarkerPath 18 4 64 SetGoal 19 1 SetZone 19 5 SetMarkerPath 19 0 68 SetMarkerPath 19 1 67 SetGoal 20 2 SetZone 20 10 SetMarkerPath 20 0 55 SetMarkerPath 20 1 28 SetGoal 21 3 SetZone 21 2 SetMarkerPath 21 0 74 SetMarkerPath 21 1 73 SetGoal 22 8 SetZone 22 8 SetMarkerPath 22 0 47 SetMarkerPath 22 1 48 SetGoal 23 7 SetZone 23 1 SetMarkerPath 23 0 4 SetMarkerPath 23 1 75 SetMarkerPath 23 2 76 SetMarkerPath 23 3 60 SetMarkerPath 23 4 36 SetMarkerPath 23 5 55 SetMarkerPathFlags 23 5 r SetRocketJumpPathFields 23 5 78.3 -1.0 0 SetMarkerPath 23 6 54 SetMarkerPathFlags 23 6 r SetRocketJumpPathFields 23 6 78.3 -1.0 0 SetMarkerPath 23 7 53 SetMarkerPathFlags 23 7 r SetRocketJumpPathFields 23 7 78.3 -1.0 0 SetGoal 24 11 SetZone 24 3 SetMarkerPath 24 0 60 SetMarkerPath 24 1 61 SetMarkerPath 24 2 77 SetGoal 25 6 SetZone 25 9 SetMarkerPath 25 0 18 SetMarkerPath 25 1 31 SetMarkerPath 25 2 30 SetGoal 26 5 SetZone 26 9 SetMarkerPath 26 0 18 SetMarkerPath 26 1 45 SetGoal 27 17 SetZone 27 10 SetMarkerPath 27 0 28 SetMarkerPath 27 1 57 SetGoal 28 17 SetZone 28 10 SetMarkerPath 28 0 20 SetMarkerPath 28 1 27 SetGoal 29 15 SetZone 29 9 SetMarkerPath 29 0 30 SetMarkerPath 29 1 44 SetGoal 30 15 SetZone 30 9 SetMarkerPath 30 0 25 SetMarkerPath 30 1 29 SetGoal 31 16 SetZone 31 9 SetMarkerPath 31 0 32 SetMarkerPath 31 1 25 SetGoal 32 16 SetZone 32 9 SetMarkerPath 32 0 59 SetMarkerPath 32 1 31 SetGoal 33 10 SetZone 33 6 SetMarkerPath 33 0 2 SetMarkerPath 33 1 54 SetMarkerPath 33 2 52 SetMarkerPath 33 3 34 SetMarkerPath 33 4 35 SetMarkerPath 33 5 38 SetGoal 34 14 SetZone 34 6 SetMarkerPath 34 0 33 SetMarkerPath 34 1 35 SetMarkerPath 34 2 52 SetGoal 35 14 SetZone 35 6 SetMarkerPath 35 0 2 SetMarkerPath 35 1 33 SetMarkerPath 35 2 7 SetMarkerPath 35 3 34 SetGoal 36 12 SetZone 36 1 SetMarkerPath 36 0 4 SetMarkerPath 36 1 23 SetMarkerPath 36 2 60 SetMarkerPath 36 3 39 SetZone 37 10 SetMarkerPath 37 0 55 SetMarkerPath 37 1 36 SetZone 38 6 SetMarkerPath 38 0 2 SetMarkerPath 38 1 33 SetMarkerPath 38 2 1 SetZone 39 1 SetMarkerPath 39 0 4 SetMarkerPath 39 1 75 SetMarkerPath 39 2 36 SetMarkerPath 39 3 3 SetZone 40 10 SetMarkerPath 40 0 3 SetMarkerPath 40 1 58 SetMarkerPath 40 2 4 SetZone 41 5 SetMarkerPath 41 0 1 SetMarkerPath 41 1 69 SetMarkerPath 41 2 2 SetZone 42 9 SetMarkerPath 42 0 32 SetZone 44 9 SetMarkerPath 44 0 29 SetMarkerPath 44 1 45 SetZone 45 9 SetMarkerPath 45 0 18 SetMarkerPath 45 1 44 SetMarkerPath 45 2 26 SetMarkerPath 45 3 46 SetZone 46 8 SetMarkerPath 46 0 45 SetMarkerPath 46 1 47 SetZone 47 8 SetMarkerPath 47 0 46 SetMarkerPath 47 1 22 SetZone 48 8 SetMarkerPath 48 0 22 SetMarkerPath 48 1 49 SetMarkerPath 48 2 50 SetZone 49 7 SetMarkerPath 49 0 48 SetMarkerPath 49 1 50 SetMarkerPath 49 2 51 SetZone 50 7 SetMarkerPath 50 0 48 SetMarkerPath 50 1 12 SetMarkerPath 50 2 49 SetZone 51 6 SetMarkerPath 51 0 52 SetMarkerPath 51 1 49 SetMarkerPath 51 2 53 SetZone 52 6 SetMarkerPath 52 0 54 SetMarkerPath 52 1 33 SetMarkerPath 52 2 34 SetMarkerPath 52 3 53 SetMarkerPath 52 4 51 SetZone 53 6 SetMarkerPath 53 0 23 SetMarkerPath 53 1 54 SetMarkerPath 53 2 52 SetMarkerPath 53 3 13 SetMarkerPath 53 4 51 SetZone 54 6 SetMarkerPath 54 0 36 SetMarkerPath 54 1 2 SetMarkerPath 54 2 52 SetMarkerPath 54 3 53 SetMarkerPath 54 4 33 SetZone 55 10 SetMarkerPath 55 0 23 SetMarkerPath 55 1 13 SetMarkerPath 55 2 20 SetZone 56 10 SetMarkerPath 56 0 23 SetZone 57 10 SetMarkerPath 57 0 18 SetMarkerPath 57 1 27 SetMarkerPath 57 2 10 SetMarkerPath 57 3 58 SetZone 58 9 SetMarkerPath 58 0 57 SetMarkerPath 58 1 10 SetMarkerPath 58 2 3 SetMarkerPath 58 3 59 SetMarkerPath 58 4 40 SetZone 59 9 SetMarkerPath 59 0 58 SetMarkerPath 59 1 32 SetZone 60 3 SetMarkerPath 60 0 23 SetMarkerPath 60 1 36 SetMarkerPath 60 2 76 SetMarkerPath 60 3 75 SetMarkerPath 60 4 24 SetZone 61 3 SetMarkerPath 61 0 62 SetMarkerPath 61 1 24 SetZone 62 4 SetMarkerPath 62 0 63 SetMarkerPath 62 1 17 SetMarkerPath 62 2 15 SetMarkerPath 62 3 61 SetMarkerPath 62 4 64 SetZone 63 4 SetMarkerPath 63 0 72 SetMarkerPath 63 1 62 SetMarkerPath 63 2 64 SetMarkerPath 63 3 18 SetZone 64 4 SetMarkerPath 64 0 63 SetMarkerPath 64 1 62 SetMarkerPath 64 2 18 SetMarkerPath 64 3 65 SetZone 65 5 SetMarkerPath 65 0 66 SetMarkerPath 65 1 64 SetZone 66 5 SetMarkerPath 66 0 67 SetMarkerPath 66 1 65 SetZone 67 5 SetMarkerPath 67 0 70 SetMarkerPath 67 1 19 SetMarkerPath 67 2 66 SetZone 68 5 SetMarkerPath 68 0 70 SetMarkerPath 68 1 69 SetMarkerPath 68 2 19 SetZone 69 5 SetMarkerPath 69 0 78 SetMarkerPath 69 1 1 SetMarkerPath 69 2 68 SetMarkerPath 69 3 41 SetZone 70 4 SetMarkerPath 70 0 18 SetMarkerPath 70 1 67 SetMarkerPath 70 2 68 SetZone 71 4 SetMarkerPath 71 0 72 SetMarkerPath 71 1 18 SetMarkerPath 71 2 78 SetZone 72 4 SetMarkerPath 72 0 73 SetMarkerPath 72 1 71 SetMarkerPath 72 2 18 SetMarkerPath 72 3 63 SetMarkerPath 72 4 17 SetMarkerPath 72 5 14 SetMarkerPath 72 6 26 SetMarkerPathFlags 72 6 r SetRocketJumpPathFields 72 6 78.3 -1.0 0 SetZone 73 2 SetMarkerPath 73 0 21 SetMarkerPath 73 1 72 SetZone 74 2 SetMarkerPath 74 0 75 SetMarkerPath 74 1 21 SetZone 75 2 SetMarkerPath 75 0 76 SetMarkerPath 75 1 4 SetMarkerPath 75 2 23 SetMarkerPath 75 3 60 SetMarkerPath 75 4 74 SetMarkerPath 75 5 39 SetZone 76 2 SetMarkerPath 76 0 75 SetMarkerPath 76 1 23 SetMarkerPath 76 2 60 SetMarkerPath 76 3 6 SetZone 77 3 SetMarkerPath 77 0 61 SetMarkerPath 77 1 24 SetZone 78 5 SetMarkerPath 78 0 71 SetMarkerPath 78 1 1 SetMarkerPath 78 2 69 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/povdmm4.bot000066400000000000000000000067761475442401000263540ustar00rootroot00000000000000CreateMarker 557 -345 88 CreateMarker 580 -172 88 CreateMarker 561 -249 88 CreateMarker 529 -252 -232 CreateMarker -22 -402 -232 CreateMarker 143 -460 -232 CreateMarker 417 -104 -232 CreateMarker 239 -44 -232 CreateMarker 286 -450 -232 CreateMarker 65 -44 -232 CreateMarker -63 -104 -232 CreateMarker 447 -422 -232 CreateMarker 204 -643 -184 CreateMarker 214 131 -184 CreateMarker -75 56 -200 CreateMarker 475 -581 -200 CreateMarker 28 -250 -232 CreateMarker 325 -266 -232 CreateMarker 168 -258 -232 CreateMarker -163 -458 -232 CreateMarker 543 -51 -232 CreateMarker 215 -585 -152 CreateMarker 166 87 -152 SetZone 1 6 SetMarkerFlag 1 t SetMarkerPath 1 0 16 SetMarkerPath 1 1 15 SetMarkerPath 1 2 30 SetMarkerPath 1 3 3 SetZone 2 6 SetGoal 3 2 SetZone 3 6 SetMarkerPath 3 0 1 SetZone 4 5 SetZone 5 5 SetMarkerFlag 5 t SetMarkerPath 5 0 31 SetMarkerPath 5 1 17 SetMarkerPath 5 2 18 SetMarkerPath 5 3 6 SetGoal 6 1 SetZone 6 5 SetMarkerPath 6 0 5 SetZone 7 3 SetMarkerPath 7 0 26 SetMarkerPath 7 1 23 SetZone 8 4 SetMarkerPath 8 0 25 SetMarkerPath 8 1 24 SetZone 9 2 SetMarkerPath 9 0 27 SetMarkerPath 9 1 15 SetMarkerPath 9 2 21 SetMarkerPath 9 3 30 SetZone 10 1 SetMarkerPath 10 0 11 SetMarkerPath 10 1 12 SetMarkerPath 10 2 13 SetZone 11 1 SetMarkerPath 11 0 10 SetMarkerPath 11 1 13 SetMarkerPath 11 2 19 SetZone 12 1 SetMarkerPath 12 0 10 SetMarkerPath 12 1 13 SetMarkerPath 12 2 17 SetZone 13 1 SetMarkerPath 13 0 10 SetMarkerPath 13 1 11 SetMarkerPath 13 2 12 SetMarkerPath 13 3 28 SetZone 14 2 SetMarkerPath 14 0 28 SetMarkerPath 14 1 17 SetMarkerPath 14 2 22 SetMarkerPath 14 3 31 SetZone 15 2 SetMarkerPath 15 0 29 SetMarkerPath 15 1 27 SetMarkerPath 15 2 16 SetMarkerPath 15 3 9 SetMarkerPath 15 4 30 SetMarkerPath 15 5 1 SetZone 16 2 SetMarkerPath 16 0 29 SetMarkerPath 16 1 28 SetMarkerPath 16 2 27 SetMarkerPath 16 3 19 SetMarkerPath 16 4 15 SetZone 17 2 SetMarkerPath 17 0 29 SetMarkerPath 17 1 28 SetMarkerPath 17 2 18 SetMarkerPath 17 3 14 SetMarkerPath 17 4 31 SetMarkerPath 17 5 5 SetZone 18 2 SetMarkerPath 18 0 29 SetMarkerPath 18 1 28 SetMarkerPath 18 2 27 SetMarkerPath 18 3 20 SetMarkerPath 18 4 17 SetZone 19 2 SetMarkerPath 19 0 29 SetMarkerPath 19 1 28 SetMarkerPath 19 2 22 SetMarkerPath 19 3 16 SetZone 20 2 SetMarkerPath 20 0 29 SetMarkerPath 20 1 27 SetMarkerPath 20 2 21 SetMarkerPath 20 3 18 SetZone 21 2 SetMarkerPath 21 0 27 SetMarkerPath 21 1 20 SetMarkerPath 21 2 9 SetMarkerPath 21 3 25 SetZone 22 2 SetMarkerPath 22 0 28 SetMarkerPath 22 1 14 SetMarkerPath 22 2 19 SetMarkerPath 22 3 26 SetZone 23 3 SetMarkerPath 23 0 7 SetMarkerPath 23 1 32 SetZone 24 4 SetMarkerPath 24 0 8 SetMarkerPath 24 1 33 SetZone 25 4 SetMarkerPath 25 0 21 SetMarkerPath 25 1 8 SetMarkerPath 25 2 20 SetZone 26 3 SetMarkerPath 26 0 22 SetMarkerPath 26 1 7 SetMarkerPath 26 2 19 SetZone 27 2 SetMarkerPath 27 0 29 SetMarkerPath 27 1 16 SetMarkerPath 27 2 15 SetMarkerPath 27 3 9 SetMarkerPath 27 4 21 SetMarkerPath 27 5 20 SetMarkerPath 27 6 18 SetZone 28 2 SetMarkerPath 28 0 29 SetMarkerPath 28 1 18 SetMarkerPath 28 2 19 SetMarkerPath 28 3 17 SetMarkerPath 28 4 14 SetMarkerPath 28 5 22 SetMarkerPath 28 6 16 SetZone 29 2 SetMarkerPath 29 0 28 SetMarkerPath 29 1 19 SetMarkerPath 29 2 16 SetMarkerPath 29 3 15 SetMarkerPath 29 4 27 SetMarkerPath 29 5 20 SetMarkerPath 29 6 18 SetMarkerPath 29 7 17 SetZone 30 2 SetMarkerPath 30 0 15 SetMarkerPath 30 1 9 SetMarkerPath 30 2 1 SetZone 31 2 SetMarkerPath 31 0 17 SetMarkerPath 31 1 14 SetMarkerPath 31 2 5 SetZone 32 3 SetMarkerPath 32 0 16 SetMarkerPath 32 1 19 SetZone 33 4 SetMarkerPath 33 0 18 SetMarkerPath 33 1 20 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/povdmm4b.bot000066400000000000000000000126741475442401000265100ustar00rootroot00000000000000CreateMarker 201 -707 -184 CreateMarker 248 -608 -184 CreateMarker 166 -573 -152 CreateMarker 375 -575 -152 CreateMarker 246 -458 -232 CreateMarker 513 -607 -200 CreateMarker 472 -476 -216 CreateMarker 574 -364 -232 CreateMarker 569 -196 -232 CreateMarker 487 3 -232 CreateMarker 402 -161 -232 CreateMarker 358 -360 -232 CreateMarker 209 -278 -232 CreateMarker 249 -126 -232 CreateMarker 158 48 -232 CreateMarker 76 -88 -232 CreateMarker 35 -267 -232 CreateMarker 125 -399 -232 CreateMarker 29 -532 -232 CreateMarker -152 -491 -232 CreateMarker -62 -359 -232 CreateMarker -235 -391 -232 CreateMarker -240 -90 -232 CreateMarker -165 59 -200 CreateMarker -55 169 -200 CreateMarker 182 181 -184 CreateMarker 199 70 -152 CreateMarker 47 73 -152 CreateMarker 108 96 -184 CreateMarker 320 -9 -232 CreateMarker 612 -56 -232 CreateMarker -27 5 -232 CreateMarker 388 -540 -232 SetZone 1 3 SetMarkerPath 1 0 4 SetMarkerPath 1 1 5 SetMarkerPath 1 2 7 SetMarkerPath 1 3 9 SetZone 2 1 SetMarkerPath 2 0 28 SetMarkerPath 2 1 27 SetMarkerPath 2 2 32 SetMarkerPath 2 3 31 SetMarkerPath 2 4 29 SetZone 3 2 SetMarkerPath 3 0 23 SetMarkerPath 3 1 26 SetMarkerPath 3 2 35 SetMarkerPath 3 3 19 SetMarkerPath 3 4 20 SetMarkerPath 3 5 24 SetMarkerPath 3 6 25 SetMarkerPath 3 7 27 SetZone 4 3 SetMarkerPath 4 0 6 SetMarkerPath 4 1 5 SetMarkerPath 4 2 1 SetZone 5 3 SetMarkerPath 5 0 4 SetMarkerPath 5 1 1 SetMarkerPath 5 2 6 SetMarkerPath 5 3 7 SetMarkerPath 5 4 9 SetZone 6 3 SetMarkerPath 6 2 21 SetMarkerPath 6 3 8 SetMarkerPath 6 4 15 SetMarkerPath 6 5 10 SetMarkerPath 6 6 7 SetZone 7 3 SetMarkerPath 7 2 9 SetMarkerPath 7 3 10 SetMarkerPath 7 4 15 SetMarkerPath 7 5 8 SetMarkerPath 7 6 6 SetZone 8 2 SetMarkerPath 8 0 15 SetMarkerPath 8 1 22 SetMarkerPath 8 2 21 SetMarkerPath 8 3 16 SetMarkerPath 8 4 36 SetZone 9 3 SetMarkerPath 9 0 1 SetMarkerPath 9 1 5 SetMarkerPath 9 2 10 SetMarkerPath 9 3 11 SetMarkerPath 9 4 8 SetMarkerPath 9 5 36 SetZone 10 3 SetMarkerPath 10 0 9 SetMarkerPath 10 1 11 SetMarkerPath 10 2 15 SetMarkerPath 10 3 36 SetZone 11 2 SetMarkerPath 11 0 9 SetMarkerPath 11 1 10 SetMarkerPath 11 2 15 SetMarkerPath 11 3 12 SetMarkerPath 11 4 14 SetZone 12 2 SetMarkerPath 12 0 11 SetMarkerPath 12 1 15 SetMarkerPath 12 2 14 SetMarkerPath 12 3 34 SetMarkerPath 12 4 13 SetZone 13 2 SetMarkerPath 13 0 12 SetMarkerPath 13 1 34 SetMarkerPath 13 2 14 SetMarkerPath 13 3 33 SetMarkerPath 13 4 17 SetZone 14 2 SetMarkerPath 14 0 11 SetMarkerPath 14 1 12 SetMarkerPath 14 2 34 SetMarkerPath 14 3 13 SetMarkerPath 14 4 33 SetMarkerPath 14 5 17 SetMarkerPath 14 6 16 SetMarkerPath 14 7 15 SetZone 15 2 SetMarkerPath 15 0 11 SetMarkerPath 15 1 12 SetMarkerPath 15 2 14 SetMarkerPath 15 3 10 SetMarkerPath 15 4 8 SetMarkerPath 15 5 21 SetMarkerPath 15 6 16 SetMarkerPath 15 7 17 SetZone 16 2 SetMarkerPath 16 0 14 SetMarkerPath 16 1 15 SetMarkerPath 16 2 8 SetMarkerPath 16 3 17 SetMarkerPath 16 4 21 SetMarkerPath 16 5 20 SetMarkerPath 16 6 19 SetZone 17 2 SetMarkerPath 17 0 19 SetMarkerPath 17 1 13 SetMarkerPath 17 2 33 SetMarkerPath 17 3 18 SetMarkerPath 17 4 14 SetMarkerPath 17 5 15 SetMarkerPath 17 6 16 SetMarkerPath 17 7 20 SetZone 18 2 SetMarkerPath 18 0 33 SetMarkerPath 18 1 17 SetMarkerPath 18 2 19 SetMarkerPath 18 3 35 SetZone 19 2 SetMarkerPath 19 0 18 SetMarkerPath 19 1 3 SetMarkerPath 19 2 26 SetMarkerPath 19 3 35 SetMarkerPath 19 4 33 SetMarkerPath 19 5 17 SetMarkerPath 19 6 16 SetMarkerPath 19 7 20 SetZone 20 2 SetMarkerPath 20 0 3 SetMarkerPath 20 1 26 SetMarkerPath 20 2 17 SetMarkerPath 20 3 16 SetMarkerPath 20 4 21 SetMarkerPath 20 5 24 SetMarkerPath 20 6 19 SetZone 21 2 SetMarkerPath 21 0 15 SetMarkerPath 21 1 8 SetMarkerPath 21 2 22 SetMarkerPath 21 3 16 SetMarkerPath 21 4 24 SetMarkerPath 21 5 20 SetZone 22 2 SetMarkerPath 22 0 8 SetMarkerPath 22 1 23 SetMarkerPath 22 2 24 SetMarkerPath 22 3 21 SetMarkerPath 22 4 36 SetZone 23 2 SetMarkerPath 23 0 22 SetMarkerPath 23 1 25 SetMarkerPath 23 2 3 SetMarkerPath 23 3 24 SetZone 24 2 SetMarkerPath 24 0 22 SetMarkerPath 24 1 23 SetMarkerPath 24 2 3 SetMarkerPath 24 3 25 SetMarkerPath 24 4 21 SetMarkerPath 24 5 20 SetZone 25 2 SetMarkerPath 25 0 23 SetMarkerPath 25 1 3 SetMarkerPath 25 2 24 SetMarkerPath 25 3 26 SetZone 26 1 SetMarkerPath 26 0 3 SetMarkerPath 26 1 25 SetMarkerPath 26 2 20 SetMarkerPath 26 3 19 SetMarkerPath 26 4 35 SetMarkerPath 26 5 27 SetZone 27 1 SetMarkerPath 27 0 26 SetMarkerPath 27 1 28 SetMarkerPath 27 2 35 SetMarkerPath 27 3 3 SetMarkerPath 27 4 2 SetZone 28 1 SetMarkerPath 28 0 27 SetMarkerPath 28 1 2 SetMarkerPath 28 2 32 SetMarkerPath 28 3 35 SetMarkerPath 28 4 3 SetZone 29 1 SetMarkerPath 29 0 2 SetMarkerPath 29 1 30 SetMarkerPath 29 2 32 SetZone 30 1 SetMarkerPath 30 2 33 SetMarkerPath 30 3 17 SetMarkerPath 30 4 19 SetMarkerPath 30 5 35 SetZone 31 1 SetMarkerPath 31 2 18 SetMarkerPath 31 3 17 SetMarkerPath 31 4 19 SetMarkerPath 31 5 35 SetMarkerPath 31 6 27 SetMarkerPath 31 7 28 SetZone 32 1 SetMarkerPath 32 0 28 SetMarkerPath 32 1 2 SetMarkerPath 32 2 29 SetMarkerPath 32 3 30 SetMarkerPath 32 4 31 SetMarkerPath 32 5 19 SetMarkerPathFlags 32 5 j SetZone 33 2 SetMarkerPath 33 0 13 SetMarkerPath 33 1 14 SetMarkerPath 33 2 17 SetMarkerPath 33 3 18 SetMarkerPath 33 4 19 SetZone 34 2 SetMarkerPath 34 0 12 SetMarkerPath 34 1 13 SetMarkerPath 34 2 14 SetZone 35 2 SetMarkerPath 35 0 18 SetMarkerPath 35 1 3 SetMarkerPath 35 2 26 SetMarkerPath 35 3 27 SetMarkerPathFlags 35 3 j SetMarkerPath 35 4 19 SetZone 36 2 SetMarkerPath 36 0 8 SetMarkerPath 36 1 15 SetMarkerPath 36 2 10 SetMarkerPath 36 3 9 SetMarkerPathFlags 36 3 j SetMarkerPath 36 4 22 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ptucket.bot000066400000000000000000000150571475442401000264350ustar00rootroot00000000000000CreateMarker -262 -150 344 CreateMarker -20 -385 344 CreateMarker -238 -630 344 CreateMarker -492 -381 344 CreateMarker -587 -382 388 CreateMarker -810 -377 464 CreateMarker -256 -705 381 CreateMarker -256 -944 464 CreateMarker 68 -388 383 CreateMarker 304 -380 464 CreateMarker -263 -69 376 CreateMarker -249 168 464 CreateMarker -253 304 600 CreateMarker -516 272 595 CreateMarker -695 121 579 CreateMarker -899 -109 590 CreateMarker -941 -335 597 CreateMarker -910 -646 595 CreateMarker -727 -874 590 CreateMarker -538 -1026 593 CreateMarker -257 -1072 603 CreateMarker 40 -1028 603 CreateMarker 245 -850 594 CreateMarker 405 -647 607 CreateMarker 426 -386 594 CreateMarker 395 -107 598 CreateMarker 219 111 596 CreateMarker 28 256 592 CreateMarker 135 8 464 CreateMarker -617 39 464 CreateMarker -673 -746 464 CreateMarker 151 -753 464 CreateMarker -9 -595 344 CreateMarker -29 -187 344 CreateMarker -456 -173 344 CreateMarker -502 -586 344 CreateMarker -607 -785 344 CreateMarker -448 -904 344 CreateMarker -293 -917 344 CreateMarker -73 -892 344 CreateMarker 120 -729 344 CreateMarker 223 -585 344 CreateMarker 272 -427 344 CreateMarker 251 -204 344 CreateMarker 114 -36 344 CreateMarker -47 102 344 CreateMarker -246 156 344 CreateMarker -457 120 344 CreateMarker -594 7 344 CreateMarker -748 -181 344 CreateMarker -799 -411 344 CreateMarker -770 -586 344 CreateMarker -282 -370 344 CreateMarker -260 -1175 616 CreateMarker -584 -1159 616 CreateMarker -804 -950 616 CreateMarker -1023 -730 616 CreateMarker -1024 -392 616 CreateMarker -1014 -57 616 CreateMarker -833 170 616 CreateMarker -588 368 616 CreateMarker -268 385 616 CreateMarker 49 369 616 CreateMarker 505 -77 616 CreateMarker 523 -366 616 CreateMarker 503 -682 616 CreateMarker 310 -935 616 CreateMarker 55 -1155 616 CreateMarker 307 182 616 SetZone 1 7 SetMarkerPath 1 0 15 SetZone 2 7 SetMarkerPath 2 0 15 SetZone 3 7 SetMarkerPath 3 0 15 SetZone 4 7 SetMarkerPath 4 0 15 SetZone 5 7 SetMarkerPath 5 0 15 SetZone 7 2 SetMarkerPath 7 0 22 SetZone 8 4 SetMarkerPath 8 0 26 SetZone 9 1 SetMarkerPath 9 0 20 SetZone 10 3 SetMarkerPath 10 0 24 SetZone 11 8 SetMarkerPath 11 0 69 SetZone 12 8 SetMarkerPath 12 0 80 SetZone 13 8 SetMarkerPath 13 0 77 SetZone 14 8 SetMarkerPath 14 0 73 SetZone 15 7 SetMarkerPath 15 0 69 SetZone 16 4 SetMarkerPath 16 1 26 SetMarkerPath 16 2 49 SetMarkerPath 16 3 50 SetMarkerPath 16 4 68 SetZone 17 3 SetMarkerPath 17 1 48 SetMarkerPath 17 2 24 SetMarkerPath 17 3 49 SetMarkerPath 17 4 68 SetZone 18 2 SetMarkerPath 18 1 51 SetMarkerPath 18 2 22 SetMarkerPath 18 3 48 SetMarkerPath 18 4 68 SetZone 19 1 SetMarkerPath 19 1 50 SetMarkerPath 19 2 20 SetMarkerPath 19 3 51 SetMarkerPath 19 4 68 SetZone 20 1 SetMarkerPath 20 1 21 SetMarkerPath 20 2 19 SetZone 21 5 SetMarkerPath 21 1 32 SetMarkerPath 21 2 20 SetZone 22 2 SetMarkerPath 22 1 23 SetMarkerPath 22 2 18 SetZone 23 5 SetMarkerPath 23 1 36 SetMarkerPath 23 2 22 SetZone 24 3 SetMarkerPath 24 1 25 SetMarkerPath 24 2 17 SetZone 25 5 SetMarkerPath 25 1 40 SetMarkerPath 25 2 24 SetZone 26 4 SetMarkerPath 26 1 27 SetMarkerPath 26 2 16 SetZone 27 6 SetMarkerPath 27 1 28 SetMarkerPath 27 2 26 SetZone 28 6 SetMarkerPath 28 1 29 SetMarkerPath 28 2 27 SetZone 29 6 SetMarkerPath 29 1 28 SetMarkerPath 29 2 30 SetZone 30 6 SetMarkerPath 30 1 29 SetMarkerPath 30 2 45 SetMarkerPath 30 3 31 SetZone 31 6 SetMarkerPath 31 1 32 SetMarkerPath 31 2 30 SetZone 32 5 SetMarkerPath 32 1 31 SetMarkerPath 32 2 21 SetZone 33 6 SetMarkerPath 33 1 34 SetZone 34 5 SetMarkerPath 34 1 33 SetMarkerPath 34 2 35 SetMarkerPath 34 3 46 SetZone 35 5 SetMarkerPath 35 1 34 SetMarkerPath 35 2 36 SetZone 36 7 SetMarkerPath 36 1 35 SetMarkerPath 36 2 23 SetMarkerPath 36 3 37 SetZone 37 5 SetMarkerPath 37 1 38 SetMarkerPath 37 2 36 SetZone 38 5 SetMarkerPath 38 1 37 SetMarkerPath 38 2 39 SetMarkerPath 38 3 47 SetZone 39 5 SetMarkerPath 39 1 38 SetMarkerPath 39 2 40 SetZone 40 5 SetMarkerPath 40 1 39 SetMarkerPath 40 2 41 SetMarkerPath 40 3 25 SetZone 41 6 SetMarkerPath 41 1 40 SetMarkerPath 41 2 42 SetZone 42 6 SetMarkerPath 42 1 41 SetMarkerPath 42 2 44 SetMarkerPath 42 3 43 SetZone 43 6 SetMarkerPath 43 1 42 SetZone 44 6 SetMarkerPath 44 1 42 SetMarkerPath 44 2 49 SetZone 45 6 SetMarkerPath 45 1 30 SetMarkerPath 45 2 50 SetZone 46 5 SetMarkerPath 46 1 34 SetMarkerPath 46 2 51 SetZone 47 5 SetMarkerPath 47 1 38 SetMarkerPath 47 2 48 SetZone 48 3 SetMarkerPath 48 1 18 SetMarkerPath 48 2 56 SetMarkerPath 48 3 17 SetZone 49 4 SetMarkerPath 49 1 16 SetMarkerPath 49 2 17 SetMarkerPath 49 3 60 SetZone 50 1 SetMarkerPath 50 1 16 SetMarkerPath 50 2 64 SetMarkerPath 50 3 19 SetZone 51 2 SetMarkerPath 51 1 19 SetMarkerPath 51 2 52 SetMarkerPath 51 3 18 SetZone 52 2 SetMarkerPath 52 1 51 SetMarkerPath 52 2 53 SetMarkerPath 52 3 67 SetZone 53 2 SetMarkerPath 53 1 54 SetMarkerPath 53 2 52 SetZone 54 2 SetMarkerPath 54 1 55 SetMarkerPath 54 2 53 SetZone 55 2 SetMarkerPath 55 1 56 SetMarkerPath 55 2 54 SetZone 56 3 SetMarkerPath 56 1 48 SetMarkerPath 56 2 57 SetMarkerPath 56 3 55 SetZone 57 3 SetMarkerPath 57 1 58 SetMarkerPath 57 2 56 SetZone 58 3 SetMarkerPath 58 1 59 SetMarkerPath 58 2 57 SetZone 59 3 SetMarkerPath 59 1 60 SetMarkerPath 59 2 58 SetZone 60 4 SetMarkerPath 60 1 49 SetMarkerPath 60 2 61 SetMarkerPath 60 3 59 SetZone 61 4 SetMarkerPath 61 1 62 SetMarkerPath 61 2 60 SetZone 62 4 SetMarkerPath 62 1 61 SetMarkerPath 62 2 63 SetZone 63 4 SetMarkerPath 63 1 64 SetMarkerPath 63 2 62 SetZone 64 1 SetMarkerPath 64 1 50 SetMarkerPath 64 2 65 SetMarkerPath 64 3 63 SetZone 65 1 SetMarkerPath 65 1 66 SetMarkerPath 65 2 64 SetZone 66 1 SetMarkerPath 66 1 67 SetMarkerPath 66 2 65 SetZone 67 1 SetMarkerPath 67 1 52 SetMarkerPath 67 2 66 SetZone 68 4 SetMarkerPath 68 1 17 SetMarkerPath 68 2 18 SetMarkerPath 68 3 19 SetMarkerPath 68 4 16 SetZone 69 8 SetMarkerPath 69 0 70 SetMarkerPath 69 1 83 SetZone 70 8 SetMarkerPath 70 0 69 SetMarkerPath 70 1 71 SetZone 71 8 SetMarkerPath 71 0 70 SetMarkerPath 71 1 72 SetZone 72 8 SetMarkerPath 72 0 71 SetMarkerPath 72 1 73 SetZone 73 8 SetMarkerPath 73 0 72 SetMarkerPath 73 1 74 SetZone 74 8 SetMarkerPath 74 0 73 SetMarkerPath 74 1 75 SetZone 75 8 SetMarkerPath 75 0 74 SetMarkerPath 75 1 76 SetZone 76 8 SetMarkerPath 76 0 75 SetMarkerPath 76 1 77 SetZone 77 8 SetMarkerPath 77 0 76 SetMarkerPath 77 1 78 SetZone 78 8 SetMarkerPath 78 0 77 SetMarkerPath 78 1 84 SetZone 79 8 SetMarkerPath 79 0 84 SetMarkerPath 79 1 80 SetZone 80 8 SetMarkerPath 80 0 79 SetMarkerPath 80 1 81 SetZone 81 8 SetMarkerPath 81 0 80 SetMarkerPath 81 1 82 SetZone 82 8 SetMarkerPath 82 0 81 SetMarkerPath 82 1 83 SetZone 83 8 SetMarkerPath 83 0 82 SetMarkerPath 83 1 69 SetZone 84 8 SetMarkerPath 84 0 78 SetMarkerPath 84 1 79 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/pushdmm4.bot000066400000000000000000000104211475442401000265050ustar00rootroot00000000000000CreateMarker 3216 336 -216 CreateMarker 3015 336 -216 CreateMarker 2840 338 -216 CreateMarker 2608 345 -216 CreateMarker 2608 564 -216 CreateMarker 2620 754 -216 CreateMarker 2619 937 -216 CreateMarker 2804 944 -216 CreateMarker 2982 935 -216 CreateMarker 3216 937 -216 CreateMarker 3214 717 -216 CreateMarker 3206 565 -216 CreateMarker 3095 454 -216 CreateMarker 2914 462 -216 CreateMarker 2716 453 -216 CreateMarker 2727 666 -216 CreateMarker 2723 838 -216 CreateMarker 2914 809 -216 CreateMarker 3082 815 -216 CreateMarker 3075 643 -216 CreateMarker 2832 601 -216 CreateMarker 2850 749 -216 CreateMarker 3000 696 -216 CreateMarker 2984 565 -216 SetZone 5 5 SetMarkerPath 5 0 26 SetMarkerPath 5 1 27 SetMarkerPath 5 2 20 SetMarkerPath 5 3 21 SetMarkerPath 5 4 22 SetZone 6 4 SetMarkerPath 6 0 24 SetMarkerPath 6 1 25 SetMarkerPath 6 2 19 SetMarkerPath 6 3 27 SetZone 7 2 SetMarkerPath 7 0 28 SetMarkerPath 7 1 21 SetMarkerPath 7 2 22 SetMarkerPath 7 3 13 SetMarkerPath 7 4 25 SetMarkerPath 7 5 26 SetZone 8 3 SetMarkerPath 8 0 29 SetMarkerPath 8 1 25 SetMarkerPath 8 2 16 SetMarkerPath 8 3 11 SetMarkerPath 8 4 23 SetZone 9 1 SetMarkerPath 9 0 20 SetMarkerPath 9 1 21 SetMarkerPath 9 2 10 SetZone 10 1 SetMarkerPath 10 0 9 SetMarkerPath 10 1 21 SetMarkerPath 10 2 32 SetMarkerPath 10 3 22 SetMarkerPath 10 4 11 SetZone 11 1 SetMarkerPath 11 0 10 SetMarkerPath 11 1 12 SetMarkerPath 11 2 23 SetMarkerPath 11 3 22 SetMarkerPath 11 4 29 SetZone 12 1 SetMarkerPath 12 0 11 SetMarkerPath 12 1 23 SetMarkerPath 12 2 13 SetZone 13 1 SetMarkerPath 13 0 12 SetMarkerPath 13 1 23 SetMarkerPath 13 2 29 SetMarkerPath 13 3 24 SetMarkerPath 13 4 14 SetZone 14 1 SetMarkerPath 14 0 15 SetMarkerPath 14 1 13 SetMarkerPath 14 2 25 SetMarkerPath 14 3 24 SetMarkerPath 14 4 30 SetZone 15 1 SetMarkerPath 15 0 16 SetMarkerPath 15 1 25 SetMarkerPath 15 2 14 SetZone 16 1 SetMarkerPath 16 0 15 SetMarkerPath 16 1 17 SetMarkerPath 16 2 26 SetMarkerPath 16 3 25 SetMarkerPath 16 4 30 SetZone 17 1 SetMarkerPath 17 0 16 SetMarkerPath 17 1 18 SetMarkerPath 17 2 27 SetMarkerPath 17 3 31 SetMarkerPath 17 4 26 SetMarkerPath 17 5 25 SetZone 18 1 SetMarkerPath 18 0 17 SetMarkerPath 18 1 19 SetMarkerPath 18 2 27 SetZone 19 1 SetMarkerPath 19 0 18 SetMarkerPath 19 1 20 SetMarkerPath 19 2 28 SetMarkerPath 19 3 27 SetMarkerPath 19 4 31 SetZone 20 1 SetMarkerPath 20 0 19 SetMarkerPath 20 1 28 SetMarkerPath 20 2 32 SetMarkerPath 20 3 21 SetMarkerPath 20 4 9 SetZone 21 1 SetMarkerPath 21 0 20 SetMarkerPath 21 1 9 SetMarkerPath 21 2 10 SetMarkerPath 21 3 28 SetMarkerPath 21 4 32 SetMarkerPath 21 5 22 SetZone 22 1 SetMarkerPath 22 0 10 SetMarkerPath 22 1 11 SetMarkerPath 22 2 21 SetMarkerPath 22 3 32 SetMarkerPath 22 4 29 SetMarkerPath 22 5 23 SetZone 23 1 SetMarkerPath 23 0 11 SetMarkerPath 23 1 12 SetMarkerPath 23 2 13 SetMarkerPath 23 3 22 SetMarkerPath 23 4 24 SetMarkerPath 23 5 29 SetZone 24 1 SetMarkerPath 24 0 13 SetMarkerPath 24 1 14 SetMarkerPath 24 2 25 SetMarkerPath 24 3 23 SetMarkerPath 24 4 30 SetMarkerPath 24 5 29 SetZone 25 1 SetMarkerPath 25 0 15 SetMarkerPath 25 1 16 SetMarkerPath 25 2 17 SetMarkerPath 25 3 14 SetMarkerPath 25 4 26 SetMarkerPath 25 5 30 SetMarkerPath 25 6 24 SetZone 26 1 SetMarkerPath 26 0 16 SetMarkerPath 26 1 17 SetMarkerPath 26 2 25 SetMarkerPath 26 3 30 SetMarkerPath 26 4 31 SetMarkerPath 26 5 27 SetZone 27 1 SetMarkerPath 27 0 17 SetMarkerPath 27 1 18 SetMarkerPath 27 2 19 SetMarkerPath 27 3 26 SetMarkerPath 27 4 28 SetMarkerPath 27 5 31 SetZone 28 1 SetMarkerPath 28 0 19 SetMarkerPath 28 1 20 SetMarkerPath 28 2 27 SetMarkerPath 28 3 31 SetMarkerPath 28 4 32 SetMarkerPath 28 5 21 SetZone 29 1 SetMarkerPath 29 0 11 SetMarkerPath 29 1 13 SetMarkerPath 29 2 22 SetMarkerPath 29 3 23 SetMarkerPath 29 4 24 SetMarkerPath 29 5 31 SetMarkerPath 29 6 32 SetMarkerPath 29 7 30 SetZone 30 1 SetMarkerPath 30 0 16 SetMarkerPath 30 1 14 SetMarkerPath 30 2 25 SetMarkerPath 30 3 26 SetMarkerPath 30 4 24 SetMarkerPath 30 5 31 SetMarkerPath 30 6 32 SetMarkerPath 30 7 29 SetZone 31 1 SetMarkerPath 31 0 17 SetMarkerPath 31 1 19 SetMarkerPath 31 2 26 SetMarkerPath 31 3 27 SetMarkerPath 31 4 28 SetMarkerPath 31 5 32 SetMarkerPath 31 6 29 SetMarkerPath 31 7 30 SetZone 32 1 SetMarkerPath 32 0 20 SetMarkerPath 32 1 10 SetMarkerPath 32 2 28 SetMarkerPath 32 3 21 SetMarkerPath 32 4 22 SetMarkerPath 32 5 31 SetMarkerPath 32 6 29 SetMarkerPath 32 7 30 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/q1q3monsoon#td.bot000066400000000000000000000311321475442401000275370ustar00rootroot00000000000000CreateMarker -255 87 312 CreateMarker -120 128 312 CreateMarker 117 128 312 CreateMarker 336 125 312 CreateMarker -271 -171 312 CreateMarker -416 -207 312 CreateMarker -416 -447 216 CreateMarker 1063 -577 184 CreateMarker 887 -624 184 CreateMarker 669 -616 184 CreateMarker 599 -441 184 CreateMarker 609 -855 32 CreateMarker 632 -676 32 CreateMarker 940 -610 32 CreateMarker 820 -429 32 CreateMarker 971 -290 32 CreateMarker 834 -219 32 CreateMarker 610 -189 32 CreateMarker 438 -248 32 CreateMarker 252 -82 32 CreateMarker -33 -119 32 CreateMarker -212 -148 32 CreateMarker -353 -262 32 CreateMarker -135 -503 216 CreateMarker -85 -605 216 CreateMarker 80 -544 184 CreateMarker 219 -535 184 CreateMarker 247 -692 168 CreateMarker 393 -844 80 CreateMarker 237 -410 184 CreateMarker 302 -330 184 CreateMarker 524 -307 184 CreateMarker 113 -304 184 CreateMarker 309 -53 156 CreateMarker 533 -68 184 CreateMarker 594 67 232 CreateMarker 598 243 296 CreateMarker 521 382 296 CreateMarker 670 493 296 CreateMarker 665 700 296 CreateMarker 704 836 296 CreateMarker 849 845 240 CreateMarker 992 689 152 CreateMarker 984 535 88 CreateMarker 960 392 88 CreateMarker 845 235 80 CreateMarker 797 391 88 CreateMarker 656 495 120 CreateMarker 673 661 112 CreateMarker 876 686 88 CreateMarker 853 535 88 CreateMarker 821 96 32 CreateMarker 794 -596 32 CreateMarker -278 -33 312 CreateMarker 334 156 136 CreateMarker 16 355 136 CreateMarker 45 80 80 CreateMarker 118 -178 32 CreateMarker 458 -71 32 CreateMarker 99 -71 32 CreateMarker 642 -69 184 CreateMarker 829 -891 184 CreateMarker 562 -569 184 CreateMarker 930 310 296 CreateMarker 1057 226 296 CreateMarker 1049 61 296 CreateMarker 903 28 296 CreateMarker 815 -169 296 CreateMarker 940 -253 296 CreateMarker 939 -102 296 CreateMarker 818 -527 184 CreateMarker 676 391 296 SetGoal 1 24 SetZone 1 2 SetMarkerPath 1 0 27 SetMarkerPath 1 1 35 SetMarkerPath 1 2 80 SetMarkerPath 1 3 79 SetGoal 2 1 SetZone 2 12 SetMarkerPath 2 0 48 SetMarkerPath 2 1 33 SetMarkerPath 2 2 49 SetMarkerPath 2 3 102 SetGoal 3 15 SetZone 3 10 SetMarkerPath 3 0 54 SetMarkerPath 3 1 30 SetMarkerPath 3 2 52 SetMarkerPath 3 3 53 SetMarkerPath 3 4 93 SetGoal 4 19 SetZone 4 11 SetMarkerPath 4 0 92 SetMarkerPath 4 1 7 SetGoal 5 16 SetZone 5 11 SetMarkerPath 5 0 57 SetMarkerPath 5 1 6 SetMarkerPath 5 2 56 SetGoal 6 16 SetZone 6 11 SetMarkerPath 6 0 7 SetMarkerPath 6 1 5 SetMarkerPath 6 2 57 SetMarkerPath 6 3 92 SetGoal 7 16 SetZone 7 11 SetMarkerPath 7 0 92 SetMarkerPath 7 1 6 SetMarkerPath 7 2 4 SetGoal 8 23 SetZone 8 7 SetMarkerPath 8 0 42 SetMarkerPath 8 1 41 SetMarkerPath 8 2 94 SetMarkerPath 8 3 45 SetMarkerPath 8 4 9 SetGoal 9 20 SetZone 9 6 SetMarkerPath 9 0 73 SetGoal 10 17 SetZone 10 7 SetMarkerPath 10 0 44 SetMarkerPath 10 1 11 SetGoal 11 2 SetZone 11 7 SetMarkerPath 11 0 10 SetMarkerPath 11 1 44 SetGoal 12 18 SetZone 12 10 SetMarkerPath 12 0 69 SetMarkerPath 12 1 13 SetGoal 13 16 SetZone 13 10 SetMarkerPath 13 0 69 SetMarkerPath 13 1 12 SetMarkerPath 13 2 68 SetGoal 14 3 SetZone 14 8 SetMarkerPath 14 0 47 SetMarkerPath 14 1 63 SetMarkerPath 14 2 64 SetMarkerPath 14 3 65 SetGoal 15 16 SetZone 15 9 SetMarkerPath 15 0 63 SetMarkerPath 15 1 16 SetGoal 16 18 SetZone 16 9 SetMarkerPath 16 0 63 SetMarkerPath 16 1 15 SetMarkerPath 16 2 62 SetGoal 17 21 SetZone 17 5 SetMarkerPath 17 0 60 SetMarkerPath 17 1 32 SetMarkerPath 17 2 98 SetMarkerPath 17 3 99 SetMarkerPath 17 4 59 SetGoal 18 16 SetZone 18 4 SetMarkerPath 18 0 19 SetMarkerPath 18 1 20 SetGoal 19 15 SetZone 19 4 SetMarkerPath 19 0 96 SetMarkerPath 19 1 36 SetMarkerPath 19 2 18 SetMarkerPath 19 3 20 SetMarkerPath 19 4 97 SetGoal 20 4 SetZone 20 4 SetMarkerPath 20 0 19 SetMarkerPath 20 1 97 SetMarkerPath 20 2 95 SetMarkerPath 20 3 18 SetMarkerPath 20 4 74 SetMarkerPath 20 5 70 SetMarkerPathFlags 20 5 r SetRocketJumpPathFields 20 5 37.0 88.0 0 SetGoal 21 19 SetZone 21 3 SetMarkerPath 21 0 22 SetMarkerPath 21 1 72 SetMarkerPath 21 2 51 SetGoal 22 23 SetZone 22 3 SetMarkerPath 22 0 75 SetMarkerPath 22 1 21 SetMarkerPath 22 2 72 SetMarkerPath 22 3 101 SetGoal 23 5 SetZone 23 13 SetMarkerPath 23 0 106 SetMarkerPath 23 1 109 SetMarkerPath 23 2 108 SetMarkerPath 23 3 110 SetGoal 24 16 SetZone 24 2 SetMarkerPath 24 0 112 SetMarkerPath 24 1 104 SetMarkerPath 24 2 25 SetMarkerPath 24 3 91 SetMarkerPath 24 4 105 SetGoal 25 16 SetZone 25 2 SetMarkerPath 25 0 24 SetGoal 26 16 SetZone 26 2 SetMarkerPath 26 0 77 SetMarkerPath 26 1 112 SetGoal 27 18 SetZone 27 2 SetMarkerPath 27 0 78 SetMarkerPath 27 1 112 SetMarkerPath 27 2 79 SetMarkerPath 27 3 1 SetMarkerPath 27 4 80 SetGoal 28 6 SetZone 28 1 SetMarkerPath 28 0 82 SetMarkerPath 28 1 83 SetGoal 29 7 SetZone 29 1 SetMarkerPath 29 0 91 SetMarkerPath 29 1 89 SetMarkerPath 29 2 88 SetZone 30 10 SetMarkerPath 30 0 54 SetMarkerPath 30 1 3 SetMarkerPath 30 2 52 SetZone 31 13 SetMarkerPath 31 0 106 SetMarkerPath 31 1 107 SetMarkerPath 31 2 110 SetMarkerPath 31 3 108 SetZone 32 5 SetMarkerPath 32 0 17 SetMarkerPath 32 1 98 SetZone 33 12 SetMarkerPath 33 0 2 SetZone 34 8 SetMarkerPath 34 0 41 SetMarkerPath 34 1 39 SetMarkerPath 34 2 94 SetMarkerPath 34 3 45 SetMarkerPath 34 4 46 SetZone 35 2 SetMarkerPath 35 0 1 SetMarkerPath 35 1 81 SetMarkerPath 35 2 80 SetZone 36 4 SetMarkerPath 36 0 19 SetZone 37 9 SetMarkerPath 37 0 63 SetMarkerPath 37 1 14 SetZone 38 11 SetMarkerPath 38 0 48 SetZone 39 8 SetMarkerPath 39 0 41 SetMarkerPath 39 1 94 SetMarkerPath 39 2 34 SetZone 40 8 SetMarkerPath 40 0 39 SetZone 41 8 SetMarkerPath 41 0 42 SetMarkerPath 41 1 39 SetMarkerPath 41 2 34 SetMarkerPath 41 3 94 SetMarkerPath 41 4 8 SetZone 42 7 SetMarkerPath 42 0 43 SetMarkerPath 42 1 8 SetMarkerPath 42 2 94 SetMarkerPath 42 3 41 SetZone 43 7 SetMarkerPath 43 0 44 SetMarkerPath 43 1 42 SetZone 44 7 SetMarkerPath 44 0 10 SetMarkerPath 44 1 43 SetMarkerPath 44 2 11 SetZone 45 8 SetMarkerPath 45 0 94 SetMarkerPath 45 1 8 SetMarkerPath 45 2 34 SetMarkerPath 45 3 46 SetZone 46 8 SetMarkerPath 46 0 45 SetMarkerPath 46 1 34 SetMarkerPath 46 2 94 SetMarkerPath 46 3 47 SetMarkerPath 46 4 63 SetZone 47 8 SetMarkerPath 47 0 46 SetMarkerPath 47 1 14 SetMarkerPath 47 2 63 SetZone 48 12 SetMarkerPath 48 0 2 SetMarkerPath 48 1 49 SetZone 49 12 SetMarkerPath 49 0 48 SetMarkerPath 49 1 2 SetMarkerPath 49 2 111 SetMarkerPath 49 3 50 SetMarkerPath 49 4 56 SetMarkerPath 49 5 108 SetMarkerPathFlags 49 5 r SetRocketJumpPathFields 49 5 50.0 275.0 0 SetZone 50 3 SetMarkerPath 50 0 49 SetMarkerPath 50 1 103 SetMarkerPath 50 2 111 SetMarkerPath 50 3 52 SetMarkerPath 50 4 51 SetZone 51 3 SetMarkerPath 51 0 21 SetMarkerPath 51 1 103 SetMarkerPath 51 2 50 SetZone 52 10 SetMarkerPath 52 0 30 SetMarkerPath 52 1 3 SetMarkerPath 52 2 53 SetMarkerPath 52 3 69 SetMarkerPath 52 4 102 SetMarkerPathFlags 52 4 r SetRocketJumpPathFields 52 4 79.0 176.0 0 SetZone 53 10 SetMarkerPath 53 0 3 SetMarkerPath 53 1 52 SetZone 54 10 SetMarkerPath 54 0 30 SetMarkerPath 54 1 3 SetMarkerPath 54 2 93 SetMarkerPath 54 3 55 SetMarkerPath 54 4 56 SetZone 55 11 SetMarkerPath 55 0 57 SetMarkerPath 55 1 93 SetMarkerPath 55 2 54 SetMarkerPath 55 3 56 SetZone 56 11 SetMarkerPath 56 0 57 SetMarkerPath 56 1 54 SetMarkerPath 56 2 55 SetMarkerPath 56 3 38 SetMarkerPath 56 4 5 SetZone 57 11 SetMarkerPath 57 0 58 SetMarkerPath 57 1 5 SetMarkerPath 57 2 56 SetMarkerPath 57 3 55 SetMarkerPath 57 4 6 SetZone 58 5 SetMarkerPath 58 0 59 SetMarkerPath 58 1 99 SetMarkerPath 58 2 57 SetZone 59 5 SetMarkerPath 59 0 60 SetMarkerPath 59 1 17 SetMarkerPath 59 2 99 SetMarkerPath 59 3 58 SetMarkerPath 59 4 40 SetMarkerPath 59 5 71 SetMarkerPathFlags 59 5 r SetRocketJumpPathFields 59 5 72.0 26.0 0 SetZone 60 5 SetMarkerPath 60 0 100 SetMarkerPath 60 1 99 SetMarkerPath 60 2 59 SetMarkerPath 60 3 17 SetMarkerPath 60 4 98 SetZone 61 9 SetMarkerPath 61 0 62 SetMarkerPath 61 1 100 SetMarkerPath 61 2 98 SetZone 62 9 SetMarkerPath 62 0 63 SetMarkerPath 62 1 16 SetMarkerPath 62 2 37 SetMarkerPath 62 3 61 SetZone 63 9 SetMarkerPath 63 0 37 SetMarkerPath 63 1 15 SetMarkerPath 63 2 16 SetMarkerPath 63 3 62 SetZone 64 6 SetMarkerPath 64 0 14 SetMarkerPath 64 1 66 SetMarkerPath 64 2 65 SetZone 65 6 SetMarkerPath 65 0 14 SetMarkerPath 65 1 66 SetMarkerPath 65 2 64 SetZone 66 6 SetMarkerPath 66 0 68 SetMarkerPath 66 1 65 SetMarkerPath 66 2 64 SetMarkerPath 66 3 67 SetMarkerPath 66 4 70 SetZone 67 6 SetMarkerPath 67 0 68 SetMarkerPath 67 1 66 SetMarkerPath 67 2 70 SetZone 68 6 SetMarkerPath 68 0 13 SetMarkerPath 68 1 67 SetMarkerPath 68 2 66 SetZone 69 10 SetMarkerPath 69 0 52 SetMarkerPath 69 1 12 SetMarkerPath 69 2 13 SetZone 70 6 SetMarkerPath 70 0 66 SetMarkerPath 70 1 67 SetMarkerPath 70 2 73 SetMarkerPath 70 3 71 SetZone 71 6 SetMarkerPath 71 0 70 SetMarkerPath 71 1 73 SetZone 72 3 SetMarkerPath 72 0 75 SetMarkerPath 72 1 22 SetMarkerPath 72 2 21 SetZone 73 6 SetMarkerPath 73 0 70 SetMarkerPath 73 1 9 SetMarkerPath 73 2 71 SetMarkerPath 73 3 74 SetMarkerPath 73 4 98 SetZone 74 4 SetMarkerPath 74 0 20 SetMarkerPath 74 1 75 SetMarkerPath 74 2 59 SetMarkerPath 74 3 98 SetMarkerPath 74 4 100 SetZone 75 3 SetMarkerPath 75 0 74 SetMarkerPath 75 1 101 SetMarkerPath 75 2 59 SetMarkerPath 75 3 22 SetMarkerPath 75 4 72 SetMarkerPath 75 5 76 SetZone 76 2 SetMarkerPath 76 0 75 SetMarkerPath 76 1 101 SetMarkerPath 76 2 77 SetZone 77 2 SetMarkerPath 77 0 76 SetMarkerPath 77 1 26 SetMarkerPath 77 2 78 SetMarkerPath 77 3 79 SetMarkerPath 77 4 112 SetZone 78 2 SetMarkerPath 78 0 77 SetMarkerPath 78 1 112 SetMarkerPath 78 2 27 SetZone 79 2 SetMarkerPath 79 0 77 SetMarkerPath 79 1 112 SetMarkerPath 79 2 27 SetMarkerPath 79 3 1 SetMarkerPath 79 4 91 SetZone 80 2 SetMarkerPath 80 0 27 SetMarkerPath 80 1 1 SetMarkerPath 80 2 35 SetMarkerPath 80 3 81 SetMarkerPath 80 4 91 SetZone 81 1 SetMarkerPath 81 0 35 SetMarkerPath 81 1 82 SetMarkerPath 81 2 80 SetZone 82 1 SetMarkerPath 82 0 81 SetMarkerPath 82 1 28 SetMarkerPath 82 2 90 SetMarkerPath 82 3 89 SetZone 83 1 SetMarkerPath 83 0 28 SetMarkerPath 83 1 90 SetMarkerPath 83 2 91 SetMarkerPath 83 3 84 SetZone 84 1 SetMarkerPath 84 0 83 SetMarkerPath 84 1 85 SetMarkerPath 84 2 87 SetMarkerPath 84 3 91 SetZone 85 1 SetMarkerPath 85 0 84 SetMarkerPath 85 1 87 SetMarkerPath 85 2 91 SetZone 86 1 SetMarkerPath 86 0 87 SetMarkerPath 86 1 92 SetZone 87 1 SetMarkerPath 87 0 84 SetMarkerPath 87 1 91 SetMarkerPath 87 2 85 SetMarkerPath 87 3 88 SetMarkerPath 87 4 86 SetZone 88 1 SetMarkerPath 88 0 91 SetMarkerPath 88 1 29 SetMarkerPath 88 2 89 SetMarkerPath 88 3 87 SetZone 89 1 SetMarkerPath 89 0 91 SetMarkerPath 89 1 90 SetMarkerPath 89 2 29 SetMarkerPath 89 3 88 SetZone 90 1 SetMarkerPath 90 0 91 SetMarkerPath 90 1 89 SetZone 91 1 SetMarkerPath 91 0 84 SetMarkerPath 91 1 90 SetMarkerPath 91 2 89 SetMarkerPath 91 3 29 SetMarkerPath 91 4 88 SetMarkerPath 91 5 87 SetMarkerPath 91 6 85 SetMarkerPath 91 7 79 SetMarkerPathFlags 91 7 r SetRocketJumpPathFields 91 7 80.0 120.0 0 SetZone 92 11 SetMarkerPath 92 0 86 SetMarkerPath 92 1 4 SetMarkerPath 92 2 7 SetMarkerPath 92 3 6 SetZone 93 10 SetMarkerPath 93 0 55 SetMarkerPath 93 1 54 SetMarkerPath 93 2 3 SetZone 94 8 SetMarkerPath 94 0 42 SetMarkerPath 94 1 41 SetMarkerPath 94 2 39 SetMarkerPath 94 3 8 SetMarkerPath 94 4 45 SetMarkerPath 94 5 34 SetMarkerPath 94 6 46 SetZone 95 4 SetMarkerPath 95 0 20 SetZone 96 4 SetMarkerPath 96 0 97 SetMarkerPath 96 1 19 SetZone 97 4 SetMarkerPath 97 0 100 SetMarkerPath 97 1 96 SetZone 98 5 SetMarkerPath 98 0 61 SetMarkerPath 98 1 100 SetMarkerPath 98 2 60 SetMarkerPath 98 3 32 SetMarkerPath 98 4 17 SetZone 99 5 SetMarkerPath 99 0 60 SetMarkerPath 99 1 17 SetMarkerPath 99 2 59 SetMarkerPath 99 3 58 SetZone 100 5 SetMarkerPath 100 0 61 SetMarkerPath 100 1 97 SetMarkerPath 100 2 98 SetMarkerPath 100 3 60 SetZone 101 3 SetMarkerPath 101 0 75 SetMarkerPath 101 1 22 SetMarkerPath 101 2 76 SetZone 102 12 SetMarkerPath 102 0 2 SetZone 103 3 SetMarkerPath 103 0 50 SetMarkerPath 103 1 51 SetMarkerPath 103 2 52 SetZone 104 2 SetMarkerPath 104 0 112 SetMarkerPath 104 1 24 SetMarkerPath 104 2 105 SetMarkerPath 104 3 91 SetZone 105 13 SetMarkerPath 105 0 104 SetMarkerPath 105 1 106 SetMarkerPath 105 2 24 SetZone 106 13 SetMarkerPath 106 0 105 SetMarkerPath 106 1 107 SetMarkerPath 106 2 31 SetMarkerPath 106 3 110 SetMarkerPath 106 4 23 SetZone 107 13 SetMarkerPath 107 0 106 SetMarkerPath 107 1 110 SetMarkerPath 107 2 31 SetZone 108 13 SetMarkerPath 108 0 23 SetMarkerPath 108 1 110 SetMarkerPath 108 2 31 SetZone 109 13 SetMarkerPath 109 0 23 SetMarkerPath 109 1 110 SetMarkerPath 109 2 111 SetMarkerPath 109 3 55 SetZone 110 13 SetMarkerPath 110 0 106 SetMarkerPath 110 1 23 SetMarkerPath 110 2 109 SetMarkerPath 110 3 108 SetMarkerPath 110 4 107 SetMarkerPath 110 5 31 SetZone 111 12 SetMarkerPath 111 0 49 SetMarkerPath 111 1 50 SetZone 112 2 SetMarkerPath 112 0 26 SetMarkerPath 112 1 77 SetMarkerPath 112 2 78 SetMarkerPath 112 3 79 SetMarkerPath 112 4 104 SetMarkerPath 112 5 24 SetMarkerPath 112 6 91 SetMarkerPath 112 7 27 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/rarena3.bot000066400000000000000000000061661475442401000263120ustar00rootroot00000000000000CreateMarker 197 -705 -296 CreateMarker -182 -686 -281 CreateMarker -17 219 -584 CreateMarker -22 553 -584 CreateMarker 380 387 -584 CreateMarker 174 171 -584 CreateMarker 251 -63 -584 CreateMarker -5 -248 -584 CreateMarker -278 -19 -584 CreateMarker -178 152 -584 CreateMarker 23 -463 -584 CreateMarker -513 -47 -584 CreateMarker -360 351 -584 CreateMarker 521 -119 -584 CreateMarker 390 -352 -584 CreateMarker -372 -329 -584 SetZone 1 3 SetMarkerViewOfs 1 -2 SetMarkerPath 1 1 13 SetZone 2 1 SetMarkerPath 2 1 3 SetMarkerPath 2 2 4 SetMarkerPath 2 3 5 SetMarkerPath 2 4 6 SetMarkerPath 2 5 7 SetZone 3 1 SetMarkerPath 3 1 12 SetMarkerPath 3 2 4 SetMarkerPath 3 3 2 SetMarkerPath 3 4 11 SetZone 4 1 SetMarkerPath 4 1 12 SetMarkerPath 4 2 5 SetMarkerPath 4 3 3 SetMarkerPath 4 4 2 SetZone 5 1 SetMarkerPath 5 1 12 SetMarkerPath 5 2 11 SetMarkerPath 5 3 6 SetMarkerPath 5 4 4 SetMarkerPath 5 5 2 SetZone 6 1 SetMarkerPath 6 1 11 SetMarkerPath 6 2 7 SetMarkerPath 6 3 5 SetMarkerPath 6 4 2 SetZone 7 1 SetMarkerPath 7 1 11 SetMarkerPath 7 2 6 SetMarkerPath 7 3 2 SetZone 8 3 SetMarkerViewOfs 8 -10 SetMarkerPath 8 1 18 SetMarkerPath 8 2 16 SetMarkerPath 8 3 17 SetZone 9 3 SetMarkerViewOfs 9 -10 SetMarkerPath 9 1 18 SetMarkerPath 9 2 19 SetMarkerPath 9 3 20 SetZone 11 1 SetMarkerPath 11 1 12 SetMarkerPath 11 2 7 SetMarkerPath 11 3 6 SetMarkerPath 11 4 5 SetMarkerPath 11 5 3 SetZone 12 1 SetMarkerPath 12 1 11 SetMarkerPath 12 2 3 SetMarkerPath 12 3 4 SetMarkerPath 12 4 5 SetZone 13 2 SetMarkerPath 13 1 19 SetMarkerPath 13 2 16 SetMarkerPath 13 3 14 SetMarkerPath 13 4 1 SetMarkerPath 13 5 23 SetMarkerPath 13 6 20 SetZone 14 2 SetMarkerPath 14 1 15 SetMarkerPath 14 2 13 SetMarkerPath 14 3 23 SetMarkerPath 14 4 20 SetZone 15 2 SetMarkerPath 15 1 16 SetMarkerPath 15 2 17 SetMarkerPath 15 3 24 SetMarkerPath 15 4 14 SetMarkerPath 15 5 23 SetZone 16 2 SetMarkerPath 16 1 8 SetMarkerPath 16 2 15 SetMarkerPath 16 3 13 SetMarkerPath 16 4 17 SetMarkerPath 16 5 20 SetZone 17 3 SetMarkerPath 17 1 25 SetMarkerPath 17 2 18 SetMarkerPath 17 3 16 SetMarkerPath 17 4 24 SetMarkerPath 17 5 8 SetMarkerPath 17 6 15 SetZone 18 3 SetMarkerPath 18 1 25 SetMarkerPath 18 2 9 SetMarkerPath 18 3 21 SetMarkerPath 18 4 17 SetMarkerPath 18 5 22 SetMarkerPath 18 6 19 SetZone 19 3 SetMarkerPath 19 1 22 SetMarkerPath 19 2 26 SetMarkerPath 19 3 9 SetMarkerPath 19 4 13 SetMarkerPath 19 5 23 SetMarkerPath 19 6 18 SetZone 20 2 SetMarkerPath 20 1 14 SetMarkerPath 20 2 19 SetMarkerPath 20 3 9 SetMarkerPath 20 4 23 SetMarkerPath 20 5 13 SetMarkerPath 20 6 16 SetZone 21 3 SetMarkerPath 21 1 25 SetMarkerPath 21 2 18 SetMarkerPath 21 3 22 SetMarkerPath 21 4 26 SetZone 22 2 SetMarkerPath 22 1 18 SetMarkerPath 22 2 21 SetMarkerPath 22 3 26 SetMarkerPath 22 4 23 SetMarkerPath 22 5 19 SetZone 23 2 SetMarkerPath 23 1 22 SetMarkerPath 23 2 19 SetMarkerPath 23 3 14 SetMarkerPath 23 4 20 SetMarkerPath 23 5 13 SetMarkerPath 23 6 15 SetZone 24 3 SetMarkerPath 24 1 25 SetMarkerPath 24 2 17 SetMarkerPath 24 3 15 SetZone 25 3 SetMarkerPath 25 1 21 SetMarkerPath 25 2 24 SetMarkerPath 25 3 17 SetMarkerPath 25 4 18 SetZone 26 3 SetMarkerPath 26 1 22 SetMarkerPath 26 2 19 SetMarkerPath 26 3 21 SetMarkerPath 26 4 18 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ravageqwb8.bot000066400000000000000000000265141475442401000270250ustar00rootroot00000000000000CreateMarker 969 -101 -144 CreateMarker 997 -315 -192 CreateMarker 769 -65 -192 CreateMarker 863 -209 -156 CreateMarker 590 -201 -138 CreateMarker 744 -184 -150 CreateMarker 854 -362 -174 CreateMarker 980 -227 54 CreateMarker 821 -75 54 CreateMarker 899 34 54 CreateMarker 997 72 54 CreateMarker 1125 -73 54 CreateMarker 1079 -177 54 CreateMarker 983 -336 54 CreateMarker 983 -490 90 CreateMarker 984 -668 90 CreateMarker 783 -915 90 CreateMarker 983 -795 90 CreateMarker 900 -917 90 CreateMarker 358 -1066 102 CreateMarker 403 -933 102 CreateMarker 351 -816 102 CreateMarker 413 -680 102 CreateMarker 408 -431 54 CreateMarker 406 -305 54 CreateMarker 403 -117 54 CreateMarker 566 -64 54 CreateMarker 738 -70 54 CreateMarker 263 -70 54 CreateMarker 132 -73 54 CreateMarker 80 -192 54 CreateMarker -145 -409 54 CreateMarker -211 -586 66 CreateMarker -298 -680 102 CreateMarker -99 -526 102 CreateMarker 75 -404 102 CreateMarker 199 -493 102 CreateMarker 311 -587 102 CreateMarker 298 -423 54 CreateMarker 491 -1029 102 CreateMarker 587 -947 78 CreateMarker 616 -1064 78 CreateMarker 995 -578 90 CreateMarker 1085 19 -138 CreateMarker 858 -547 -186 CreateMarker 620 -811 -186 CreateMarker 405 -745 -186 CreateMarker -245 -1279 102 CreateMarker -51 -1213 102 CreateMarker -60 -1066 102 CreateMarker 101 -1050 102 CreateMarker -104 -929 102 CreateMarker -278 -1046 102 CreateMarker 460 -582 102 CreateMarker 412 -585 -186 CreateMarker 320 -839 -186 SetZone 1 7 SetMarkerPath 1 0 31 SetMarkerPath 1 1 78 SetZone 2 5 SetMarkerPath 2 0 71 SetMarkerPath 2 1 36 SetZone 3 4 SetMarkerPath 3 0 4 SetZone 4 3 SetMarkerPath 4 0 30 SetMarkerPathAngleHint 4 0 10 SetMarkerPath 4 1 56 SetMarkerPath 4 2 55 SetMarkerPath 4 3 51 SetMarkerPath 4 4 75 SetMarkerPath 4 5 61 SetZone 5 5 SetMarkerPath 5 0 7 SetZone 6 6 SetMarkerPath 6 0 8 SetZone 7 6 SetMarkerPath 7 0 6 SetMarkerPath 7 1 28 SetMarkerPath 7 2 95 SetMarkerPath 7 3 24 SetZone 8 5 SetMarkerPath 8 0 5 SetMarkerPath 8 1 34 SetGoal 9 1 SetZone 9 5 SetMarkerPath 9 0 93 SetMarkerPath 9 1 92 SetMarkerPath 9 2 88 SetMarkerPathFlags 9 2 r SetRocketJumpPathFields 9 2 80.0 30.0 0 SetGoal 10 2 SetZone 10 9 SetMarkerPath 10 0 36 SetMarkerPath 10 1 71 SetMarkerPath 10 2 86 SetMarkerPath 10 3 72 SetGoal 11 3 SetZone 11 4 SetMarkerPath 11 0 52 SetGoal 12 4 SetZone 12 7 SetMarkerPath 12 0 80 SetMarkerPath 12 1 35 SetMarkerPath 12 2 23 SetMarkerPath 12 3 79 SetMarkerPath 12 4 84 SetMarkerPathFlags 12 4 r SetRocketJumpPathFields 12 4 37.0 175.0 0 SetGoal 13 17 SetZone 13 1 SetMarkerPath 13 0 90 SetMarkerPathFlags 13 0 j SetMarkerPath 13 1 26 SetGoal 14 16 SetZone 14 4 SetMarkerPath 14 0 48 SetMarkerPath 14 1 91 SetMarkerPath 14 2 40 SetGoal 15 16 SetZone 15 4 SetMarkerPath 15 0 53 SetMarkerPath 15 1 48 SetMarkerPath 15 2 91 SetMarkerPath 15 3 51 SetGoal 16 16 SetZone 16 8 SetMarkerPath 16 0 18 SetMarkerPath 16 1 73 SetMarkerPath 16 2 17 SetMarkerPath 16 3 74 SetGoal 17 16 SetZone 17 8 SetMarkerPath 17 0 73 SetMarkerPath 17 1 16 SetMarkerPath 17 2 19 SetMarkerPath 17 3 74 SetGoal 18 23 SetZone 18 8 SetMarkerPath 18 0 76 SetMarkerPath 18 1 16 SetMarkerPath 18 2 73 SetMarkerPath 18 3 74 SetGoal 19 23 SetZone 19 8 SetMarkerPath 19 0 73 SetMarkerPath 19 1 17 SetMarkerPath 19 2 74 SetMarkerPath 19 3 75 SetGoal 20 16 SetZone 20 1 SetMarkerPath 20 0 21 SetMarkerPath 20 1 22 SetMarkerPath 20 2 9 SetMarkerPath 20 3 64 SetGoal 21 16 SetZone 21 1 SetMarkerPath 21 0 26 SetMarkerPath 21 1 20 SetGoal 22 16 SetZone 22 1 SetMarkerPath 22 0 47 SetMarkerPath 22 1 20 SetGoal 23 19 SetZone 23 7 SetMarkerPath 23 0 12 SetGoal 24 21 SetZone 24 6 SetMarkerPath 24 0 7 SetMarkerPath 24 1 28 SetMarkerPath 24 2 95 SetMarkerPath 24 3 96 SetGoal 25 20 SetZone 25 1 SetMarkerPath 25 0 47 SetMarkerPath 25 1 88 SetMarkerPath 25 2 89 SetMarkerPath 25 3 64 SetGoal 26 24 SetZone 26 1 SetMarkerPath 26 0 13 SetMarkerPath 26 1 21 SetGoal 27 18 SetZone 27 4 SetMarkerPath 27 0 54 SetMarkerPath 27 1 37 SetMarkerPath 27 2 51 SetGoal 28 16 SetZone 28 6 SetMarkerPath 28 0 7 SetMarkerPath 28 1 24 SetMarkerPath 28 2 95 SetMarkerPath 28 3 96 SetGoal 29 5 SetZone 29 6 SetMarkerPath 29 0 99 SetMarkerPath 29 1 69 SetMarkerPath 29 2 34 SetMarkerPath 29 3 103 SetGoal 30 6 SetZone 30 2 SetMarkerPath 30 0 57 SetMarkerPath 30 1 56 SetMarkerPath 30 2 55 SetMarkerPath 30 3 60 SetMarkerPath 30 4 59 SetMarkerPath 30 5 58 SetGoal 31 15 SetZone 31 7 SetMarkerPath 31 0 79 SetMarkerPath 31 1 1 SetMarkerPath 31 2 78 SetGoal 32 16 SetZone 32 9 SetMarkerPath 32 0 33 SetMarkerPath 32 1 84 SetMarkerPath 32 2 83 SetGoal 33 16 SetZone 33 9 SetMarkerPath 33 0 82 SetMarkerPath 33 1 32 SetMarkerPath 33 2 83 SetMarkerPath 33 3 31 SetGoal 34 16 SetZone 34 5 SetMarkerPath 34 0 8 SetMarkerPath 34 1 103 SetMarkerPath 34 2 94 SetGoal 35 19 SetZone 35 7 SetMarkerPath 35 0 12 SetMarkerPath 35 1 79 SetGoal 36 18 SetZone 36 9 SetMarkerPath 36 0 85 SetMarkerPath 36 1 10 SetMarkerPath 36 2 38 SetMarkerPath 36 3 71 SetMarkerPath 36 4 72 SetMarkerPath 36 5 101 SetMarkerPath 36 6 102 SetGoal 37 19 SetZone 37 4 SetMarkerPath 37 0 27 SetMarkerPath 37 1 53 SetMarkerPath 37 2 51 SetZone 38 9 SetMarkerPath 38 0 36 SetMarkerPath 38 1 101 SetZone 39 6 SetMarkerPath 39 0 99 SetZone 40 4 SetMarkerPath 40 0 14 SetMarkerPath 40 1 48 SetMarkerPath 40 2 51 SetZone 41 1 SetMarkerPath 41 0 64 SetMarkerPath 41 1 89 SetMarkerPath 41 2 88 SetMarkerPath 41 3 47 SetZone 42 5 SetMarkerPath 42 0 103 SetMarkerPath 42 1 94 SetMarkerPath 42 2 93 SetGoal 43 23 SetZone 43 6 SetMarkerPath 43 0 44 SetMarkerPath 43 1 98 SetGoal 44 23 SetZone 44 6 SetMarkerPath 44 0 67 SetMarkerPath 44 1 43 SetGoal 45 24 SetZone 45 7 SetMarkerPath 45 0 100 SetMarkerPath 45 1 46 SetGoal 46 24 SetZone 46 7 SetMarkerPath 46 0 45 SetMarkerPath 46 1 81 SetGoal 47 7 SetZone 47 1 SetMarkerPath 47 0 88 SetMarkerPath 47 1 22 SetMarkerPath 47 2 64 SetMarkerPathFlags 47 2 j SetZone 48 4 SetMarkerPath 48 0 53 SetMarkerPath 48 1 51 SetMarkerPath 48 2 14 SetMarkerPath 48 3 91 SetMarkerPath 48 4 15 SetZone 49 4 SetMarkerPath 49 0 54 SetMarkerPathFlags 49 0 w SetMarkerPath 49 1 40 SetMarkerPath 49 2 48 SetMarkerPath 49 3 14 SetZone 50 4 SetMarkerPath 50 0 53 SetMarkerPathFlags 50 0 w SetMarkerPath 50 1 15 SetMarkerPath 50 2 48 SetMarkerPath 50 3 91 SetZone 51 4 SetMarkerPath 51 0 54 SetMarkerPath 51 1 27 SetMarkerPath 51 2 37 SetMarkerPath 51 3 53 SetMarkerPath 51 4 48 SetMarkerPath 51 5 30 SetMarkerPathFlags 51 5 r SetRocketJumpPathFields 51 5 72.0 225.0 0 SetZone 52 4 SetMarkerPath 52 0 53 SetMarkerPath 52 1 11 SetZone 53 4 SetMarkerPath 53 0 54 SetMarkerPath 53 1 37 SetMarkerPath 53 2 51 SetMarkerPath 53 3 52 SetMarkerPath 53 4 48 SetMarkerPath 53 5 15 SetMarkerPath 53 6 61 SetMarkerPathFlags 53 6 r SetRocketJumpPathFields 53 6 80.0 150.0 0 SetZone 54 4 SetMarkerPath 54 0 92 SetMarkerPath 54 1 27 SetMarkerPath 54 2 51 SetMarkerPath 54 3 53 SetZone 55 2 SetMarkerPath 55 0 56 SetMarkerPath 55 1 30 SetMarkerPath 55 2 60 SetMarkerPath 55 3 61 SetZone 56 2 SetMarkerPath 56 0 75 SetMarkerPath 56 1 55 SetMarkerPath 56 2 57 SetMarkerPath 56 3 30 SetZone 57 2 SetMarkerPath 57 0 56 SetMarkerPath 57 1 58 SetMarkerPath 57 2 30 SetZone 58 2 SetMarkerPath 58 0 57 SetMarkerPath 58 1 30 SetZone 59 2 SetMarkerPath 59 0 30 SetMarkerPath 59 1 60 SetZone 60 2 SetMarkerPath 60 0 30 SetMarkerPath 60 1 59 SetMarkerPath 60 2 55 SetZone 61 2 SetMarkerPath 61 0 55 SetMarkerPath 61 1 62 SetZone 62 1 SetMarkerPath 62 0 61 SetMarkerPath 62 1 90 SetZone 63 1 SetMarkerPath 63 0 90 SetMarkerPath 63 1 13 SetMarkerPath 63 2 20 SetMarkerPath 63 3 65 SetMarkerPath 63 4 9 SetZone 64 1 SetMarkerPath 64 0 66 SetMarkerPath 64 1 41 SetMarkerPath 64 2 20 SetMarkerPath 64 3 25 SetMarkerPath 64 4 47 SetMarkerPath 64 5 88 SetMarkerPath 64 6 89 SetMarkerPath 64 7 9 SetZone 65 1 SetMarkerPath 65 0 63 SetMarkerPath 65 1 66 SetMarkerPath 65 2 20 SetZone 66 1 SetMarkerPath 66 0 65 SetMarkerPath 66 1 64 SetMarkerPath 66 2 20 SetMarkerPath 66 3 9 SetZone 67 6 SetMarkerPath 67 0 87 SetMarkerPath 67 1 44 SetMarkerPath 67 2 68 SetZone 68 6 SetMarkerPath 68 0 87 SetMarkerPath 68 1 69 SetMarkerPath 68 2 67 SetMarkerPath 68 3 70 SetZone 69 6 SetMarkerPath 69 0 29 SetMarkerPath 69 1 68 SetMarkerPath 69 2 70 SetMarkerPath 69 4 8 SetZone 70 9 SetMarkerPath 70 0 85 SetMarkerPath 70 1 101 SetMarkerPath 70 2 69 SetMarkerPath 70 3 68 SetMarkerPath 70 4 71 SetZone 71 9 SetMarkerPath 71 0 86 SetMarkerPath 71 1 72 SetMarkerPath 71 2 102 SetZone 72 9 SetMarkerPath 72 0 73 SetMarkerPath 72 1 86 SetMarkerPath 72 2 71 SetZone 73 8 SetMarkerPath 73 0 76 SetMarkerPath 73 1 18 SetMarkerPath 73 2 17 SetMarkerPath 73 3 74 SetMarkerPath 73 4 16 SetMarkerPath 73 5 19 SetMarkerPath 73 6 72 SetZone 74 8 SetMarkerPath 74 0 73 SetMarkerPath 74 1 18 SetMarkerPath 74 2 16 SetMarkerPath 74 3 17 SetMarkerPath 74 4 19 SetMarkerPath 74 5 75 SetZone 75 2 SetMarkerPath 75 0 19 SetMarkerPath 75 1 74 SetMarkerPath 75 2 56 SetZone 76 8 SetMarkerPath 76 0 77 SetMarkerPath 76 1 18 SetMarkerPath 76 2 73 SetZone 77 7 SetMarkerPath 77 0 78 SetMarkerPath 77 1 76 SetZone 78 7 SetMarkerPath 78 0 31 SetMarkerPath 78 1 1 SetMarkerPath 78 2 77 SetZone 79 7 SetMarkerPath 79 0 12 SetMarkerPath 79 1 80 SetMarkerPath 79 2 31 SetMarkerPath 79 3 35 SetZone 80 7 SetMarkerPath 80 0 81 SetMarkerPath 80 1 23 SetMarkerPath 80 2 12 SetMarkerPath 80 3 79 SetZone 81 7 SetMarkerPath 81 0 46 SetMarkerPath 81 1 23 SetMarkerPath 81 2 80 SetMarkerPath 81 3 82 SetZone 82 9 SetMarkerPath 82 0 81 SetMarkerPath 82 1 12 SetMarkerPath 82 2 80 SetMarkerPath 82 3 31 SetMarkerPath 82 4 33 SetZone 83 9 SetMarkerPath 83 0 33 SetMarkerPath 83 1 32 SetMarkerPath 83 2 1 SetMarkerPath 83 3 31 SetMarkerPath 83 4 79 SetMarkerPath 83 5 84 SetZone 84 9 SetMarkerPath 84 0 32 SetMarkerPath 84 1 83 SetMarkerPath 84 2 86 SetMarkerPath 84 3 85 SetZone 85 9 SetMarkerPath 85 0 84 SetMarkerPath 85 1 86 SetMarkerPath 85 2 70 SetMarkerPath 85 3 71 SetMarkerPath 85 4 36 SetMarkerPath 85 5 101 SetZone 86 9 SetMarkerPath 86 0 85 SetMarkerPath 86 1 71 SetMarkerPath 86 2 72 SetZone 87 6 SetMarkerPath 87 0 89 SetMarkerPath 87 1 88 SetMarkerPath 87 2 68 SetMarkerPath 87 3 67 SetZone 88 1 SetMarkerPath 88 0 64 SetMarkerPath 88 1 41 SetMarkerPath 88 2 89 SetMarkerPath 88 3 47 SetMarkerPath 88 4 87 SetMarkerPath 88 5 25 SetZone 89 1 SetMarkerPath 89 0 64 SetMarkerPath 89 1 41 SetMarkerPath 89 2 88 SetMarkerPath 89 3 87 SetMarkerPath 89 4 25 SetZone 90 1 SetMarkerPath 90 0 62 SetMarkerPath 90 1 13 SetMarkerPath 90 2 63 SetMarkerPath 90 3 9 SetZone 91 4 SetMarkerPath 91 0 3 SetMarkerPath 91 1 48 SetMarkerPath 91 2 14 SetMarkerPath 91 3 15 SetZone 92 5 SetMarkerPath 92 0 9 SetMarkerPath 92 1 54 SetZone 93 5 SetMarkerPath 93 0 42 SetMarkerPath 93 1 94 SetMarkerPath 93 2 9 SetZone 94 5 SetMarkerPath 94 0 42 SetMarkerPath 94 1 34 SetMarkerPath 94 2 93 SetMarkerPath 94 3 71 SetMarkerPath 94 4 102 SetMarkerPath 94 5 103 SetZone 95 6 SetMarkerPath 95 0 7 SetMarkerPath 95 1 24 SetMarkerPath 95 2 28 SetMarkerPath 95 3 96 SetZone 96 6 SetMarkerPath 96 0 24 SetMarkerPath 96 1 95 SetMarkerPath 96 2 28 SetMarkerPath 96 3 97 SetZone 97 6 SetMarkerPath 97 0 96 SetMarkerPath 97 1 98 SetMarkerPath 97 2 99 SetMarkerPath 97 3 100 SetZone 98 6 SetMarkerPath 98 0 97 SetMarkerPath 98 1 43 SetZone 99 6 SetMarkerPath 99 0 97 SetMarkerPath 99 1 39 SetMarkerPath 99 2 29 SetZone 100 7 SetMarkerPath 100 0 97 SetMarkerPath 100 1 45 SetZone 101 9 SetMarkerPath 101 0 36 SetMarkerPath 101 1 70 SetMarkerPath 101 2 38 SetMarkerPath 101 3 85 SetMarkerPath 101 4 71 SetMarkerPath 101 5 86 SetZone 102 5 SetMarkerPath 102 0 94 SetMarkerPath 102 1 2 SetZone 103 5 SetMarkerPath 103 0 34 SetMarkerPath 103 1 42 SetMarkerPath 103 2 94 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/schloss.bot000066400000000000000000000443001475442401000264250ustar00rootroot00000000000000CreateMarker 795 -2451 416 CreateMarker 1060 -2747 312 CreateMarker 821 -2637 184 CreateMarker 808 -2799 184 CreateMarker 804 -2971 184 CreateMarker 631 -2298 248 CreateMarker 611 -2475 248 CreateMarker 603 -2628 184 CreateMarker 998 -2656 184 CreateMarker 1014 -2452 248 CreateMarker 1000 -2311 248 CreateMarker 992 -2855 168 CreateMarker 670 -2768 88 CreateMarker 414 -2756 104 CreateMarker 428 -2630 232 CreateMarker 496 -2912 248 CreateMarker 229 -2776 248 CreateMarker 260 -2608 248 CreateMarker 358 -2480 248 CreateMarker 486 -2416 248 CreateMarker 332 -2316 248 CreateMarker 191 -2427 248 CreateMarker -189 -2457 296 CreateMarker -375 -2399 312 CreateMarker -243 -2531 312 CreateMarker -246 -2737 312 CreateMarker -234 -2890 312 CreateMarker -139 -2753 344 CreateMarker -135 -2637 408 CreateMarker -109 -2520 440 CreateMarker -16 -2691 440 CreateMarker -33 -2856 440 CreateMarker -173 -2959 440 CreateMarker -344 -3039 440 CreateMarker -358 -3184 504 CreateMarker -365 -3274 600 CreateMarker -208 -2411 472 CreateMarker -98 -2339 440 CreateMarker 31 -2420 440 CreateMarker 134 -2287 440 CreateMarker 69 -2142 440 CreateMarker -77 -2134 440 CreateMarker -210 -2037 440 CreateMarker -290 -1863 504 CreateMarker -168 -1928 504 CreateMarker -117 -1718 504 CreateMarker 108 -1720 504 CreateMarker -36 -1904 504 CreateMarker 127 -1931 504 CreateMarker 73 -2027 552 CreateMarker 78 -2168 600 CreateMarker 202 -2280 600 CreateMarker 199 -2451 600 CreateMarker 105 -2545 600 CreateMarker -1 -2450 600 CreateMarker 70 -2346 600 CreateMarker 326 -2265 456 CreateMarker 335 -2392 401 CreateMarker -105 -3113 440 CreateMarker -95 -3256 440 CreateMarker 60 -3212 440 CreateMarker 224 -3208 440 CreateMarker 361 -3192 440 CreateMarker 361 -3332 440 CreateMarker 340 -3561 408 CreateMarker 473 -3491 408 CreateMarker 642 -3452 408 CreateMarker 629 -3623 408 CreateMarker 638 -3798 408 CreateMarker 631 -3959 408 CreateMarker 497 -3950 408 CreateMarker 336 -3943 408 CreateMarker 121 -3930 408 CreateMarker 173 -3728 408 CreateMarker 183 -3464 408 CreateMarker 52 -3567 408 CreateMarker 493 -3690 408 CreateMarker 62 -3724 536 CreateMarker 64 -3887 600 CreateMarker 206 -3984 600 CreateMarker 511 -3984 600 CreateMarker 636 -3909 600 CreateMarker 554 -3702 600 CreateMarker 672 -3594 600 CreateMarker 546 -3481 600 CreateMarker 645 -3373 600 CreateMarker 638 -3214 600 CreateMarker 650 -3057 600 CreateMarker 514 -3079 600 CreateMarker 357 -3027 600 CreateMarker 331 -3152 600 CreateMarker 206 -3140 600 CreateMarker -3 -3102 600 CreateMarker -183 -3023 600 CreateMarker -121 -3242 600 CreateMarker -193 -3392 600 CreateMarker -372 -3392 600 CreateMarker 175 -3684 600 CreateMarker 167 -3518 600 CreateMarker 46 -3594 600 CreateMarker 779 -3374 440 CreateMarker 747 -3697 408 CreateMarker 888 -3703 408 CreateMarker 1027 -3700 344 CreateMarker 1103 -3560 264 CreateMarker 1082 -3386 184 CreateMarker 1104 -3237 184 CreateMarker 854 -3139 184 CreateMarker 930 -3278 184 CreateMarker 1175 -3120 184 CreateMarker 1305 -3127 184 CreateMarker 1187 -2985 184 CreateMarker 1178 -2822 184 CreateMarker 1337 -2760 184 CreateMarker 1160 -2683 184 CreateMarker 1180 -2560 184 CreateMarker 1260 -2443 184 CreateMarker 1253 -2207 312 CreateMarker 1252 -2101 312 CreateMarker 810 -2368 296 CreateMarker 808 -2233 292 SetZone 1 6 SetZone 3 8 SetZone 4 8 SetZone 5 4 SetZone 6 4 SetZone 7 1 SetZone 8 4 SetZone 9 6 SetZone 10 5 SetZone 11 4 SetZone 12 2 SetZone 13 7 SetZone 14 1 SetZone 15 2 SetZone 16 1 SetZone 17 5 SetZone 18 2 SetZone 19 7 SetZone 20 8 SetZone 21 6 SetZone 22 1 SetZone 23 1 SetZone 24 7 SetZone 25 7 SetZone 26 7 SetZone 27 7 SetZone 28 7 SetZone 29 6 SetZone 30 6 SetZone 31 6 SetZone 32 5 SetZone 33 5 SetZone 34 5 SetZone 35 3 SetZone 36 3 SetZone 37 4 SetZone 38 4 SetZone 39 4 SetZone 40 3 SetZone 41 3 SetZone 42 3 SetZone 43 5 SetZone 44 7 SetZone 45 7 SetZone 46 8 SetZone 47 3 SetZone 48 4 SetZone 49 6 SetZone 50 2 SetZone 51 7 SetZone 52 6 SetZone 53 1 SetZone 54 1 SetZone 55 3 SetZone 56 1 SetZone 57 5 SetZone 58 7 SetZone 59 1 SetZone 60 1 SetZone 61 1 SetZone 62 1 SetZone 63 1 SetZone 64 1 SetZone 65 1 SetZone 66 1 SetZone 67 1 SetZone 68 1 SetZone 69 1 SetZone 70 1 SetZone 71 1 SetZone 72 1 SetZone 73 1 SetZone 74 2 SetZone 75 2 SetZone 76 2 SetZone 77 2 SetZone 78 2 SetZone 79 2 SetZone 80 2 SetZone 81 2 SetZone 82 3 SetZone 83 3 SetZone 84 3 SetZone 85 3 SetZone 86 3 SetZone 87 3 SetZone 88 3 SetZone 89 3 SetZone 90 3 SetZone 91 3 SetZone 92 3 SetZone 93 3 SetZone 94 3 SetZone 95 3 SetZone 96 3 SetZone 97 3 SetZone 98 3 SetZone 99 3 SetZone 100 4 SetZone 101 4 SetZone 102 4 SetZone 103 4 SetZone 104 4 SetZone 105 4 SetZone 106 4 SetZone 107 4 SetZone 108 4 SetZone 109 4 SetZone 110 4 SetZone 111 4 SetZone 112 4 SetZone 113 4 SetZone 114 4 SetZone 115 4 SetZone 116 4 SetZone 117 5 SetZone 118 5 SetZone 119 5 SetZone 120 5 SetZone 121 5 SetZone 122 5 SetZone 123 5 SetZone 124 5 SetZone 125 5 SetZone 126 5 SetZone 127 5 SetZone 128 5 SetZone 129 5 SetZone 130 5 SetZone 131 5 SetZone 132 5 SetZone 133 5 SetZone 134 5 SetZone 135 5 SetZone 136 6 SetZone 137 6 SetZone 138 6 SetZone 139 6 SetZone 140 6 SetZone 141 6 SetZone 142 6 SetZone 143 6 SetZone 144 6 SetZone 145 6 SetZone 146 6 SetZone 147 6 SetZone 148 6 SetZone 149 6 SetZone 150 6 SetZone 151 6 SetZone 152 6 SetZone 153 6 SetZone 154 6 SetZone 155 6 SetZone 156 6 SetZone 157 6 SetZone 158 6 SetZone 159 7 SetZone 160 7 SetZone 161 7 SetZone 162 7 SetZone 163 7 SetZone 164 7 SetZone 165 7 SetZone 166 7 SetZone 167 7 SetZone 168 7 SetZone 169 7 SetZone 170 7 SetZone 171 7 SetZone 172 7 SetZone 173 7 SetZone 174 7 SetZone 175 7 SetZone 176 8 SetZone 177 8 SetZone 178 1 SetZone 179 1 SetMarkerPath 1 1 149 SetMarkerPath 3 1 176 SetMarkerPath 3 2 20 SetMarkerPath 6 1 105 SetMarkerPath 6 2 176 SetGoal 7 6 SetMarkerPath 7 1 60 SetMarkerPathFlags 7 1 j SetGoal 8 10 SetMarkerPath 8 1 114 SetMarkerPath 8 2 96 SetMarkerPathFlags 8 2 j SetGoal 9 11 SetMarkerPath 9 1 138 SetMarkerPath 9 2 139 SetMarkerPath 9 3 10 SetMarkerPathFlags 9 3 j SetGoal 10 4 SetMarkerPath 10 1 135 SetMarkerPath 10 2 132 SetMarkerPath 10 3 123 SetMarkerPath 10 4 130 SetGoal 11 5 SetMarkerPath 11 1 102 SetMarkerPath 11 2 104 SetGoal 12 9 SetMarkerPath 12 1 74 SetMarkerPathFlags 12 1 j SetMarkerPath 12 2 75 SetGoal 13 7 SetMarkerPath 13 1 175 SetMarkerPath 13 2 174 SetGoal 14 13 SetMarkerPath 14 1 22 SetMarkerPath 14 2 23 SetMarkerPath 14 3 61 SetGoal 15 1 SetMarkerPath 15 1 79 SetGoal 16 3 SetMarkerPath 16 1 13 SetMarkerPathFlags 16 1 j SetGoal 17 2 SetMarkerPath 17 1 57 SetMarkerPath 17 2 118 SetMarkerPath 18 1 81 SetMarkerPath 18 2 80 SetGoal 19 12 SetGoal 20 23 SetMarkerPath 20 1 3 SetMarkerPath 20 2 46 SetGoal 21 24 SetMarkerPath 21 1 152 SetMarkerPath 21 2 153 SetGoal 22 13 SetMarkerPath 22 1 61 SetMarkerPath 22 2 14 SetGoal 23 13 SetMarkerPath 23 1 61 SetMarkerPath 23 2 14 SetGoal 24 17 SetMarkerPath 24 1 25 SetMarkerPath 24 2 175 SetGoal 25 17 SetMarkerPath 25 1 24 SetMarkerPath 25 2 175 SetGoal 26 15 SetMarkerPath 26 1 45 SetMarkerPath 26 2 167 SetGoal 27 16 SetMarkerPath 27 1 172 SetMarkerPath 27 2 169 SetGoal 28 12 SetMarkerPath 28 1 44 SetMarkerPath 28 2 160 SetMarkerPath 28 3 51 SetMarkerPath 28 4 159 SetMarkerPath 28 5 161 SetGoal 29 11 SetMarkerPath 29 1 157 SetMarkerPath 29 2 49 SetGoal 30 24 SetMarkerPath 30 1 31 SetMarkerPath 30 2 151 SetMarkerPath 30 3 153 SetGoal 31 24 SetMarkerPath 31 1 30 SetMarkerPath 31 2 52 SetMarkerPath 31 3 150 SetGoal 32 18 SetMarkerPath 32 1 120 SetMarkerPath 32 2 33 SetGoal 33 18 SetMarkerPath 33 1 34 SetMarkerPath 33 2 32 SetMarkerPath 33 3 121 SetGoal 34 18 SetMarkerPath 34 1 43 SetMarkerPath 34 2 33 SetMarkerPath 34 3 121 SetGoal 35 20 SetMarkerPath 35 1 36 SetMarkerPath 35 2 82 SetMarkerPath 35 3 83 SetGoal 36 20 SetMarkerPath 36 1 55 SetMarkerPath 36 2 35 SetMarkerPath 36 3 83 SetGoal 37 22 SetMarkerPath 37 1 38 SetGoal 38 22 SetMarkerPath 38 1 37 SetMarkerPath 38 2 100 SetGoal 39 23 SetMarkerPath 39 1 107 SetGoal 40 20 SetMarkerPath 40 1 85 SetMarkerPath 40 2 41 SetGoal 41 20 SetMarkerPath 41 1 40 SetMarkerPath 41 2 55 SetMarkerPath 41 3 85 SetMarkerPath 42 1 97 SetMarkerPath 42 2 98 SetMarkerPath 43 1 34 SetMarkerPath 43 2 121 SetMarkerPath 44 1 28 SetMarkerPath 44 2 51 SetMarkerPath 44 3 159 SetMarkerPath 45 1 166 SetMarkerPath 45 2 63 SetMarkerPath 45 3 26 SetMarkerPath 46 1 20 SetMarkerPath 46 2 177 SetMarkerPath 47 1 82 SetMarkerPath 47 2 81 SetMarkerPath 48 1 100 SetMarkerPath 48 2 101 SetGoal 49 11 SetMarkerPath 49 1 158 SetMarkerPath 49 2 29 SetMarkerPath 49 3 157 SetGoal 50 8 SetMarkerPath 50 1 76 SetMarkerPath 50 2 75 SetGoal 51 12 SetMarkerPath 51 1 28 SetMarkerPath 51 2 44 SetGoal 52 24 SetMarkerPath 52 1 149 SetMarkerPath 52 2 31 SetMarkerPath 52 3 150 SetGoal 53 14 SetMarkerPath 53 1 72 SetMarkerPath 53 2 54 SetGoal 54 14 SetMarkerPath 54 1 53 SetMarkerPath 54 2 71 SetGoal 55 20 SetMarkerPath 55 1 36 SetMarkerPath 55 2 84 SetMarkerPath 55 3 41 SetGoal 56 14 SetMarkerPath 56 1 71 SetMarkerPath 56 2 70 SetGoal 57 19 SetMarkerPath 57 1 93 SetMarkerPath 57 2 17 SetMarkerPath 57 3 117 SetMarkerPath 57 4 118 SetGoal 58 15 SetMarkerPath 58 1 168 SetMarkerPath 58 2 166 SetMarkerPath 59 1 7 SetMarkerPathFlags 59 1 j SetMarkerPath 60 1 173 SetMarkerPathFlags 60 1 j SetMarkerPath 60 2 16 SetMarkerPathFlags 60 2 j SetMarkerPath 61 1 67 SetMarkerPath 61 2 22 SetMarkerPath 61 3 23 SetMarkerPath 61 4 62 SetMarkerPath 61 5 66 SetMarkerPath 61 6 14 SetMarkerPath 62 1 61 SetMarkerPath 62 2 63 SetMarkerPath 62 3 70 SetMarkerPathFlags 62 3 j SetMarkerPath 62 4 71 SetMarkerPathFlags 62 4 j SetMarkerPath 62 5 66 SetMarkerPath 63 1 62 SetMarkerPath 63 2 166 SetMarkerPath 63 3 45 SetMarkerPath 64 1 65 SetMarkerPath 64 2 178 SetMarkerPath 64 3 179 SetMarkerPath 65 1 66 SetMarkerPath 65 2 64 SetMarkerPath 65 3 178 SetMarkerPath 66 1 61 SetMarkerPath 66 2 65 SetMarkerPath 66 3 62 SetMarkerPath 67 1 70 SetMarkerPath 67 2 61 SetMarkerPath 67 3 68 SetMarkerPath 68 1 69 SetMarkerPath 68 2 67 SetMarkerPath 68 3 178 SetMarkerPath 69 1 178 SetMarkerPath 69 2 179 SetMarkerPath 69 3 68 SetMarkerPath 70 1 56 SetMarkerPath 70 2 67 SetMarkerPath 71 1 56 SetMarkerPath 71 2 54 SetMarkerPath 72 1 73 SetMarkerPath 72 2 53 SetMarkerPath 73 1 72 SetMarkerPath 73 2 76 SetMarkerPath 73 3 77 SetMarkerPath 73 4 78 SetMarkerPath 74 1 12 SetMarkerPath 75 1 12 SetMarkerPath 75 2 76 SetMarkerPath 75 3 50 SetMarkerPath 76 1 77 SetMarkerPath 76 2 50 SetMarkerPath 76 3 75 SetMarkerPath 76 4 73 SetMarkerPath 76 5 80 SetMarkerPath 77 1 80 SetMarkerPath 77 2 76 SetMarkerPath 77 3 73 SetMarkerPath 77 4 78 SetMarkerPath 77 5 79 SetMarkerPath 78 1 77 SetMarkerPath 78 2 73 SetMarkerPath 78 3 79 SetMarkerPath 79 1 77 SetMarkerPath 79 2 15 SetMarkerPath 79 3 80 SetMarkerPath 79 4 78 SetMarkerPath 80 1 18 SetMarkerPath 80 2 77 SetMarkerPath 80 3 79 SetMarkerPath 80 4 76 SetMarkerPath 81 1 18 SetMarkerPath 81 2 47 SetMarkerPath 81 3 83 SetMarkerPath 82 1 35 SetMarkerPath 82 2 47 SetMarkerPath 82 3 83 SetMarkerPath 83 1 81 SetMarkerPath 83 2 82 SetMarkerPath 83 3 84 SetMarkerPath 83 4 35 SetMarkerPath 83 5 36 SetMarkerPath 84 1 55 SetMarkerPath 84 2 83 SetMarkerPath 84 3 85 SetMarkerPath 85 1 40 SetMarkerPath 85 2 41 SetMarkerPath 85 3 84 SetMarkerPath 85 4 86 SetMarkerPath 86 1 85 SetMarkerPath 86 2 87 SetMarkerPath 87 1 86 SetMarkerPath 87 2 88 SetMarkerPath 87 3 89 SetMarkerPath 88 1 87 SetMarkerPath 88 2 95 SetMarkerPath 88 3 97 SetMarkerPath 88 4 96 SetMarkerPath 88 5 89 SetMarkerPath 89 1 88 SetMarkerPath 89 2 90 SetMarkerPath 89 3 50 SetMarkerPathFlags 89 3 j SetMarkerPath 89 4 87 SetMarkerPath 90 1 89 SetMarkerPath 90 2 91 SetMarkerPath 91 1 90 SetMarkerPath 91 2 92 SetMarkerPath 91 3 117 SetMarkerPath 92 1 91 SetMarkerPath 92 2 93 SetMarkerPath 92 3 85 SetMarkerPathFlags 92 3 j SetMarkerPath 93 1 92 SetMarkerPath 93 2 94 SetMarkerPath 93 3 57 SetMarkerPath 94 1 93 SetMarkerPath 94 2 155 SetMarkerPath 95 1 88 SetMarkerPath 95 2 96 SetMarkerPath 95 3 82 SetMarkerPathFlags 95 3 j SetMarkerPath 96 1 97 SetMarkerPath 96 2 88 SetMarkerPath 96 3 95 SetMarkerPath 97 1 96 SetMarkerPath 97 2 88 SetMarkerPath 97 3 42 SetMarkerPath 97 4 98 SetMarkerPath 98 1 42 SetMarkerPath 98 2 99 SetMarkerPath 98 3 97 SetMarkerPath 99 1 98 SetMarkerPath 99 2 100 SetMarkerPath 100 1 99 SetMarkerPath 100 2 48 SetMarkerPath 100 3 101 SetMarkerPath 100 4 38 SetMarkerPath 101 1 48 SetMarkerPath 101 2 100 SetMarkerPath 101 3 102 SetMarkerPath 101 4 103 SetMarkerPath 102 1 101 SetMarkerPath 102 2 11 SetMarkerPath 102 3 103 SetMarkerPath 103 1 104 SetMarkerPath 103 2 106 SetMarkerPath 103 3 102 SetMarkerPath 103 4 101 SetMarkerPath 104 1 11 SetMarkerPath 104 2 103 SetMarkerPath 104 3 105 SetMarkerPath 105 1 106 SetMarkerPath 105 2 107 SetMarkerPath 105 3 6 SetMarkerPath 105 4 104 SetMarkerPath 106 1 103 SetMarkerPath 106 2 105 SetMarkerPath 106 3 107 SetMarkerPath 106 4 38 SetMarkerPathFlags 106 4 j SetMarkerPath 107 1 105 SetMarkerPath 107 2 106 SetMarkerPath 107 3 108 SetMarkerPath 107 4 39 SetMarkerPath 108 1 107 SetMarkerPath 108 2 109 SetMarkerPath 109 1 108 SetMarkerPath 109 2 100 SetMarkerPathFlags 109 2 j SetMarkerPath 109 3 114 SetMarkerPath 109 4 110 SetMarkerPath 110 1 114 SetMarkerPath 110 2 109 SetMarkerPath 110 3 115 SetMarkerPathFlags 110 3 j SetMarkerPath 111 1 112 SetMarkerPath 111 2 114 SetMarkerPath 111 3 115 SetMarkerPathFlags 111 3 j SetMarkerPath 112 1 113 SetMarkerPath 112 2 111 SetMarkerPath 112 3 89 SetMarkerPathFlags 112 3 j SetMarkerPath 113 1 114 SetMarkerPath 113 2 112 SetMarkerPath 113 3 96 SetMarkerPathFlags 113 3 j SetMarkerPath 114 1 109 SetMarkerPath 114 2 113 SetMarkerPath 114 3 111 SetMarkerPath 114 4 110 SetMarkerPath 114 5 8 SetMarkerPath 115 1 116 SetMarkerPath 116 1 115 SetMarkerPath 116 2 77 SetMarkerPathFlags 116 2 j SetMarkerPath 117 1 57 SetMarkerPath 117 2 118 SetMarkerPath 117 3 119 SetMarkerPath 117 4 91 SetMarkerPath 118 1 17 SetMarkerPath 118 2 117 SetMarkerPath 118 3 119 SetMarkerPath 118 4 57 SetMarkerPath 119 1 117 SetMarkerPath 119 2 120 SetMarkerPath 119 3 118 SetMarkerPath 120 1 119 SetMarkerPath 120 2 121 SetMarkerPath 120 3 32 SetMarkerPath 121 1 120 SetMarkerPath 121 2 43 SetMarkerPath 121 3 34 SetMarkerPath 121 4 33 SetMarkerPath 121 5 122 SetMarkerPath 122 1 121 SetMarkerPath 122 2 124 SetMarkerPath 122 3 123 SetMarkerPath 122 4 133 SetMarkerPath 123 1 132 SetMarkerPath 123 2 133 SetMarkerPath 123 3 10 SetMarkerPath 123 4 124 SetMarkerPath 123 5 122 SetMarkerPath 124 1 122 SetMarkerPath 124 2 125 SetMarkerPath 124 3 123 SetMarkerPath 124 4 135 SetMarkerPath 125 1 126 SetMarkerPath 125 2 124 SetMarkerPath 126 1 135 SetMarkerPath 126 2 125 SetMarkerPath 126 3 127 SetMarkerPath 126 4 160 SetMarkerPath 127 1 128 SetMarkerPath 127 2 135 SetMarkerPath 127 3 126 SetMarkerPath 127 4 160 SetMarkerPath 128 1 129 SetMarkerPath 128 2 127 SetMarkerPath 129 1 130 SetMarkerPath 129 2 128 SetMarkerPath 129 3 135 SetMarkerPath 130 1 10 SetMarkerPath 130 2 131 SetMarkerPath 130 3 129 SetMarkerPath 130 4 132 SetMarkerPath 131 1 130 SetMarkerPath 132 1 10 SetMarkerPath 132 2 123 SetMarkerPath 132 3 130 SetMarkerPath 133 1 134 SetMarkerPath 133 2 123 SetMarkerPath 133 3 122 SetMarkerPath 134 1 133 SetMarkerPath 134 2 136 SetMarkerPath 135 1 126 SetMarkerPath 135 2 10 SetMarkerPath 135 3 127 SetMarkerPath 135 4 129 SetMarkerPath 135 5 124 SetMarkerPath 136 1 137 SetMarkerPath 136 2 134 SetMarkerPath 137 1 136 SetMarkerPath 137 2 138 SetMarkerPath 137 3 156 SetMarkerPathFlags 137 3 j SetMarkerPath 138 1 137 SetMarkerPath 138 2 9 SetMarkerPath 139 1 9 SetMarkerPath 139 2 140 SetMarkerPath 140 1 139 SetMarkerPath 140 2 141 SetMarkerPath 141 1 140 SetMarkerPath 141 2 142 SetMarkerPath 141 3 10 SetMarkerPathFlags 141 3 j SetMarkerPath 142 1 141 SetMarkerPath 142 2 143 SetMarkerPath 142 3 144 SetMarkerPath 143 1 142 SetMarkerPath 143 2 144 SetMarkerPath 143 3 123 SetMarkerPathFlags 143 3 j SetMarkerPath 144 1 143 SetMarkerPath 144 2 142 SetMarkerPath 144 3 145 SetMarkerPath 145 1 144 SetMarkerPath 145 2 146 SetMarkerPath 146 1 145 SetMarkerPath 146 2 147 SetMarkerPath 147 1 146 SetMarkerPath 147 2 148 SetMarkerPath 148 1 147 SetMarkerPath 148 2 149 SetMarkerPath 148 3 12 SetMarkerPathFlags 148 3 j SetMarkerPath 149 1 148 SetMarkerPath 149 2 1 SetMarkerPath 149 3 52 SetMarkerPath 149 4 150 SetMarkerPath 150 1 149 SetMarkerPath 150 2 31 SetMarkerPath 150 3 52 SetMarkerPath 151 1 30 SetMarkerPath 151 2 152 SetMarkerPath 152 1 151 SetMarkerPath 152 2 21 SetMarkerPath 152 3 91 SetMarkerPathFlags 152 3 j SetMarkerPath 153 1 21 SetMarkerPath 153 2 154 SetMarkerPath 153 3 30 SetMarkerPath 154 1 153 SetMarkerPath 154 2 155 SetMarkerPath 154 3 17 SetMarkerPathFlags 154 3 j SetMarkerPath 155 1 154 SetMarkerPath 155 2 94 SetMarkerPath 156 1 158 SetMarkerPathFlags 156 1 j SetMarkerPath 157 1 29 SetMarkerPath 157 2 158 SetMarkerPath 157 3 49 SetMarkerPath 157 4 123 SetMarkerPathFlags 157 4 j SetMarkerPath 158 1 157 SetMarkerPath 158 2 49 SetMarkerPath 158 3 136 SetMarkerPathFlags 158 3 j SetMarkerPath 159 1 28 SetMarkerPath 159 2 166 SetMarkerPathFlags 159 2 j SetMarkerPath 159 3 44 SetMarkerPath 160 1 28 SetMarkerPath 160 2 127 SetMarkerPath 160 3 126 SetMarkerPath 160 4 161 SetMarkerPath 161 1 162 SetMarkerPath 161 2 160 SetMarkerPath 161 3 28 SetMarkerPath 162 1 163 SetMarkerPath 162 2 161 SetMarkerPath 163 1 164 SetMarkerPath 163 2 162 SetMarkerPath 164 1 165 SetMarkerPath 164 2 163 SetMarkerPath 164 3 167 SetMarkerPath 165 1 164 SetMarkerPath 165 2 167 SetMarkerPath 165 3 168 SetMarkerPath 166 1 58 SetMarkerPath 166 2 63 SetMarkerPath 166 3 45 SetMarkerPath 166 4 167 SetMarkerPath 167 1 26 SetMarkerPath 167 2 166 SetMarkerPath 167 3 165 SetMarkerPath 167 4 164 SetMarkerPath 168 1 169 SetMarkerPath 168 2 58 SetMarkerPath 168 3 170 SetMarkerPath 168 4 165 SetMarkerPath 169 1 27 SetMarkerPath 169 2 168 SetMarkerPath 170 1 171 SetMarkerPath 170 2 168 SetMarkerPath 171 1 173 SetMarkerPath 171 2 170 SetMarkerPath 171 3 172 SetMarkerPath 171 4 16 SetMarkerPathFlags 171 4 r SetMarkerPath 172 1 171 SetMarkerPath 172 2 27 SetMarkerPath 173 1 174 SetMarkerPath 173 2 171 SetMarkerPath 174 1 175 SetMarkerPath 174 2 13 SetMarkerPath 174 3 173 SetMarkerPath 175 1 174 SetMarkerPath 175 2 24 SetMarkerPath 175 3 25 SetMarkerPath 175 4 13 SetMarkerPath 176 1 3 SetMarkerPath 176 2 177 SetMarkerPath 176 3 175 SetMarkerPathFlags 176 3 j SetMarkerPath 177 1 46 SetMarkerPath 177 2 176 SetMarkerPath 178 1 179 SetMarkerPath 178 2 64 SetMarkerPath 178 3 69 SetMarkerPath 178 4 68 SetMarkerPath 178 5 65 SetMarkerPath 178 6 14 SetMarkerPathFlags 178 6 j SetMarkerPath 179 1 178 SetMarkerPath 179 2 69 SetMarkerPath 179 3 64 SetMarkerPath 179 4 59 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/shifter.bot000066400000000000000000000321051475442401000264130ustar00rootroot00000000000000CreateMarker 760 720 248 CreateMarker 465 678 344 CreateMarker 765 607 248 CreateMarker 924 529 248 CreateMarker 909 282 156 CreateMarker 737 191 152 CreateMarker 860 60 152 CreateMarker 858 -127 152 CreateMarker 1017 -300 152 CreateMarker 1026 -543 216 CreateMarker 447 -276 152 CreateMarker 149 -230 152 CreateMarker -89 -240 152 CreateMarker -342 -91 152 CreateMarker -452 164 152 CreateMarker -294 184 152 CreateMarker -208 13 152 CreateMarker -449 315 152 CreateMarker -351 508 120 CreateMarker 516 305 152 CreateMarker 396 421 152 CreateMarker 150 597 120 CreateMarker -59 710 104 CreateMarker -137 344 88 CreateMarker -137 169 88 CreateMarker 89 161 24 CreateMarker 253 155 24 CreateMarker 245 298 24 CreateMarker 237 -92 -24 CreateMarker 263 -287 -24 CreateMarker 443 -425 -24 CreateMarker 645 -434 -24 CreateMarker 932 -510 -24 CreateMarker 759 -747 220 CreateMarker 611 -656 216 CreateMarker 687 -458 344 CreateMarker 865 -187 344 CreateMarker 236 -780 344 CreateMarker 181 -556 344 CreateMarker 161 -335 344 CreateMarker 152 -124 344 CreateMarker -1 23 344 CreateMarker -72 -262 344 CreateMarker -235 164 348 CreateMarker -86 438 344 CreateMarker 130 636 344 CreateMarker 348 659 344 CreateMarker 284 382 348 CreateMarker 473 352 344 CreateMarker 681 167 344 CreateMarker 698 -38 344 CreateMarker 1028 -52 344 CreateMarker 428 -616 280 CreateMarker 55 -214 344 CreateMarker 534 179 344 CreateMarker -374 38 152 CreateMarker 809 200 348 CreateMarker 8 115 344 CreateMarker 332 -119 -24 CreateMarker 340 -103 344 CreateMarker 618 653 156 CreateMarker 817 -337 152 CreateMarker 944 -208 -48 CreateMarker 900 190 152 SetZone 1 11 SetMarkerPath 1 0 2 SetZone 2 9 SetMarkerPath 2 0 77 SetZone 3 1 SetMarkerPath 3 0 4 SetZone 4 7 SetMarkerPath 4 0 43 SetMarkerPath 4 1 88 SetMarkerPath 4 2 87 SetZone 5 3 SetMarkerPath 5 0 6 SetZone 6 9 SetMarkerPath 6 0 79 SetMarkerPath 6 1 80 SetZone 7 1 SetMarkerPath 7 0 69 SetMarkerPath 7 1 24 SetMarkerPath 7 2 68 SetGoal 8 1 SetZone 8 11 SetMarkerPath 8 0 33 SetMarkerPath 8 1 32 SetGoal 9 2 SetZone 9 7 SetMarkerPath 9 0 88 SetMarkerPath 9 1 43 SetMarkerPath 9 2 89 SetMarkerPath 9 3 90 SetGoal 10 17 SetZone 10 8 SetMarkerPath 10 0 81 SetMarkerPath 10 1 95 SetMarkerPath 10 2 101 SetGoal 11 19 SetZone 11 7 SetMarkerPath 11 0 31 SetMarkerPath 11 1 41 SetZone 12 4 SetMarkerPath 12 0 50 SetMarkerPath 12 1 18 SetZone 13 8 SetMarkerPath 13 0 84 SetMarkerPath 13 1 30 SetZone 14 6 SetMarkerPath 14 0 29 SetMarkerPath 14 1 42 SetMarkerPath 14 2 45 SetZone 15 2 SetMarkerPath 15 0 60 SetMarkerPath 15 1 59 SetZone 16 10 SetMarkerPath 16 0 75 SetMarkerPath 16 1 76 SetGoal 17 3 SetZone 17 11 SetMarkerPath 17 0 73 SetMarkerPath 17 1 40 SetMarkerPath 17 2 38 SetMarkerPath 17 3 74 SetGoal 18 15 SetZone 18 4 SetMarkerPath 18 0 49 SetMarkerPath 18 1 12 SetMarkerPath 18 2 50 SetMarkerPath 18 3 27 SetMarkerPath 18 4 52 SetMarkerPath 18 5 103 SetGoal 19 15 SetZone 19 8 SetMarkerPath 19 0 84 SetMarkerPath 19 1 30 SetMarkerPath 19 2 13 SetGoal 20 16 SetZone 20 9 SetMarkerPath 20 0 77 SetMarkerPath 20 1 21 SetGoal 21 16 SetZone 21 9 SetMarkerPath 21 0 20 SetMarkerPath 21 1 79 SetMarkerPath 21 2 77 SetMarkerPath 21 3 94 SetMarkerPath 21 4 80 SetGoal 22 4 SetZone 22 3 SetMarkerPath 22 0 58 SetMarkerPath 22 1 57 SetMarkerPathAngleHint 22 1 -20 SetMarkerPath 22 2 53 SetMarkerPath 22 3 66 SetMarkerPath 22 4 67 SetMarkerPath 22 5 68 SetMarkerPath 22 6 70 SetMarkerPath 22 7 90 SetMarkerPathFlags 22 7 r SetRocketJumpPathFields 22 7 70.0 225.0 0 SetGoal 23 16 SetZone 23 1 SetMarkerPath 23 0 68 SetMarkerPath 23 1 24 SetMarkerPath 23 2 69 SetMarkerPath 23 3 70 SetGoal 24 16 SetZone 24 1 SetMarkerPath 24 0 68 SetMarkerPath 24 1 7 SetMarkerPath 24 2 69 SetMarkerPath 24 3 23 SetGoal 25 18 SetZone 25 1 SetMarkerPath 25 0 67 SetMarkerPath 25 1 68 SetMarkerPath 25 2 69 SetMarkerPath 25 3 3 SetGoal 26 16 SetZone 26 2 SetMarkerPath 26 0 63 SetMarkerPath 26 1 64 SetMarkerPath 26 2 39 SetMarkerPath 26 3 60 SetMarkerPath 26 4 65 SetGoal 27 16 SetZone 27 4 SetMarkerPath 27 0 18 SetMarkerPath 27 1 52 SetMarkerPath 27 2 28 SetGoal 28 16 SetZone 28 4 SetMarkerPath 28 0 27 SetMarkerPath 28 1 52 SetMarkerPath 28 2 53 SetGoal 29 16 SetZone 29 6 SetMarkerPath 29 0 14 SetMarkerPath 29 1 44 SetMarkerPath 29 2 42 SetMarkerPath 29 3 45 SetMarkerPath 29 4 41 SetMarkerPathFlags 29 4 r SetRocketJumpPathFields 29 4 50.0 98.0 0 SetGoal 30 16 SetZone 30 8 SetMarkerPath 30 0 84 SetMarkerPath 30 1 13 SetMarkerPath 30 2 83 SetMarkerPath 30 3 85 SetMarkerPath 30 4 19 SetMarkerPath 30 5 99 SetGoal 31 19 SetZone 31 7 SetMarkerPath 31 0 43 SetMarkerPathAngleHint 31 0 -20 SetMarkerPath 31 1 11 SetMarkerPath 31 2 29 SetGoal 32 19 SetZone 32 11 SetMarkerPath 32 0 8 SetMarkerPath 32 1 72 SetGoal 33 19 SetZone 33 11 SetMarkerPath 33 0 71 SetMarkerPath 33 1 8 SetGoal 34 18 SetZone 34 10 SetMarkerPath 34 0 37 SetMarkerPath 34 1 75 SetGoal 35 15 SetZone 35 5 SetMarkerPath 35 0 62 SetMarkerPath 35 1 63 SetMarkerPath 35 2 44 SetMarkerPathFlags 35 2 r SetRocketJumpPathFields 35 2 40.0 190.0 5 SetMarkerPath 35 3 102 SetGoal 36 18 SetZone 36 5 SetMarkerPath 36 0 47 SetMarkerPath 36 1 61 SetMarkerPath 36 2 69 SetMarkerPath 36 3 22 SetMarkerPathFlags 36 3 r SetRocketJumpPathFields 36 3 35.0 20.0 0 SetMarkerPath 36 4 89 SetMarkerPathFlags 36 4 r SetRocketJumpPathFields 36 4 67.0 325.0 0 SetMarkerPath 36 5 99 SetMarkerPathFlags 36 5 r SetRocketJumpPathFields 36 5 72.0 360.0 0 SetMarkerPath 36 6 70 SetGoal 37 18 SetZone 37 10 SetMarkerPath 37 0 51 SetMarkerPath 37 1 34 SetZone 38 11 SetMarkerPath 38 0 17 SetMarkerPath 38 1 74 SetMarkerPath 38 2 73 SetGoal 39 5 SetZone 39 2 SetMarkerPath 39 0 64 SetMarkerPath 39 1 26 SetMarkerPath 39 2 60 SetMarkerPath 39 3 85 SetMarkerPathFlags 39 3 r SetRocketJumpPathFields 39 3 80.0 90.0 0 SetMarkerPath 39 4 87 SetMarkerPathFlags 39 4 r SetRocketJumpPathFields 39 4 80.0 180.0 0 SetGoal 40 6 SetZone 40 11 SetMarkerPath 40 0 17 SetMarkerPath 40 1 73 SetMarkerPath 40 2 74 SetGoal 41 7 SetZone 41 7 SetMarkerPath 41 0 98 SetMarkerPath 41 1 46 SetMarkerPath 41 2 29 SetZone 42 6 SetMarkerPath 42 0 14 SetMarkerPath 42 1 29 SetMarkerPath 42 2 43 SetMarkerPath 42 3 44 SetZone 43 7 SetMarkerPath 43 0 4 SetMarkerPath 43 1 88 SetMarkerPath 43 2 42 SetMarkerPath 43 4 31 SetMarkerPathAngleHint 43 4 20 SetMarkerPath 43 5 9 SetZone 44 6 SetMarkerPath 44 0 29 SetMarkerPath 44 1 42 SetMarkerPath 44 2 45 SetMarkerPath 44 3 35 SetZone 45 6 SetMarkerPath 45 0 14 SetMarkerPath 45 1 29 SetMarkerPath 45 2 46 SetMarkerPath 45 3 44 SetZone 46 4 SetMarkerPath 46 0 45 SetMarkerPath 46 1 47 SetMarkerPath 46 3 41 SetMarkerPathFlags 46 3 r SetRocketJumpPathFields 46 3 80.0 0.0 1 SetMarkerPath 46 4 105 SetZone 47 4 SetMarkerPath 47 0 46 SetMarkerPath 47 1 48 SetMarkerPath 47 2 36 SetMarkerPath 47 3 61 SetMarkerPath 47 4 105 SetZone 48 4 SetMarkerPath 48 1 47 SetMarkerPath 48 2 49 SetMarkerPath 48 3 105 SetZone 49 4 SetMarkerPath 49 0 48 SetMarkerPath 49 1 18 SetMarkerPath 49 2 50 SetMarkerPath 49 3 103 SetZone 50 4 SetMarkerPath 50 0 49 SetMarkerPath 50 1 12 SetMarkerPath 50 2 18 SetMarkerPath 50 3 51 SetMarkerPath 50 4 103 SetZone 51 10 SetMarkerPath 51 0 50 SetMarkerPath 51 1 37 SetMarkerPath 51 2 17 SetMarkerPath 51 3 78 SetMarkerPathFlags 51 3 r SetRocketJumpPathFields 51 3 55.0 305.0 0 SetZone 52 4 SetMarkerPath 52 0 18 SetMarkerPath 52 1 27 SetMarkerPath 52 2 28 SetMarkerPath 52 3 53 SetZone 53 3 SetMarkerPath 53 0 54 SetMarkerPath 53 1 52 SetMarkerPath 53 2 28 SetMarkerPath 53 3 22 SetZone 54 3 SetMarkerPath 54 0 55 SetMarkerPath 54 1 53 SetZone 55 3 SetMarkerPath 55 0 56 SetMarkerPath 55 1 58 SetMarkerPath 55 2 57 SetMarkerPath 55 3 54 SetZone 56 3 SetMarkerPath 56 0 5 SetMarkerPath 56 1 59 SetMarkerPath 56 2 57 SetMarkerPath 56 3 55 SetZone 57 3 SetMarkerPath 57 0 56 SetMarkerPath 57 1 55 SetMarkerPath 57 2 66 SetMarkerPath 57 3 97 SetMarkerPath 57 4 59 SetMarkerPath 57 5 22 SetMarkerPathAngleHint 57 5 20 SetZone 58 3 SetMarkerPath 58 0 55 SetMarkerPath 58 1 22 SetMarkerPath 58 2 97 SetZone 59 2 SetMarkerPath 59 0 56 SetMarkerPath 59 1 57 SetMarkerPath 59 2 60 SetMarkerPath 59 3 15 SetZone 60 2 SetMarkerPath 60 0 26 SetMarkerPath 60 1 65 SetMarkerPath 60 2 59 SetMarkerPath 60 3 15 SetMarkerPath 60 4 39 SetZone 61 5 SetMarkerPath 61 0 36 SetMarkerPath 61 1 47 SetMarkerPath 61 2 62 SetMarkerPath 61 3 22 SetMarkerPathFlags 61 3 r SetRocketJumpPathFields 61 3 42.0 35.0 0 SetMarkerPath 61 4 82 SetMarkerPathFlags 61 4 r SetRocketJumpPathFields 61 4 74.0 40.0 0 SetMarkerPath 61 5 68 SetMarkerPath 61 6 69 SetZone 62 5 SetMarkerPath 62 0 61 SetMarkerPath 62 1 35 SetMarkerPath 62 2 24 SetMarkerPath 62 3 69 SetZone 63 2 SetMarkerPath 63 0 35 SetMarkerPath 63 1 26 SetMarkerPath 63 2 64 SetZone 64 2 SetMarkerPath 64 0 63 SetMarkerPath 64 1 39 SetMarkerPath 64 2 26 SetZone 65 2 SetMarkerPath 65 0 26 SetMarkerPath 65 1 60 SetMarkerPath 65 2 66 SetMarkerPath 65 3 22 SetMarkerPathFlags 65 3 r SetRocketJumpPathFields 65 3 44.0 116.0 0 SetZone 66 1 SetMarkerPath 66 0 65 SetMarkerPath 66 1 67 SetZone 67 1 SetMarkerPath 67 0 66 SetMarkerPath 67 1 25 SetMarkerPath 67 2 69 SetMarkerPath 67 3 68 SetMarkerPath 67 4 70 SetZone 68 1 SetMarkerPath 68 0 67 SetMarkerPath 68 1 25 SetMarkerPath 68 2 69 SetMarkerPath 68 3 24 SetMarkerPath 68 4 23 SetMarkerPath 68 5 70 SetMarkerPath 68 6 100 SetZone 69 1 SetMarkerPath 69 0 67 SetMarkerPath 69 1 68 SetMarkerPath 69 2 7 SetMarkerPath 69 3 3 SetMarkerPath 69 4 24 SetMarkerPath 69 5 25 SetMarkerPath 69 6 23 SetZone 70 1 SetMarkerPath 70 0 67 SetMarkerPath 70 1 68 SetMarkerPath 70 2 23 SetMarkerPath 70 3 71 SetMarkerPath 70 4 100 SetZone 71 11 SetMarkerPath 71 0 70 SetMarkerPath 71 1 33 SetMarkerPath 71 2 72 SetMarkerPath 71 3 100 SetZone 72 11 SetMarkerPath 72 0 71 SetMarkerPath 72 1 32 SetMarkerPath 72 2 73 SetZone 73 11 SetMarkerPath 73 0 72 SetMarkerPath 73 1 17 SetMarkerPath 73 2 40 SetMarkerPath 73 3 38 SetZone 74 11 SetMarkerPath 74 0 17 SetMarkerPath 74 1 40 SetMarkerPath 74 2 38 SetMarkerPath 74 3 1 SetZone 75 10 SetMarkerPath 75 0 34 SetMarkerPath 75 1 16 SetMarkerPath 75 2 76 SetMarkerPath 75 3 17 SetZone 76 10 SetMarkerPath 76 0 75 SetMarkerPath 76 1 94 SetMarkerPath 76 2 16 SetMarkerPath 76 3 103 SetMarkerPathAngleHint 76 3 -10 SetZone 77 9 SetMarkerPath 77 0 2 SetMarkerPath 77 1 75 SetMarkerPath 77 2 50 SetMarkerPath 77 3 78 SetMarkerPathAngleHint 77 3 -20 SetMarkerPath 77 4 20 SetZone 78 9 SetMarkerPath 78 0 77 SetMarkerPathAngleHint 78 0 20 SetMarkerPath 78 1 92 SetMarkerPath 78 2 93 SetZone 79 9 SetMarkerPath 79 0 21 SetMarkerPath 79 1 6 SetMarkerPath 79 2 80 SetZone 80 9 SetMarkerPath 80 0 21 SetMarkerPath 80 1 79 SetMarkerPath 80 2 6 SetMarkerPath 80 3 94 SetMarkerPath 80 4 81 SetZone 81 8 SetMarkerPath 81 0 80 SetMarkerPath 81 1 10 SetMarkerPath 81 2 82 SetMarkerPath 81 3 95 SetZone 82 8 SetMarkerPath 82 0 81 SetMarkerPath 82 1 95 SetMarkerPath 82 2 83 SetMarkerPath 82 3 101 SetZone 83 8 SetMarkerPath 83 0 30 SetMarkerPath 83 1 82 SetMarkerPath 83 2 95 SetMarkerPath 83 3 99 SetZone 84 8 SetMarkerPath 84 0 95 SetMarkerPath 84 1 13 SetMarkerPath 84 2 30 SetMarkerPath 84 3 19 SetZone 85 8 SetMarkerPath 85 0 30 SetMarkerPath 85 1 86 SetMarkerPath 85 2 56 SetMarkerPath 85 3 99 SetMarkerPath 85 4 39 SetZone 86 8 SetMarkerPath 86 0 85 SetMarkerPath 86 1 87 SetMarkerPath 86 2 39 SetZone 87 7 SetMarkerPath 87 0 4 SetMarkerPath 87 1 88 SetMarkerPath 87 2 86 SetMarkerPath 87 3 39 SetZone 88 7 SetMarkerPath 88 0 4 SetMarkerPath 88 1 87 SetMarkerPath 88 2 9 SetMarkerPath 88 3 43 SetZone 89 7 SetMarkerPath 89 0 9 SetMarkerPath 89 1 90 SetMarkerPath 89 2 99 SetMarkerPathAngleHint 89 2 43 SetMarkerPath 89 3 22 SetMarkerPath 89 4 68 SetZone 90 7 SetMarkerPath 90 0 91 SetMarkerPath 90 1 89 SetMarkerPath 90 2 9 SetMarkerPath 90 3 68 SetMarkerPath 90 4 96 SetZone 91 7 SetMarkerPath 91 0 98 SetMarkerPath 91 1 92 SetMarkerPath 91 2 96 SetMarkerPath 91 3 90 SetZone 92 9 SetMarkerPath 92 0 91 SetMarkerPath 92 1 78 SetMarkerPath 92 2 93 SetZone 93 9 SetMarkerPath 93 0 92 SetMarkerPath 93 1 78 SetMarkerPath 93 2 51 SetZone 94 10 SetMarkerPath 94 0 80 SetMarkerPath 94 1 76 SetZone 95 8 SetMarkerPath 95 0 81 SetMarkerPath 95 1 82 SetMarkerPath 95 2 10 SetMarkerPath 95 3 84 SetMarkerPath 95 4 83 SetZone 96 7 SetMarkerPath 96 0 91 SetMarkerPath 96 1 90 SetMarkerPath 96 2 67 SetMarkerPath 96 3 83 SetMarkerPathFlags 96 3 r SetRocketJumpPathFields 96 3 30.0 20.0 0 SetZone 97 3 SetMarkerPath 97 0 58 SetMarkerPath 97 1 57 SetZone 98 7 SetMarkerPath 98 0 41 SetMarkerPath 98 1 11 SetMarkerPathAngleHint 98 1 -20 SetMarkerPath 98 2 91 SetMarkerPath 98 3 45 SetZone 99 8 SetMarkerPath 99 0 83 SetMarkerPath 99 1 85 SetMarkerPath 99 2 30 SetMarkerPath 99 3 89 SetMarkerPathAngleHint 99 3 -30 SetMarkerPath 99 4 23 SetMarkerPath 99 5 69 SetMarkerPath 99 6 91 SetMarkerPathFlags 99 6 r SetRocketJumpPathFields 99 6 30.0 182.0 0 SetZone 100 1 SetMarkerPath 100 0 71 SetMarkerPath 100 1 70 SetMarkerPath 100 2 68 SetMarkerPath 100 3 22 SetMarkerPathFlags 100 3 r SetRocketJumpPathFields 100 3 71.0 330.0 4 SetZone 101 8 SetMarkerPath 101 0 10 SetMarkerPath 101 1 82 SetMarkerPath 101 2 22 SetMarkerPath 101 3 68 SetZone 102 5 SetMarkerPath 102 0 35 SetZone 103 4 SetMarkerPath 103 0 18 SetMarkerPath 103 1 49 SetMarkerPath 103 2 50 SetMarkerPath 103 3 17 SetZone 104 11 SetMarkerPath 104 0 40 SetMarkerPath 104 1 17 SetMarkerPath 104 2 74 SetZone 105 4 SetMarkerPath 105 0 46 SetMarkerPath 105 1 47 SetMarkerPath 105 2 48 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/skull.bot000066400000000000000000000201031475442401000260740ustar00rootroot00000000000000CreateMarker 195 17 -360 CreateMarker 318 -292 -360 CreateMarker 343 -100 -360 CreateMarker 110 -228 -316 CreateMarker -51 -182 -296 CreateMarker -3 106 -296 CreateMarker 149 -100 -360 CreateMarker 382 9 -322 CreateMarker 398 253 -296 CreateMarker 380 369 -296 CreateMarker 367 477 -296 CreateMarker 30 479 -296 CreateMarker 96 260 -296 CreateMarker -81 -467 -296 CreateMarker 88 378 -296 CreateMarker 155 -436 -296 CreateMarker 240 -590 -296 CreateMarker 80 -580 -296 CreateMarker -93 -576 -296 CreateMarker 428 -579 -296 CreateMarker 579 -581 -248 CreateMarker 693 -580 -232 CreateMarker 718 -300 -232 CreateMarker 518 -249 -232 CreateMarker 724 -134 -264 CreateMarker 742 2 -296 CreateMarker 584 134 -296 CreateMarker 517 -129 -192 CreateMarker 524 2 -168 CreateMarker 517 145 -168 CreateMarker 372 262 -168 CreateMarker 247 234 -232 CreateMarker 675 14 -120 CreateMarker 801 1 -56 CreateMarker 982 2 -40 CreateMarker 1008 255 -40 CreateMarker 832 256 -40 CreateMarker 672 255 24 CreateMarker 526 253 56 CreateMarker 377 219 56 CreateMarker 420 361 56 CreateMarker 309 438 56 CreateMarker 208 496 56 CreateMarker 75 343 56 CreateMarker -45 313 56 CreateMarker -47 186 56 CreateMarker -35 42 56 CreateMarker -75 -150 56 CreateMarker 415 -476 -46 CreateMarker 427 -342 -8 CreateMarker 315 -258 -8 CreateMarker 583 -485 -104 CreateMarker 677 -486 -104 CreateMarker 672 -387 -104 SetZone 2 1 SetZone 3 2 SetZone 4 2 SetZone 5 1 SetZone 6 2 SetZone 7 3 SetZone 8 3 SetZone 9 4 SetZone 10 4 SetZone 11 4 SetZone 12 4 SetZone 13 2 SetZone 14 1 SetZone 15 2 SetZone 16 2 SetZone 17 4 SetZone 18 1 SetZone 19 1 SetZone 20 2 SetZone 21 3 SetZone 22 3 SetZone 23 3 SetZone 25 2 SetZone 26 4 SetZone 27 4 SetZone 28 1 SetZone 29 1 SetZone 30 3 SetZone 31 3 SetZone 32 2 SetZone 33 4 SetZone 34 3 SetZone 35 2 SetZone 36 2 SetZone 37 2 SetZone 39 2 SetZone 40 1 SetZone 41 1 SetZone 42 1 SetZone 43 2 SetZone 57 1 SetZone 58 1 SetZone 59 1 SetZone 60 1 SetZone 61 1 SetZone 62 1 SetZone 63 1 SetZone 64 1 SetZone 65 1 SetZone 66 1 SetZone 67 1 SetZone 68 1 SetZone 69 1 SetZone 70 1 SetZone 71 1 SetZone 72 2 SetZone 73 2 SetZone 74 2 SetZone 75 2 SetZone 76 2 SetZone 77 2 SetZone 78 2 SetZone 79 2 SetZone 80 2 SetZone 81 2 SetZone 82 2 SetZone 83 2 SetZone 84 3 SetZone 85 3 SetZone 86 3 SetZone 87 3 SetZone 88 3 SetZone 89 3 SetZone 90 3 SetZone 91 3 SetZone 92 3 SetZone 93 3 SetZone 94 3 SetZone 95 3 SetZone 96 3 SetZone 97 3 SetZone 98 3 SetZone 99 3 SetZone 100 4 SetZone 101 4 SetZone 102 4 SetZone 103 4 SetZone 104 4 SetZone 105 4 SetZone 106 4 SetZone 107 4 SetZone 108 4 SetZone 109 4 SetZone 110 4 SetGoal 2 1 SetMarkerPath 2 1 70 SetMarkerPath 2 2 61 SetMarkerPath 2 3 60 SetGoal 3 3 SetMarkerPath 3 1 36 SetMarkerPath 3 2 76 SetMarkerPath 3 3 73 SetMarkerPath 3 4 72 SetGoal 4 5 SetMarkerPath 4 1 79 SetMarkerPath 4 2 20 SetMarkerPath 4 3 16 SetGoal 5 8 SetMarkerPath 5 1 68 SetMarkerPath 5 2 14 SetMarkerPath 5 3 69 SetMarkerPath 5 4 66 SetMarkerPath 5 5 67 SetMarkerPath 5 6 71 SetGoal 6 7 SetMarkerPath 6 1 15 SetMarkerPath 6 2 82 SetGoal 7 17 SetMarkerPath 7 1 68 SetMarkerPath 7 2 67 SetGoal 8 15 SetMarkerPath 8 1 21 SetGoal 9 16 SetMarkerPath 9 1 10 SetMarkerPath 9 2 103 SetMarkerPath 9 3 104 SetGoal 10 16 SetMarkerPath 10 1 104 SetMarkerPath 10 2 9 SetMarkerPath 10 3 107 SetMarkerPathFlags 10 3 j SetGoal 11 19 SetMarkerPath 11 1 12 SetGoal 12 19 SetMarkerPath 12 1 11 SetMarkerPath 12 2 79 SetGoal 13 7 SetMarkerPath 13 1 83 SetMarkerPath 13 2 15 SetMarkerPath 13 3 82 SetGoal 14 8 SetMarkerPath 14 1 5 SetMarkerPath 14 2 68 SetMarkerPath 14 3 67 SetGoal 15 7 SetMarkerPath 15 1 13 SetMarkerPath 15 2 6 SetMarkerPath 15 3 82 SetGoal 16 4 SetMarkerPath 16 1 78 SetMarkerPath 16 2 25 SetMarkerPath 16 3 4 SetGoal 17 18 SetMarkerPath 17 1 61 SetGoal 18 11 SetMarkerPath 18 1 19 SetMarkerPath 18 2 58 SetGoal 19 11 SetMarkerPath 19 1 58 SetMarkerPath 19 2 18 SetMarkerPath 19 3 59 SetGoal 20 5 SetMarkerPath 20 1 4 SetMarkerPath 20 2 79 SetMarkerPath 20 3 78 SetGoal 21 14 SetMarkerPath 21 1 95 SetMarkerPath 21 2 8 SetGoal 22 13 SetMarkerPath 22 1 91 SetMarkerPath 22 2 31 SetMarkerPath 22 3 15 SetMarkerPath 25 1 16 SetMarkerPath 26 1 99 SetMarkerPath 26 2 100 SetMarkerPath 28 1 57 SetMarkerPath 29 1 14 SetMarkerPath 30 1 87 SetMarkerPath 30 2 34 SetMarkerPath 30 3 86 SetMarkerPath 31 1 22 SetMarkerPath 31 2 91 SetMarkerPath 32 1 39 SetMarkerPath 34 1 30 SetMarkerPath 35 1 39 SetMarkerPath 36 1 76 SetMarkerPath 36 2 3 SetMarkerPath 37 1 40 SetGoal 39 2 SetMarkerPath 39 1 75 SetMarkerPath 39 2 32 SetMarkerPath 39 3 35 SetMarkerPath 39 4 86 SetGoal 40 12 SetMarkerPath 40 1 65 SetMarkerPath 40 2 64 SetMarkerPath 40 3 57 SetGoal 41 10 SetMarkerPath 41 1 61 SetMarkerPath 41 2 62 SetGoal 42 9 SetMarkerPath 42 1 62 SetMarkerPath 42 2 69 SetMarkerPath 42 3 68 SetGoal 43 6 SetMarkerPath 43 1 79 SetMarkerPath 43 2 81 SetMarkerPath 57 1 63 SetMarkerPath 57 2 59 SetMarkerPath 58 1 60 SetMarkerPath 58 2 19 SetMarkerPath 58 3 59 SetMarkerPath 58 4 18 SetMarkerPath 58 5 96 SetMarkerPath 59 1 19 SetMarkerPath 59 2 64 SetMarkerPath 59 3 63 SetMarkerPath 59 4 57 SetMarkerPath 59 5 58 SetMarkerPath 60 1 2 SetMarkerPath 60 2 61 SetMarkerPath 60 3 58 SetMarkerPath 61 1 2 SetMarkerPath 61 2 41 SetMarkerPath 61 3 60 SetMarkerPath 62 1 41 SetMarkerPath 62 2 42 SetMarkerPath 63 1 59 SetMarkerPath 63 2 57 SetMarkerPath 64 1 40 SetMarkerPath 64 2 59 SetMarkerPath 65 1 66 SetMarkerPath 65 2 40 SetMarkerPath 66 1 5 SetMarkerPath 66 2 67 SetMarkerPath 66 3 65 SetMarkerPath 67 1 5 SetMarkerPath 67 2 14 SetMarkerPath 67 3 66 SetMarkerPath 68 1 69 SetMarkerPath 68 2 42 SetMarkerPath 68 3 5 SetMarkerPath 68 4 14 SetMarkerPath 68 5 71 SetMarkerPath 69 1 42 SetMarkerPath 69 2 68 SetMarkerPath 69 3 5 SetMarkerPath 69 4 71 SetMarkerPath 69 5 88 SetMarkerPath 70 1 2 SetMarkerPath 70 2 75 SetMarkerPath 71 1 68 SetMarkerPath 71 2 5 SetMarkerPath 71 3 69 SetMarkerPath 72 1 73 SetMarkerPath 72 2 3 SetMarkerPath 72 3 74 SetMarkerPath 73 1 3 SetMarkerPath 73 2 72 SetMarkerPath 73 3 74 SetMarkerPath 73 4 76 SetMarkerPath 74 1 73 SetMarkerPath 74 2 72 SetMarkerPath 74 3 75 SetMarkerPath 75 1 74 SetMarkerPath 75 2 70 SetMarkerPath 75 3 39 SetMarkerPath 76 1 77 SetMarkerPath 76 2 36 SetMarkerPath 76 3 3 SetMarkerPath 76 4 73 SetMarkerPath 77 1 78 SetMarkerPath 77 2 76 SetMarkerPath 78 1 20 SetMarkerPath 78 2 16 SetMarkerPath 78 3 77 SetMarkerPath 79 1 81 SetMarkerPath 79 2 80 SetMarkerPath 79 3 4 SetMarkerPath 79 4 20 SetMarkerPath 79 5 43 SetMarkerPath 80 1 79 SetMarkerPath 80 2 18 SetMarkerPath 80 3 84 SetMarkerPath 81 1 82 SetMarkerPath 81 2 79 SetMarkerPath 81 3 43 SetMarkerPath 82 1 6 SetMarkerPath 82 2 15 SetMarkerPath 82 3 13 SetMarkerPath 82 4 81 SetMarkerPath 83 1 37 SetMarkerPath 83 2 13 SetMarkerPath 84 1 85 SetMarkerPath 84 2 80 SetMarkerPath 85 1 86 SetMarkerPath 85 2 84 SetMarkerPath 85 3 89 SetMarkerPath 85 4 57 SetMarkerPath 86 1 30 SetMarkerPath 86 2 85 SetMarkerPath 86 3 87 SetMarkerPath 86 4 15 SetMarkerPath 87 1 88 SetMarkerPath 87 2 30 SetMarkerPath 87 3 86 SetMarkerPath 88 1 69 SetMarkerPath 88 2 87 SetMarkerPath 89 1 85 SetMarkerPath 89 2 90 SetMarkerPath 90 1 89 SetMarkerPath 90 2 91 SetMarkerPath 91 1 90 SetMarkerPath 91 2 22 SetMarkerPath 91 3 31 SetMarkerPath 92 1 93 SetMarkerPath 93 1 92 SetMarkerPath 93 2 94 SetMarkerPath 94 1 93 SetMarkerPath 94 2 95 SetMarkerPath 95 1 94 SetMarkerPath 95 2 96 SetMarkerPath 95 3 21 SetMarkerPath 95 4 97 SetMarkerPath 96 1 95 SetMarkerPath 96 2 97 SetMarkerPath 97 1 98 SetMarkerPath 97 2 96 SetMarkerPath 97 3 95 SetMarkerPath 98 1 97 SetMarkerPath 98 2 99 SetMarkerPath 99 1 98 SetMarkerPath 99 2 26 SetMarkerPath 99 3 7 SetMarkerPath 100 1 101 SetMarkerPath 100 2 26 SetMarkerPath 100 3 99 SetMarkerPath 101 1 102 SetMarkerPath 101 2 100 SetMarkerPath 102 1 103 SetMarkerPath 102 2 101 SetMarkerPath 103 1 9 SetMarkerPath 103 2 102 SetMarkerPath 103 3 104 SetMarkerPath 104 1 10 SetMarkerPath 104 2 9 SetMarkerPath 104 3 33 SetMarkerPathFlags 104 3 j SetMarkerPath 104 4 103 SetMarkerPath 105 1 108 SetMarkerPath 105 2 3 SetMarkerPath 106 1 105 SetMarkerPath 107 1 106 SetMarkerPath 107 2 57 SetMarkerPath 108 1 109 SetMarkerPath 109 1 108 SetMarkerPath 109 2 110 SetMarkerPath 109 3 4 SetMarkerPath 110 1 12 SetMarkerPathFlags 110 1 j SetMarkerPath 110 2 109 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/spinev2.bot000066400000000000000000000315261475442401000263430ustar00rootroot00000000000000CreateMarker 673 289 -136 CreateMarker 470 290 -104 CreateMarker 150 291 -104 CreateMarker 317 287 -104 CreateMarker 24 287 -104 CreateMarker 20 399 -104 CreateMarker -157 548 -104 CreateMarker -6 542 -104 CreateMarker -32 696 -104 CreateMarker 76 546 -104 CreateMarker 198 530 -104 CreateMarker 531 510 120 CreateMarker 774 404 88 CreateMarker 766 509 88 CreateMarker 630 511 111 CreateMarker 449 405 120 CreateMarker 449 227 120 CreateMarker 286 144 120 CreateMarker 91 146 120 CreateMarker -35 149 120 CreateMarker -130 52 120 CreateMarker -128 -21 120 CreateMarker -218 -129 120 CreateMarker -385 -125 120 CreateMarker -371 536 -8 CreateMarker -274 542 -56 CreateMarker -491 532 40 CreateMarker -477 385 56 CreateMarker -554 432 56 CreateMarker -415 230 83 CreateMarker -381 416 56 CreateMarker -419 128 108 CreateMarker -542 25 120 CreateMarker -708 0 120 CreateMarker -537 -116 120 CreateMarker 115 39 120 CreateMarker 244 26 120 CreateMarker 1023 307 50 CreateMarker 1130 184 24 CreateMarker 1024 182 25 CreateMarker 833 32 24 CreateMarker 805 143 24 CreateMarker 907 127 24 CreateMarker 833 -225 24 CreateMarker 737 -323 24 CreateMarker 834 -413 24 CreateMarker 833 -560 248 CreateMarker 728 -507 248 CreateMarker 321 -319 24 CreateMarker 451 -319 24 CreateMarker 394 507 120 CreateMarker 578 -321 24 CreateMarker 66 -301 24 CreateMarker -38 -398 24 CreateMarker 286 -401 248 CreateMarker 143 -387 24 CreateMarker 1015 414 72 CreateMarker 1048 559 88 CreateMarker 853 564 88 CreateMarker -110 419 -104 CreateMarker 305 -173 24 CreateMarker 195 -215 24 CreateMarker 610 -408 248 CreateMarker 440 -371 248 CreateMarker 390 -270 248 CreateMarker 831 -102 24 SetGoal 1 1 SetZone 1 1 SetMarkerPath 1 0 24 SetMarkerPath 1 1 52 SetMarkerPath 1 2 5 SetMarkerPath 1 3 94 SetMarkerPathFlags 1 3 r SetRocketJumpPathFields 1 3 74.0 141.0 0 SetMarkerPath 1 4 89 SetMarkerPathFlags 1 4 r SetRocketJumpPathFields 1 4 65.0 183.0 0 SetMarkerPath 1 5 93 SetMarkerPathFlags 1 5 r SetRocketJumpPathFields 1 5 74.0 89.0 0 SetGoal 2 2 SetZone 2 4 SetMarkerPath 2 0 89 SetMarkerPath 2 1 109 SetMarkerPath 2 2 65 SetMarkerPath 2 3 64 SetMarkerPath 2 4 93 SetMarkerPath 2 5 1 SetGoal 3 3 SetZone 3 1 SetMarkerPath 3 0 56 SetMarkerPath 3 1 111 SetMarkerPath 3 2 57 SetZone 4 2 SetMarkerPath 4 0 11 SetMarkerPath 4 1 86 SetZone 5 1 SetMarkerPath 5 0 1 SetMarkerPath 5 1 52 SetZone 6 4 SetMarkerPath 6 0 65 SetMarkerPath 6 1 110 SetMarkerPath 6 2 20 SetZone 7 5 SetMarkerPath 7 0 116 SetMarkerPath 7 1 115 SetZone 8 3 SetMarkerPath 8 0 71 SetMarkerPath 8 1 72 SetGoal 9 4 SetZone 9 4 SetMarkerPath 9 0 90 SetGoal 10 5 SetZone 10 2 SetMarkerPath 10 0 75 SetMarkerPath 10 1 12 SetMarkerPath 10 2 86 SetGoal 11 6 SetZone 11 2 SetMarkerPath 11 0 12 SetMarkerPath 11 1 4 SetMarkerPath 11 2 86 SetGoal 12 6 SetZone 12 2 SetMarkerPath 12 0 10 SetMarkerPath 12 1 11 SetMarkerPath 12 2 86 SetMarkerPath 12 3 75 SetGoal 13 23 SetZone 13 2 SetMarkerPath 13 0 23 SetMarkerPath 13 1 14 SetMarkerPath 13 2 85 SetGoal 14 19 SetZone 14 2 SetMarkerPath 14 0 13 SetMarkerPath 14 1 15 SetMarkerPath 14 2 85 SetMarkerPath 14 3 84 SetGoal 15 20 SetZone 15 2 SetMarkerPath 15 0 14 SetMarkerPath 15 1 83 SetMarkerPath 15 2 84 SetMarkerPath 15 3 85 SetMarkerPath 15 4 16 SetMarkerPath 15 5 79 SetGoal 16 7 SetZone 16 2 SetMarkerPath 16 0 17 SetMarkerPath 16 1 79 SetGoal 17 7 SetZone 17 2 SetMarkerPath 17 0 80 SetMarkerPath 17 1 16 SetMarkerPath 17 2 79 SetGoal 18 8 SetZone 18 4 SetMarkerPath 18 0 21 SetMarkerPath 18 1 109 SetMarkerPath 18 2 110 SetMarkerPath 18 3 2 SetGoal 19 9 SetZone 19 4 SetMarkerPath 19 0 93 SetMarkerPath 19 1 92 SetGoal 20 23 SetZone 20 4 SetMarkerPath 20 0 110 SetMarkerPath 20 1 21 SetMarkerPath 20 2 2 SetMarkerPath 20 3 109 SetMarkerPath 20 4 6 SetGoal 21 23 SetZone 21 4 SetMarkerPath 21 0 20 SetMarkerPath 21 1 18 SetMarkerPath 21 2 109 SetMarkerPath 21 3 110 SetMarkerPath 21 4 2 SetZone 22 1 SetMarkerPath 22 0 23 SetZone 23 2 SetMarkerPath 23 0 25 SetMarkerPath 23 1 85 SetMarkerPath 23 2 13 SetZone 24 1 SetMarkerPath 24 0 22 SetMarkerPath 24 1 1 SetZone 25 2 SetMarkerPath 25 0 24 SetZone 26 6 SetMarkerPath 26 0 28 SetZone 27 6 SetMarkerPath 27 0 26 SetMarkerPath 27 1 105 SetZone 28 1 SetMarkerPath 28 0 29 SetMarkerPath 28 1 60 SetZone 29 1 SetMarkerPath 29 0 27 SetGoal 30 10 SetZone 30 6 SetMarkerPath 30 0 31 SetMarkerPath 30 1 104 SetMarkerPath 30 2 113 SetGoal 31 11 SetZone 31 6 SetMarkerPath 31 0 32 SetMarkerPath 31 1 30 SetMarkerPath 31 2 113 SetMarkerPath 31 3 112 SetMarkerPath 31 4 88 SetMarkerPathFlags 31 4 r SetRocketJumpPathFields 31 4 45.0 360.0 0 SetGoal 32 11 SetZone 32 6 SetMarkerPath 32 0 33 SetMarkerPath 32 1 31 SetMarkerPath 32 2 112 SetMarkerPath 32 3 113 SetMarkerPath 32 4 30 SetGoal 33 11 SetZone 33 6 SetMarkerPath 33 0 112 SetMarkerPath 33 1 32 SetMarkerPath 33 2 30 SetMarkerPath 33 3 113 SetGoal 34 12 SetZone 34 6 SetMarkerPath 34 0 107 SetMarkerPath 34 1 100 SetMarkerPath 34 2 113 SetGoal 35 20 SetZone 35 5 SetMarkerPath 35 0 95 SetMarkerPath 35 1 97 SetMarkerPath 35 2 96 SetGoal 36 19 SetZone 36 3 SetMarkerPath 36 0 37 SetMarkerPath 36 1 68 SetGoal 37 19 SetZone 37 3 SetMarkerPath 37 0 69 SetMarkerPath 37 1 36 SetMarkerPath 37 2 68 SetGoal 38 23 SetZone 38 1 SetMarkerPath 38 0 61 SetMarkerPath 38 1 60 SetMarkerPath 38 2 39 SetGoal 39 23 SetZone 39 1 SetMarkerPath 39 0 60 SetMarkerPath 39 1 40 SetMarkerPath 39 2 38 SetGoal 40 23 SetZone 40 1 SetMarkerPath 40 0 60 SetMarkerPath 40 1 46 SetMarkerPath 40 2 39 SetZone 41 1 SetMarkerPath 41 0 60 SetMarkerPath 41 1 58 SetGoal 43 13 SetZone 43 1 SetMarkerPath 43 0 53 SetMarkerPath 43 1 44 SetMarkerPath 43 2 55 SetGoal 44 13 SetZone 44 1 SetMarkerPath 44 0 54 SetMarkerPath 44 1 43 SetMarkerPath 44 2 55 SetZone 45 1 SetMarkerPath 45 0 102 SetGoal 46 19 SetZone 46 1 SetMarkerPath 46 0 60 SetMarkerPath 46 1 40 SetZone 47 1 SetMarkerPath 47 0 62 SetMarkerPath 47 1 45 SetGoal 48 14 SetZone 48 5 SetMarkerPath 48 0 114 SetMarkerPath 48 1 49 SetGoal 49 14 SetZone 49 5 SetMarkerPath 49 0 114 SetMarkerPath 49 1 115 SetMarkerPath 49 2 48 SetZone 50 5 SetMarkerPath 50 0 98 SetZone 51 5 SetMarkerPath 51 0 97 SetMarkerPath 51 1 50 SetZone 52 1 SetMarkerPath 52 0 1 SetMarkerPath 52 1 5 SetMarkerPath 52 2 53 SetZone 53 1 SetMarkerPath 53 0 52 SetMarkerPath 53 1 55 SetMarkerPath 53 2 43 SetZone 54 1 SetMarkerPath 54 0 55 SetMarkerPath 54 1 56 SetMarkerPath 54 2 44 SetMarkerPath 54 3 57 SetZone 55 1 SetMarkerPath 55 0 53 SetMarkerPath 55 1 54 SetMarkerPath 55 2 43 SetMarkerPath 55 3 44 SetZone 56 1 SetMarkerPath 56 0 54 SetMarkerPath 56 1 3 SetMarkerPath 56 2 111 SetMarkerPath 56 3 57 SetZone 57 1 SetMarkerPath 57 0 54 SetMarkerPath 57 1 58 SetMarkerPath 57 2 59 SetMarkerPath 57 3 61 SetMarkerPath 57 4 3 SetMarkerPath 57 5 111 SetZone 58 1 SetMarkerPath 58 0 111 SetMarkerPath 58 1 77 SetMarkerPath 58 2 57 SetMarkerPath 58 3 41 SetMarkerPath 58 4 59 SetMarkerPath 58 5 60 SetZone 59 1 SetMarkerPath 59 0 57 SetMarkerPath 59 1 60 SetMarkerPath 59 2 61 SetMarkerPath 59 3 58 SetMarkerPath 59 4 111 SetMarkerPath 59 5 38 SetZone 60 1 SetMarkerPath 60 0 59 SetMarkerPath 60 1 28 SetMarkerPath 60 2 41 SetMarkerPath 60 3 58 SetMarkerPath 60 4 61 SetMarkerPath 60 5 46 SetZone 61 1 SetMarkerPath 61 0 59 SetMarkerPath 61 1 62 SetMarkerPath 61 2 38 SetMarkerPath 61 3 57 SetMarkerPath 61 4 60 SetZone 62 1 SetMarkerPath 62 0 61 SetMarkerPath 62 1 47 SetZone 63 3 SetMarkerPath 63 0 67 SetMarkerPath 63 1 66 SetMarkerPath 63 2 102 SetZone 64 4 SetMarkerPath 64 0 65 SetMarkerPath 64 1 110 SetMarkerPath 64 2 2 SetMarkerPath 64 3 93 SetMarkerPath 64 4 1 SetMarkerPath 64 5 24 SetZone 65 4 SetMarkerPath 65 0 66 SetMarkerPath 65 1 2 SetMarkerPath 65 2 110 SetMarkerPath 65 3 64 SetMarkerPath 65 4 6 SetZone 66 3 SetMarkerPath 66 0 63 SetMarkerPath 66 1 65 SetZone 67 3 SetMarkerPath 67 0 68 SetMarkerPath 67 1 63 SetMarkerPath 67 2 102 SetZone 68 3 SetMarkerPath 68 0 69 SetMarkerPath 68 1 67 SetMarkerPath 68 2 36 SetMarkerPath 68 3 37 SetZone 69 3 SetMarkerPath 69 0 70 SetMarkerPath 69 1 68 SetMarkerPath 69 2 88 SetMarkerPath 69 3 87 SetMarkerPath 69 4 37 SetZone 70 3 SetMarkerPath 70 0 71 SetMarkerPath 70 1 69 SetMarkerPath 70 2 87 SetMarkerPath 70 3 88 SetZone 71 3 SetMarkerPath 71 0 72 SetMarkerPath 71 1 70 SetMarkerPath 71 2 8 SetZone 72 3 SetMarkerPath 72 0 73 SetMarkerPath 72 1 71 SetMarkerPath 72 2 8 SetZone 73 3 SetMarkerPath 73 0 74 SetMarkerPath 73 1 72 SetZone 74 3 SetMarkerPath 74 0 75 SetMarkerPath 74 1 73 SetZone 75 2 SetMarkerPath 75 0 83 SetMarkerPath 75 1 74 SetMarkerPath 75 2 10 SetMarkerPath 75 3 86 SetMarkerPath 75 4 12 SetMarkerPath 75 5 84 SetZone 76 2 SetMarkerPath 76 0 77 SetMarkerPath 76 1 78 SetZone 77 2 SetMarkerPath 77 0 58 SetMarkerPath 77 1 76 SetZone 78 2 SetMarkerPath 78 0 76 SetMarkerPath 78 1 79 SetMarkerPath 78 2 80 SetZone 79 2 SetMarkerPath 79 0 78 SetMarkerPath 79 1 81 SetMarkerPath 79 2 16 SetMarkerPath 79 3 80 SetMarkerPath 79 4 82 SetMarkerPath 79 5 17 SetZone 80 2 SetMarkerPath 80 0 78 SetMarkerPath 80 1 17 SetMarkerPath 80 2 79 SetZone 81 2 SetMarkerPath 81 0 79 SetMarkerPath 81 1 83 SetMarkerPath 81 2 82 SetMarkerPath 81 3 16 SetZone 82 2 SetMarkerPath 82 0 79 SetMarkerPath 82 1 81 SetMarkerPath 82 2 76 SetMarkerPath 82 3 78 SetZone 83 2 SetMarkerPath 83 0 81 SetMarkerPath 83 1 75 SetMarkerPath 83 2 86 SetMarkerPath 83 3 15 SetMarkerPath 83 4 84 SetZone 84 2 SetMarkerPath 84 0 83 SetMarkerPath 84 1 85 SetMarkerPath 84 2 15 SetMarkerPath 84 3 86 SetMarkerPath 84 4 75 SetMarkerPath 84 5 14 SetZone 85 2 SetMarkerPath 85 0 86 SetMarkerPath 85 1 23 SetMarkerPath 85 2 84 SetMarkerPath 85 3 15 SetMarkerPath 85 4 13 SetMarkerPath 85 5 14 SetZone 86 2 SetMarkerPath 86 0 75 SetMarkerPath 86 1 83 SetMarkerPath 86 2 84 SetMarkerPath 86 3 85 SetMarkerPath 86 4 10 SetMarkerPath 86 5 12 SetZone 87 3 SetMarkerPath 87 0 70 SetMarkerPath 87 1 88 SetMarkerPath 87 2 69 SetMarkerPath 87 3 30 SetMarkerPath 87 4 31 SetMarkerPath 87 5 113 SetZone 88 3 SetMarkerPath 88 0 87 SetMarkerPath 88 1 69 SetMarkerPath 88 2 70 SetMarkerPath 88 3 32 SetMarkerPath 88 4 30 SetMarkerPath 88 5 113 SetZone 89 4 SetMarkerPath 89 0 108 SetMarkerPath 89 1 91 SetMarkerPath 89 2 9 SetMarkerPath 89 3 1 SetZone 90 4 SetMarkerPath 90 0 91 SetMarkerPath 90 1 9 SetZone 91 4 SetMarkerPath 91 0 94 SetMarkerPath 91 1 90 SetMarkerPath 91 2 89 SetMarkerPath 91 3 1 SetZone 92 4 SetMarkerPath 92 0 19 SetMarkerPath 92 1 93 SetMarkerPath 92 2 94 SetMarkerPath 92 3 117 SetZone 93 4 SetMarkerPath 93 0 94 SetMarkerPath 93 1 92 SetMarkerPath 93 2 19 SetMarkerPath 93 3 1 SetMarkerPath 93 4 24 SetZone 94 4 SetMarkerPath 94 0 91 SetMarkerPath 94 1 92 SetMarkerPath 94 2 93 SetMarkerPath 94 3 1 SetZone 95 5 SetMarkerPath 95 0 117 SetMarkerPath 95 1 35 SetMarkerPath 95 2 96 SetZone 96 5 SetMarkerPath 96 0 35 SetMarkerPath 96 1 95 SetMarkerPath 96 2 103 SetZone 97 5 SetMarkerPath 97 0 35 SetMarkerPath 97 1 51 SetZone 98 5 SetMarkerPath 98 0 99 SetZone 99 5 SetMarkerPath 99 0 114 SetMarkerPath 99 1 51 SetZone 100 6 SetMarkerPath 100 0 101 SetMarkerPath 100 1 107 SetMarkerPath 100 2 112 SetMarkerPath 100 3 34 SetMarkerPath 100 4 113 SetMarkerPath 100 5 104 SetZone 101 5 SetMarkerPath 101 0 103 SetMarkerPath 101 1 100 SetZone 102 3 SetMarkerPath 102 0 63 SetMarkerPath 102 1 67 SetMarkerPath 102 2 47 SetZone 103 5 SetMarkerPath 103 0 96 SetMarkerPath 103 1 101 SetZone 104 6 SetMarkerPath 104 0 30 SetMarkerPath 104 1 105 SetMarkerPath 104 2 113 SetMarkerPath 104 3 107 SetMarkerPath 104 4 100 SetZone 105 6 SetMarkerPath 105 0 107 SetMarkerPath 105 1 27 SetMarkerPath 105 2 104 SetZone 106 5 SetMarkerPath 106 0 115 SetMarkerPath 106 1 116 SetMarkerPath 106 2 32 SetMarkerPath 106 3 113 SetMarkerPath 106 4 112 SetZone 107 6 SetMarkerPath 107 0 100 SetMarkerPath 107 1 105 SetMarkerPath 107 2 34 SetMarkerPath 107 3 104 SetMarkerPath 107 4 113 SetZone 108 4 SetMarkerPath 108 0 2 SetMarkerPath 108 1 89 SetMarkerPath 108 2 110 SetMarkerPath 108 3 109 SetZone 109 4 SetMarkerPath 109 0 110 SetMarkerPath 109 1 18 SetMarkerPath 109 2 2 SetMarkerPath 109 3 108 SetZone 110 4 SetMarkerPath 110 0 65 SetMarkerPath 110 1 2 SetMarkerPath 110 2 64 SetMarkerPath 110 3 109 SetMarkerPath 110 4 108 SetMarkerPath 110 5 20 SetZone 111 1 SetMarkerPath 111 0 3 SetMarkerPath 111 1 58 SetMarkerPath 111 2 57 SetMarkerPath 111 3 56 SetMarkerPath 111 4 59 SetZone 112 6 SetMarkerPath 112 0 100 SetMarkerPath 112 1 33 SetMarkerPath 112 2 113 SetZone 113 6 SetMarkerPath 113 0 34 SetMarkerPath 113 1 30 SetMarkerPath 113 2 100 SetMarkerPath 113 3 31 SetMarkerPath 113 4 112 SetMarkerPath 113 5 104 SetMarkerPath 113 6 116 SetMarkerPathFlags 113 6 r SetRocketJumpPathFields 113 6 70.0 173.0 0 SetMarkerPath 113 7 88 SetMarkerPathFlags 113 7 r SetRocketJumpPathFields 113 7 47.0 260.0 0 SetZone 114 5 SetMarkerPath 114 0 99 SetMarkerPath 114 1 48 SetMarkerPath 114 2 49 SetMarkerPath 114 3 115 SetZone 115 5 SetMarkerPath 115 0 114 SetMarkerPath 115 1 49 SetMarkerPath 115 2 116 SetMarkerPath 115 3 7 SetMarkerPath 115 4 106 SetZone 116 5 SetMarkerPath 116 0 115 SetMarkerPath 116 1 7 SetMarkerPath 116 2 113 SetMarkerPath 116 3 30 SetMarkerPath 116 4 104 SetMarkerPath 116 5 106 SetZone 117 5 SetMarkerPath 117 0 92 SetMarkerPath 117 1 95 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/subterfuge.bot000066400000000000000000000203421475442401000271220ustar00rootroot00000000000000CreateMarker -181 -209 152 CreateMarker 146 -208 24 CreateMarker 352 -204 24 CreateMarker 690 -226 88 CreateMarker 844 -67 152 CreateMarker 821 191 152 CreateMarker -150 -371 152 CreateMarker -361 -120 152 CreateMarker -262 -131 152 CreateMarker -102 149 344 CreateMarker 86 46 152 CreateMarker 96 187 152 CreateMarker 245 139 152 CreateMarker 467 137 152 CreateMarker 790 311 152 CreateMarker 815 651 152 CreateMarker 658 742 152 CreateMarker 539 847 152 CreateMarker 325 847 248 CreateMarker 137 764 252 CreateMarker 51 482 299 CreateMarker -147 480 299 CreateMarker -45 475 251 CreateMarker -50 265 344 CreateMarker -57 -188 344 CreateMarker -121 -315 344 CreateMarker 354 -48 24 CreateMarker 354 178 24 CreateMarker 349 519 24 CreateMarker 422 848 205 CreateMarker 20 -210 72 CreateMarker 228 851 252 CreateMarker 356 24 344 CreateMarker 208 656 24 CreateMarker 208 848 24 CreateMarker 348 624 24 CreateMarker 532 723 152 SetZone 1 4 SetMarkerPath 1 0 67 SetMarkerPath 1 1 32 SetMarkerPath 1 2 68 SetZone 2 1 SetMarkerPath 2 0 5 SetZone 3 1 SetMarkerPath 3 0 72 SetMarkerPath 3 1 2 SetMarkerPath 3 2 52 SetMarkerPath 3 3 53 SetZone 4 5 SetMarkerPath 4 0 3 SetZone 5 5 SetMarkerPath 5 0 4 SetMarkerPath 5 1 25 SetMarkerPath 5 2 44 SetMarkerPath 5 3 45 SetZone 6 6 SetMarkerPath 6 0 55 SetMarkerPath 6 1 56 SetMarkerPath 6 2 57 SetZone 7 4 SetMarkerPath 7 0 6 SetGoal 8 1 SetZone 8 6 SetMarkerPath 8 0 69 SetMarkerPath 8 1 20 SetMarkerPath 8 2 59 SetMarkerPathAngleHint 8 2 -35 SetMarkerPath 8 3 37 SetMarkerPath 8 4 76 SetMarkerPathAngleHint 8 4 20 SetGoal 9 2 SetZone 9 5 SetMarkerPath 9 0 29 SetMarkerPath 9 1 53 SetGoal 10 3 SetZone 10 3 SetMarkerPath 10 0 41 SetMarkerPath 10 1 42 SetMarkerPath 10 2 36 SetGoal 11 4 SetZone 11 3 SetMarkerPath 11 0 44 SetMarkerPath 11 1 43 SetGoal 12 17 SetZone 12 2 SetMarkerPath 12 0 47 SetMarkerPath 12 1 48 SetMarkerPath 12 2 40 SetMarkerPath 12 3 46 SetGoal 13 5 SetZone 13 2 SetMarkerPath 13 0 40 SetMarkerPath 13 1 46 SetMarkerPath 13 2 70 SetMarkerPath 13 3 41 SetMarkerPath 13 4 26 SetMarkerPath 13 5 50 SetMarkerPath 13 6 30 SetZone 14 4 SetMarkerPath 14 0 15 SetZone 15 1 SetMarkerPath 15 0 65 SetMarkerPath 15 1 64 SetGoal 16 15 SetZone 16 5 SetMarkerPath 16 0 25 SetMarkerPath 16 1 21 SetMarkerPath 16 2 45 SetGoal 17 18 SetZone 17 1 SetMarkerPath 17 0 63 SetMarkerPath 17 1 49 SetMarkerPath 17 2 24 SetMarkerPath 17 3 40 SetMarkerPath 17 4 33 SetMarkerPath 17 5 35 SetMarkerPath 17 6 64 SetMarkerPath 17 7 14 SetZone 18 2 SetMarkerPath 18 0 48 SetMarkerPath 18 1 40 SetZone 19 1 SetMarkerPath 19 0 35 SetMarkerPath 19 1 65 SetZone 20 6 SetMarkerPath 20 0 8 SetZone 21 5 SetMarkerPath 21 0 16 SetZone 22 4 SetMarkerPath 22 0 37 SetMarkerPath 22 1 7 SetMarkerPath 22 2 68 SetMarkerPath 22 3 75 SetGoal 23 16 SetZone 23 1 SetMarkerPath 23 0 24 SetMarkerPath 23 1 53 SetMarkerPath 23 2 29 SetMarkerPath 23 3 68 SetMarkerPath 23 4 52 SetMarkerPath 23 5 72 SetGoal 24 16 SetZone 24 1 SetMarkerPath 24 0 17 SetMarkerPath 24 1 63 SetMarkerPath 24 2 23 SetMarkerPath 24 3 32 SetGoal 25 16 SetZone 25 5 SetMarkerPath 25 0 5 SetMarkerPath 25 1 45 SetMarkerPath 25 2 16 SetMarkerPath 25 3 44 SetGoal 26 16 SetZone 26 2 SetMarkerPath 26 0 48 SetMarkerPath 26 1 13 SetMarkerPath 26 2 50 SetMarkerPath 26 3 41 SetGoal 27 16 SetZone 27 4 SetMarkerPath 27 0 66 SetMarkerPath 27 1 67 SetMarkerPath 27 2 32 SetMarkerPath 27 3 31 SetGoal 28 19 SetZone 28 5 SetMarkerPath 28 0 45 SetMarkerPath 28 1 54 SetMarkerPath 28 2 29 SetMarkerPath 28 3 32 SetGoal 29 19 SetZone 29 5 SetMarkerPath 29 0 54 SetMarkerPath 29 1 28 SetMarkerPath 29 2 9 SetMarkerPath 29 3 53 SetMarkerPath 29 4 32 SetMarkerPath 29 5 68 SetGoal 30 18 SetZone 30 2 SetMarkerPath 30 0 48 SetMarkerPath 30 1 50 SetMarkerPath 30 2 41 SetMarkerPath 30 3 13 SetGoal 31 18 SetZone 31 4 SetMarkerPath 31 0 32 SetMarkerPath 31 1 14 SetMarkerPath 31 2 27 SetMarkerPath 31 3 68 SetGoal 32 21 SetZone 32 4 SetMarkerPath 32 0 67 SetMarkerPath 32 1 1 SetMarkerPath 32 2 68 SetMarkerPath 32 3 31 SetMarkerPath 32 4 27 SetMarkerPath 32 5 14 SetGoal 33 16 SetZone 33 2 SetMarkerPath 33 0 47 SetMarkerPath 33 1 49 SetGoal 34 6 SetZone 34 6 SetMarkerPath 34 0 59 SetMarkerPath 34 2 62 SetGoal 35 19 SetZone 35 1 SetMarkerPath 35 0 19 SetMarkerPath 35 1 65 SetMarkerPath 35 2 48 SetMarkerPath 35 3 40 SetMarkerPath 35 4 47 SetMarkerPath 35 5 17 SetGoal 36 18 SetZone 36 3 SetMarkerPath 36 0 10 SetMarkerPath 36 1 42 SetMarkerPath 36 2 43 SetGoal 37 16 SetZone 37 4 SetMarkerPath 37 0 75 SetMarkerPath 37 1 22 SetMarkerPath 37 2 7 SetMarkerPath 37 3 73 SetMarkerPath 37 4 74 SetGoal 38 16 SetZone 38 5 SetMarkerPath 38 0 55 SetMarkerPath 38 1 54 SetZone 40 2 SetMarkerPath 40 0 48 SetMarkerPath 40 1 18 SetMarkerPath 40 2 12 SetMarkerPath 40 3 13 SetMarkerPath 40 4 46 SetMarkerPath 40 5 70 SetZone 41 3 SetMarkerPath 41 0 70 SetMarkerPath 41 1 10 SetMarkerPath 41 2 42 SetZone 42 3 SetMarkerPath 42 0 41 SetMarkerPath 42 1 10 SetMarkerPath 42 2 66 SetMarkerPath 42 3 36 SetZone 43 3 SetMarkerPath 43 0 44 SetMarkerPath 43 1 11 SetMarkerPath 43 2 36 SetZone 44 3 SetMarkerPath 44 0 25 SetMarkerPath 44 1 4 SetMarkerPath 44 2 5 SetMarkerPath 44 3 11 SetMarkerPath 44 4 43 SetZone 45 5 SetMarkerPath 45 0 25 SetMarkerPath 45 1 16 SetMarkerPath 45 2 5 SetMarkerPath 45 3 4 SetMarkerPath 45 4 54 SetMarkerPath 45 5 28 SetZone 46 2 SetMarkerPath 46 0 40 SetMarkerPath 46 1 13 SetMarkerPath 46 2 12 SetMarkerPath 46 3 47 SetZone 47 2 SetMarkerPath 47 0 48 SetMarkerPath 47 1 33 SetMarkerPath 47 2 12 SetMarkerPath 47 3 46 SetZone 48 2 SetMarkerPath 48 0 47 SetMarkerPath 48 1 18 SetMarkerPath 48 2 30 SetMarkerPath 48 3 40 SetMarkerPath 48 4 12 SetMarkerPath 48 5 26 SetZone 49 1 SetMarkerPath 49 0 63 SetMarkerPath 49 1 17 SetMarkerPath 49 2 33 SetMarkerPath 49 3 48 SetMarkerPath 49 4 52 SetZone 50 2 SetMarkerPath 50 0 52 SetMarkerPath 50 1 26 SetMarkerPath 50 2 51 SetMarkerPath 50 3 30 SetMarkerPath 50 4 13 SetZone 51 2 SetMarkerPath 51 0 52 SetMarkerPath 51 1 50 SetZone 52 2 SetMarkerPath 52 0 66 SetMarkerPath 52 1 67 SetMarkerPath 52 2 32 SetMarkerPath 52 3 1 SetMarkerPath 52 4 51 SetMarkerPath 52 5 50 SetMarkerPath 52 6 53 SetZone 53 5 SetMarkerPath 53 0 29 SetMarkerPath 53 1 9 SetMarkerPath 53 2 52 SetMarkerPath 53 3 32 SetMarkerPath 53 4 67 SetMarkerPath 53 5 66 SetZone 54 5 SetMarkerPath 54 0 45 SetMarkerPath 54 1 38 SetMarkerPath 54 2 29 SetMarkerPath 54 3 28 SetZone 55 6 SetMarkerPath 55 0 6 SetMarkerPath 55 1 38 SetMarkerPath 55 2 56 SetZone 56 6 SetMarkerPath 56 0 6 SetMarkerPath 56 1 55 SetMarkerPath 56 2 57 SetMarkerPath 56 3 76 SetZone 57 6 SetMarkerPath 57 0 56 SetMarkerPath 57 1 6 SetMarkerPath 57 2 37 SetMarkerPath 57 3 69 SetMarkerPath 57 4 76 SetZone 58 6 SetMarkerPath 58 0 69 SetMarkerPath 58 1 8 SetMarkerPath 58 2 37 SetMarkerPath 58 3 71 SetZone 59 6 SetMarkerPath 59 0 8 SetMarkerPathAngleHint 59 0 45 SetMarkerPath 59 1 71 SetMarkerPath 59 2 37 SetMarkerPath 59 3 34 SetZone 60 1 SetMarkerPath 60 0 62 SetMarkerPath 60 1 63 SetZone 61 1 SetMarkerPath 61 0 62 SetMarkerPath 61 1 63 SetMarkerPath 61 2 34 SetZone 62 1 SetMarkerPath 62 0 34 SetMarkerPath 62 1 63 SetZone 63 1 SetMarkerPath 63 0 62 SetMarkerPath 63 1 49 SetMarkerPath 63 2 17 SetMarkerPath 63 3 24 SetZone 64 1 SetMarkerPath 64 0 65 SetMarkerPath 64 1 15 SetMarkerPath 64 2 17 SetZone 65 1 SetMarkerPath 65 0 19 SetMarkerPath 65 1 35 SetMarkerPath 65 2 15 SetMarkerPath 65 3 64 SetMarkerPath 65 4 48 SetMarkerPath 65 5 40 SetZone 66 4 SetMarkerPath 66 0 42 SetMarkerPath 66 1 67 SetMarkerPath 66 2 27 SetZone 67 4 SetMarkerPath 67 0 66 SetMarkerPath 67 1 27 SetMarkerPath 67 2 32 SetMarkerPath 67 3 1 SetMarkerPath 67 4 14 SetZone 68 4 SetMarkerPath 68 0 1 SetMarkerPath 68 1 32 SetMarkerPath 68 2 31 SetMarkerPath 68 3 75 SetMarkerPath 68 4 22 SetZone 69 6 SetMarkerPath 69 0 57 SetMarkerPath 69 1 58 SetMarkerPath 69 2 8 SetZone 70 3 SetMarkerPath 70 0 40 SetMarkerPath 70 1 41 SetZone 71 6 SetMarkerPath 71 0 58 SetMarkerPath 71 1 8 SetMarkerPath 71 2 59 SetZone 72 1 SetMarkerPath 72 0 3 SetMarkerPath 72 1 23 SetMarkerPath 72 2 52 SetMarkerPath 72 3 53 SetMarkerPath 72 4 29 SetMarkerPath 72 5 32 SetZone 73 4 SetMarkerPath 73 0 37 SetMarkerPath 73 1 7 SetMarkerPath 73 2 74 SetZone 74 4 SetMarkerPath 74 0 73 SetMarkerPath 74 1 37 SetMarkerPath 74 2 7 SetZone 75 4 SetMarkerPath 75 0 37 SetMarkerPath 75 1 22 SetMarkerPath 75 2 68 SetZone 76 6 SetMarkerPath 76 0 57 SetMarkerPath 76 1 56 SetMarkerPath 76 2 37 SetMarkerPath 76 3 7 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ukooldm2.bot000066400000000000000000000145531475442401000265120ustar00rootroot00000000000000CreateMarker 122 -35 40 CreateMarker -401 196 -232 CreateMarker -366 326 -224 CreateMarker -266 379 -232 CreateMarker -146 465 -232 CreateMarker -9 344 -232 CreateMarker -244 806 -232 CreateMarker -434 794 -136 CreateMarker -752 530 -72 CreateMarker -285 256 40 CreateMarker -62 298 40 CreateMarker -203 617 72 CreateMarker -369 494 120 CreateMarker -378 379 168 CreateMarker -401 45 136 CreateMarker -156 13 88 CreateMarker -167 -140 104 CreateMarker -98 -34 104 CreateMarker 35 -123 -168 CreateMarker 51 226 -184 CreateMarker 94 322 -232 CreateMarker 54 -89 -168 CreateMarker 128 -170 -168 CreateMarker 254 -234 -168 CreateMarker 386 -129 -168 CreateMarker -211 -223 -168 CreateMarker 14 -352 40 CreateMarker 203 -177 40 CreateMarker 174 -339 40 CreateMarker 337 -125 40 CreateMarker -749 413 -8 CreateMarker -735 650 -120 SetZone 1 3 SetMarkerPath 1 0 7 SetZone 2 8 SetMarkerPath 2 0 9 SetZone 3 9 SetMarkerPath 3 0 10 SetZone 4 4 SetMarkerPath 4 0 8 SetZone 5 3 SetMarkerViewOfs 5 305 SetMarkerPath 5 0 10 SetZone 6 5 SetMarkerViewOfs 6 241 SetMarkerPath 6 0 11 SetZone 7 1 SetMarkerViewOfs 7 -7 SetMarkerPath 7 0 56 SetMarkerPath 7 1 31 SetZone 8 1 SetMarkerViewOfs 8 -10 SetMarkerPath 8 0 54 SetMarkerPath 8 1 53 SetZone 9 3 SetMarkerPath 9 0 44 SetMarkerPath 9 1 45 SetMarkerPath 9 2 39 SetZone 10 8 SetMarkerViewOfs 10 -10 SetMarkerPath 10 0 19 SetMarkerPath 10 1 37 SetMarkerPath 10 2 69 SetMarkerPath 10 3 70 SetMarkerPath 10 4 71 SetZone 11 2 SetMarkerViewOfs 11 -10 SetMarkerPath 11 0 25 SetMarkerPath 11 1 51 SetZone 12 5 SetMarkerViewOfs 12 17 SetMarkerPath 12 0 21 SetMarkerPath 12 1 66 SetZone 13 1 SetMarkerPath 13 0 17 SetMarkerPath 13 1 56 SetZone 14 2 SetMarkerViewOfs 14 17 SetMarkerPath 14 0 26 SetMarkerPath 14 1 72 SetZone 15 3 SetMarkerViewOfs 15 17 SetMarkerPath 15 0 35 SetMarkerPath 15 1 48 SetZone 16 3 SetMarkerViewOfs 16 17 SetMarkerPath 16 0 47 SetMarkerPath 16 1 40 SetMarkerPath 16 2 61 SetMarkerPath 16 3 62 SetGoal 17 3 SetZone 17 1 SetMarkerPath 17 0 13 SetMarkerPath 17 1 55 SetMarkerPath 17 2 24 SetMarkerPathFlags 17 2 j SetGoal 18 21 SetZone 18 4 SetMarkerPath 18 0 61 SetMarkerPath 18 1 60 SetMarkerPath 18 2 63 SetGoal 19 22 SetZone 19 8 SetMarkerPath 19 0 37 SetMarkerPath 19 1 2 SetMarkerPath 19 2 10 SetGoal 20 1 SetZone 20 7 SetMarkerPath 20 0 68 SetGoal 21 2 SetZone 21 5 SetMarkerPath 21 0 12 SetMarkerPath 21 1 6 SetMarkerPath 21 2 66 SetGoal 22 4 SetZone 22 6 SetMarkerPath 22 0 42 SetGoal 23 24 SetZone 23 1 SetMarkerPath 23 0 33 SetMarkerPath 23 1 53 SetGoal 24 19 SetZone 24 1 SetMarkerPath 24 0 51 SetMarkerPath 24 1 52 SetMarkerPath 24 2 57 SetGoal 25 18 SetZone 25 2 SetMarkerPath 25 0 26 SetMarkerPath 25 1 11 SetGoal 26 18 SetZone 26 2 SetMarkerPath 26 0 14 SetMarkerPath 26 1 25 SetGoal 27 17 SetZone 27 1 SetMarkerPath 27 0 59 SetMarkerPath 27 1 57 SetMarkerPath 27 2 58 SetMarkerPath 27 3 31 SetMarkerPath 27 4 42 SetGoal 28 5 SetZone 28 2 SetMarkerPath 28 0 29 SetMarkerPath 28 1 73 SetGoal 29 16 SetZone 29 2 SetMarkerPath 29 0 30 SetMarkerPath 29 1 28 SetGoal 30 15 SetZone 30 2 SetMarkerPath 30 0 49 SetMarkerPath 30 1 29 SetGoal 31 14 SetZone 31 1 SetMarkerPath 31 0 7 SetMarkerPath 31 1 58 SetMarkerPath 31 2 27 SetGoal 32 20 SetZone 32 1 SetMarkerPath 32 0 34 SetMarkerPath 32 1 33 SetGoal 33 23 SetZone 33 1 SetMarkerPath 33 0 32 SetMarkerPath 33 1 23 SetGoal 34 23 SetZone 34 1 SetMarkerPath 34 0 52 SetMarkerPath 34 1 32 SetGoal 35 24 SetZone 35 3 SetMarkerPath 35 0 46 SetMarkerPath 35 1 15 SetGoal 36 19 SetZone 36 3 SetMarkerPath 36 0 45 SetMarkerPath 36 1 46 SetMarkerPath 36 2 47 SetGoal 37 6 SetZone 37 8 SetMarkerPath 37 0 19 SetMarkerPath 37 1 70 SetMarkerPath 37 2 10 SetMarkerPath 37 3 69 SetGoal 38 7 SetZone 38 4 SetMarkerPath 38 0 41 SetMarkerPath 38 1 60 SetMarkerPath 38 2 64 SetMarkerPath 38 3 65 SetGoal 39 13 SetZone 39 3 SetMarkerPath 39 0 44 SetMarkerPath 39 1 9 SetGoal 40 12 SetZone 40 3 SetMarkerPath 40 0 16 SetMarkerPath 40 1 1 SetMarkerPath 40 2 62 SetGoal 41 11 SetZone 41 4 SetMarkerPath 41 0 38 SetMarkerPath 41 1 60 SetMarkerPath 41 2 67 SetZone 42 6 SetMarkerPath 42 0 22 SetMarkerPath 42 1 38 SetMarkerPathFlags 42 1 j SetZone 43 3 SetMarkerPath 43 0 5 SetMarkerPath 43 1 39 SetZone 44 3 SetMarkerPath 44 0 9 SetMarkerPath 44 1 39 SetMarkerPath 44 2 45 SetZone 45 3 SetMarkerPath 45 0 44 SetMarkerPath 45 1 36 SetMarkerPath 45 2 46 SetMarkerPath 45 3 9 SetZone 46 3 SetMarkerPath 46 0 45 SetMarkerPath 46 1 47 SetMarkerPath 46 2 35 SetZone 47 3 SetMarkerPath 47 0 16 SetMarkerPath 47 1 36 SetMarkerPath 47 2 46 SetMarkerPath 47 3 61 SetZone 48 2 SetMarkerPath 48 0 15 SetMarkerPath 48 1 49 SetZone 49 2 SetMarkerPath 49 0 48 SetMarkerPath 49 1 30 SetZone 50 2 SetMarkerPath 50 0 73 SetMarkerPath 50 1 72 SetZone 51 1 SetMarkerPath 51 0 11 SetMarkerPath 51 1 24 SetZone 52 1 SetMarkerPath 52 0 24 SetMarkerPath 52 1 34 SetZone 53 1 SetMarkerPath 53 0 23 SetMarkerPath 53 1 8 SetMarkerPath 53 2 54 SetZone 54 1 SetMarkerPath 54 0 8 SetMarkerPath 54 1 53 SetMarkerPath 54 2 55 SetZone 55 1 SetMarkerPath 55 0 54 SetMarkerPath 55 1 17 SetZone 56 1 SetMarkerPath 56 0 13 SetMarkerPath 56 1 7 SetMarkerPath 56 2 31 SetZone 57 1 SetMarkerPath 57 0 27 SetMarkerPath 57 1 24 SetMarkerPath 57 2 59 SetZone 58 1 SetMarkerPath 58 0 27 SetMarkerPath 58 1 31 SetMarkerPath 58 2 68 SetMarkerPathFlags 58 2 j SetZone 59 1 SetMarkerPath 59 0 42 SetMarkerPathFlags 59 0 j SetZone 60 4 SetMarkerPath 60 0 18 SetMarkerPath 60 1 63 SetMarkerPath 60 2 38 SetMarkerPath 60 3 41 SetMarkerPath 60 4 64 SetZone 61 4 SetMarkerPath 61 0 16 SetMarkerPath 61 1 47 SetMarkerPath 61 2 62 SetMarkerPath 61 3 18 SetZone 62 3 SetMarkerPath 62 0 61 SetMarkerPath 62 1 40 SetMarkerPath 62 2 16 SetZone 63 4 SetMarkerPath 63 0 60 SetMarkerPath 63 1 18 SetMarkerPath 63 2 64 SetZone 64 4 SetMarkerPath 64 0 63 SetMarkerPath 64 1 60 SetMarkerPath 64 2 38 SetMarkerPath 64 3 65 SetZone 65 4 SetMarkerPath 65 0 64 SetMarkerPath 65 1 38 SetMarkerPath 65 2 66 SetZone 66 5 SetMarkerPath 66 0 12 SetMarkerPath 66 1 21 SetMarkerPath 66 2 65 SetZone 67 4 SetMarkerPath 67 0 41 SetMarkerPath 67 1 4 SetZone 68 7 SetMarkerPath 68 0 20 SetMarkerPath 68 1 70 SetZone 69 8 SetMarkerPath 69 0 10 SetMarkerPath 69 1 70 SetMarkerPath 69 2 37 SetMarkerPath 69 3 71 SetZone 70 8 SetMarkerPath 70 0 37 SetMarkerPath 70 1 69 SetMarkerPath 70 2 10 SetMarkerPath 70 3 68 SetZone 71 8 SetMarkerPath 71 0 10 SetMarkerPath 71 1 66 SetMarkerPath 71 2 69 SetZone 72 2 SetMarkerPath 72 0 14 SetMarkerPath 72 1 50 SetZone 73 2 SetMarkerPath 73 0 28 SetMarkerPath 73 1 50 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ukooldm3.bot000066400000000000000000000165611475442401000265140ustar00rootroot00000000000000CreateMarker 693 464 472 CreateMarker 623 544 528 CreateMarker 507 -37 -8 CreateMarker 356 8 -104 CreateMarker 231 -92 -104 CreateMarker 8 -96 -104 CreateMarker -87 311 -104 CreateMarker -79 118 -104 CreateMarker -51 421 -104 CreateMarker 91 489 -104 CreateMarker 285 376 -104 CreateMarker 293 193 -104 CreateMarker 508 -156 24 CreateMarker 413 -143 32 CreateMarker 421 -28 80 CreateMarker 406 297 128 CreateMarker 299 528 128 CreateMarker 141 539 128 CreateMarker -36 544 128 CreateMarker -190 400 128 CreateMarker -103 175 128 CreateMarker -299 299 128 CreateMarker -445 331 128 CreateMarker -550 558 128 CreateMarker -813 412 88 CreateMarker -796 515 40 CreateMarker -699 616 -8 CreateMarker -564 651 -40 CreateMarker -389 311 -8 CreateMarker -287 228 24 CreateMarker -148 193 24 CreateMarker -98 347 24 CreateMarker 12 156 24 CreateMarker 225 144 24 CreateMarker 359 329 24 CreateMarker 132 702 156 CreateMarker 752 557 280 SetGoal 1 18 SetZone 1 6 SetMarkerPath 1 0 29 SetGoal 2 17 SetZone 2 6 SetMarkerPath 2 0 29 SetMarkerPath 2 1 26 SetGoal 3 13 SetZone 3 5 SetMarkerPath 3 0 85 SetMarkerPath 3 1 4 SetGoal 4 15 SetZone 4 5 SetMarkerPath 4 0 84 SetMarkerPath 4 1 3 SetGoal 5 15 SetZone 5 5 SetMarkerPath 5 0 84 SetMarkerPath 5 1 8 SetGoal 6 14 SetZone 6 5 SetMarkerPath 6 0 45 SetMarkerPath 6 1 85 SetGoal 7 23 SetZone 7 5 SetMarkerPath 7 0 8 SetMarkerPath 7 1 45 SetGoal 8 20 SetZone 8 5 SetMarkerPath 8 0 5 SetMarkerPath 8 1 7 SetGoal 9 12 SetZone 9 2 SetMarkerPath 9 0 21 SetGoal 10 11 SetZone 10 7 SetMarkerPath 10 0 92 SetMarkerPath 10 1 74 SetMarkerPath 10 2 13 SetMarkerPath 10 3 12 SetZone 11 1 SetMarkerPath 11 0 12 SetZone 12 7 SetMarkerViewOfs 12 2 SetMarkerPath 12 0 13 SetMarkerPath 12 1 10 SetZone 13 7 SetMarkerViewOfs 13 13 SetMarkerPath 13 0 12 SetMarkerPath 13 1 92 SetMarkerPath 13 2 10 SetGoal 14 10 SetZone 14 3 SetMarkerPath 14 0 44 SetZone 15 2 SetMarkerPath 15 0 28 SetMarkerPath 15 1 26 SetZone 16 3 SetMarkerPath 16 0 17 SetZone 17 8 SetMarkerViewOfs 17 -17 SetMarkerPath 17 0 23 SetZone 18 8 SetMarkerPath 18 0 19 SetZone 19 8 SetMarkerViewOfs 19 -10 SetMarkerPath 19 0 58 SetZone 20 8 SetMarkerPath 20 0 55 SetMarkerPath 20 1 21 SetZone 21 1 SetMarkerViewOfs 21 -58 SetMarkerPath 21 0 55 SetMarkerPath 21 1 9 SetMarkerPath 21 2 38 SetMarkerPath 21 3 37 SetGoal 22 9 SetZone 22 8 SetMarkerPath 22 0 19 SetGoal 23 8 SetZone 23 8 SetMarkerPath 23 0 17 SetMarkerPath 23 1 18 SetZone 24 6 SetMarkerPath 24 0 26 SetMarkerPath 24 1 25 SetZone 25 4 SetMarkerViewOfs 25 -34 SetMarkerPath 25 0 46 SetMarkerPath 25 1 80 SetZone 26 6 SetMarkerViewOfs 26 -10 SetMarkerPath 26 0 47 SetMarkerPath 26 1 29 SetMarkerPath 26 2 2 SetMarkerPath 26 3 24 SetZone 27 4 SetMarkerPath 27 0 28 SetZone 28 2 SetMarkerViewOfs 28 -14 SetMarkerPath 28 0 43 SetMarkerPath 28 1 15 SetGoal 29 21 SetZone 29 6 SetMarkerPath 29 0 49 SetMarkerPath 29 1 1 SetMarkerPath 29 2 47 SetMarkerPath 29 3 2 SetMarkerPath 29 4 26 SetGoal 30 7 SetZone 30 3 SetMarkerPath 30 0 72 SetMarkerPath 30 1 73 SetMarkerPath 30 2 48 SetMarkerPath 30 3 31 SetGoal 31 19 SetZone 31 3 SetMarkerPath 31 0 30 SetMarkerPath 31 1 48 SetMarkerPath 31 2 16 SetGoal 32 6 SetZone 32 4 SetMarkerPath 32 0 80 SetMarkerPathFlags 32 0 j SetMarkerPath 32 1 84 SetMarkerPathFlags 32 1 j SetGoal 33 22 SetZone 33 1 SetMarkerPath 33 0 35 SetMarkerPath 33 1 11 SetGoal 34 23 SetZone 34 1 SetMarkerPath 34 0 61 SetMarkerPath 34 1 35 SetMarkerPath 34 2 55 SetMarkerPath 34 3 62 SetGoal 35 23 SetZone 35 1 SetMarkerPath 35 0 34 SetMarkerPath 35 1 33 SetGoal 36 5 SetZone 36 3 SetMarkerPath 36 0 60 SetMarkerPath 36 1 59 SetGoal 37 4 SetZone 37 1 SetMarkerPath 37 0 21 SetMarkerPath 37 1 60 SetMarkerPath 37 2 55 SetGoal 38 4 SetZone 38 1 SetMarkerPath 38 0 62 SetMarkerPath 38 1 64 SetMarkerPath 38 2 21 SetGoal 39 2 SetZone 39 2 SetMarkerPath 39 0 40 SetMarkerPath 39 1 67 SetGoal 40 2 SetZone 40 2 SetMarkerPath 40 0 66 SetMarkerPath 40 1 39 SetMarkerPath 40 2 67 SetGoal 41 3 SetZone 41 5 SetMarkerPath 41 0 46 SetMarkerPath 41 1 81 SetGoal 42 22 SetZone 42 4 SetMarkerPath 42 0 75 SetMarkerPath 42 1 76 SetZone 43 2 SetMarkerViewOfs 43 5 SetMarkerPath 43 0 65 SetMarkerPath 43 1 28 SetZone 44 3 SetMarkerViewOfs 44 -7 SetMarkerPath 44 0 14 SetMarkerPath 44 1 72 SetZone 45 5 SetMarkerViewOfs 45 -47 SetMarkerPath 45 0 7 SetMarkerPath 45 1 6 SetZone 46 4 SetMarkerViewOfs 46 -1 SetMarkerPath 46 0 25 SetMarkerPath 46 1 79 SetMarkerPath 46 2 41 SetZone 47 6 SetMarkerViewOfs 47 1 SetMarkerPath 47 0 29 SetMarkerPath 47 1 26 SetZone 48 3 SetMarkerViewOfs 48 -3 SetMarkerPath 48 1 31 SetGoal 49 24 SetZone 49 6 SetMarkerPath 49 0 50 SetMarkerPath 49 1 29 SetGoal 50 24 SetZone 50 6 SetMarkerPath 50 0 90 SetMarkerPath 50 1 49 SetMarkerPath 50 2 91 SetGoal 51 1 SetZone 51 1 SetMarkerPath 51 0 60 SetMarkerPath 51 1 61 SetGoal 52 21 SetZone 52 4 SetMarkerPath 52 0 79 SetMarkerPath 52 1 80 SetZone 53 4 SetZone 54 4 SetZone 55 1 SetMarkerViewOfs 55 1 SetMarkerPath 55 0 34 SetMarkerPath 55 1 62 SetMarkerPath 55 2 21 SetMarkerPath 55 3 61 SetMarkerPath 55 4 37 SetZone 57 8 SetMarkerPath 57 0 17 SetMarkerPathFlags 57 0 j SetMarkerPath 57 1 48 SetMarkerPathFlags 57 1 j SetZone 58 8 SetMarkerPath 58 0 19 SetMarkerPath 58 1 20 SetZone 59 3 SetMarkerPath 59 0 36 SetMarkerPath 59 1 69 SetZone 60 1 SetMarkerPath 60 0 51 SetMarkerPath 60 1 37 SetMarkerPath 60 2 61 SetMarkerPath 60 3 68 SetMarkerPath 60 4 36 SetZone 61 1 SetMarkerPath 61 0 51 SetMarkerPath 61 1 34 SetMarkerPath 61 2 60 SetMarkerPath 61 3 55 SetZone 62 1 SetMarkerPath 62 0 34 SetMarkerPath 62 1 55 SetMarkerPath 62 2 38 SetMarkerPath 62 3 64 SetZone 63 2 SetMarkerPath 63 0 64 SetMarkerPath 63 1 65 SetZone 64 1 SetMarkerPath 64 0 62 SetMarkerPath 64 1 38 SetMarkerPath 64 2 63 SetZone 65 2 SetMarkerPath 65 0 63 SetMarkerPath 65 1 43 SetZone 66 2 SetMarkerPath 66 0 40 SetMarkerPath 66 1 74 SetZone 67 2 SetMarkerPath 67 0 39 SetMarkerPath 67 1 40 SetMarkerPath 67 2 68 SetZone 68 2 SetMarkerPath 68 0 67 SetMarkerPath 68 1 60 SetZone 69 3 SetMarkerPath 69 0 59 SetMarkerPath 69 1 70 SetZone 70 3 SetMarkerPath 70 0 69 SetMarkerPath 70 1 71 SetZone 71 3 SetMarkerPath 71 0 70 SetZone 72 3 SetMarkerPath 72 0 44 SetMarkerPath 72 1 30 SetZone 73 3 SetMarkerPath 73 0 30 SetMarkerPath 73 1 74 SetZone 74 4 SetMarkerPath 74 0 75 SetMarkerPath 74 1 73 SetZone 75 4 SetMarkerPath 75 0 74 SetMarkerPath 75 1 42 SetMarkerPath 75 2 76 SetZone 76 4 SetMarkerPath 76 0 42 SetMarkerPath 76 1 78 SetMarkerPath 76 2 77 SetMarkerPath 76 3 75 SetZone 77 4 SetMarkerPath 77 0 78 SetMarkerPath 77 1 76 SetZone 78 4 SetMarkerPath 78 0 76 SetMarkerPath 78 1 77 SetMarkerPath 78 2 79 SetZone 79 4 SetMarkerPath 79 0 78 SetMarkerPath 79 1 52 SetMarkerPath 79 2 46 SetZone 80 4 SetMarkerPath 80 0 25 SetMarkerPath 80 1 52 SetMarkerPath 80 2 32 SetMarkerPathFlags 80 2 j SetZone 81 5 SetMarkerPath 81 0 41 SetMarkerPath 81 1 82 SetZone 82 5 SetMarkerPath 82 0 81 SetMarkerPath 82 1 83 SetZone 83 5 SetMarkerPath 83 0 82 SetMarkerPath 83 1 84 SetZone 84 5 SetMarkerPath 84 0 83 SetMarkerPath 84 1 4 SetMarkerPath 84 2 5 SetZone 85 5 SetMarkerPath 85 0 6 SetMarkerPath 85 1 3 SetMarkerPath 85 2 86 SetZone 86 5 SetMarkerPath 86 0 85 SetMarkerPath 86 1 87 SetZone 87 6 SetMarkerPath 87 0 86 SetMarkerPath 87 1 89 SetMarkerPath 87 2 88 SetZone 88 6 SetMarkerPath 88 0 87 SetZone 89 6 SetMarkerPath 89 0 87 SetMarkerPath 89 1 90 SetMarkerPathFlags 89 1 j SetZone 90 6 SetMarkerPath 90 0 89 SetMarkerPathFlags 90 0 j SetMarkerPath 90 1 50 SetZone 91 6 SetMarkerPath 91 0 50 SetZone 92 7 SetMarkerPath 92 2 13 SetZone 93 8 SetMarkerPath 93 0 31 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ukooldm6.bot000066400000000000000000000201341475442401000265060ustar00rootroot00000000000000CreateMarker 485 563 152 CreateMarker 619 647 152 CreateMarker 581 838 152 CreateMarker 586 979 152 CreateMarker -441 -826 248 CreateMarker -218 -817 200 CreateMarker -139 -748 168 CreateMarker -277 -611 152 CreateMarker -79 -517 152 CreateMarker 58 -313 152 CreateMarker -153 -286 152 CreateMarker -247 -89 152 CreateMarker -394 -216 152 CreateMarker -575 -437 152 CreateMarker -498 -556 152 CreateMarker 80 -446 152 CreateMarker -172 183 56 CreateMarker 14 -56 56 CreateMarker 18 153 72 CreateMarker 91 210 120 CreateMarker 200 224 152 CreateMarker 211 390 152 CreateMarker 82 -187 24 CreateMarker 203 -174 -8 CreateMarker 288 -148 -40 CreateMarker 377 28 -40 CreateMarker 385 197 -40 CreateMarker 418 361 -40 CreateMarker 669 390 312 CreateMarker 547 492 312 CreateMarker 386 467 312 CreateMarker 361 294 312 CreateMarker 263 5 312 CreateMarker -44 -80 312 CreateMarker 240 -223 312 CreateMarker 221 -432 312 CreateMarker 53 -442 312 CreateMarker 14 -616 312 CreateMarker 295 548 152 CreateMarker 123 739 184 CreateMarker 12 712 216 CreateMarker -103 614 264 CreateMarker -112 485 296 CreateMarker -215 357 312 CreateMarker -289 414 312 CreateMarker -452 419 312 CreateMarker -425 237 312 CreateMarker -356 59 312 CreateMarker -510 0 312 CreateMarker -553 -220 304 CreateMarker -554 -389 312 CreateMarker -520 -587 312 CreateMarker 795 942 40 CreateMarker 701 958 8 SetGoal 1 1 SetZone 1 7 SetMarkerPath 1 0 62 SetMarkerPath 1 1 79 SetGoal 2 22 SetZone 2 7 SetMarkerPath 2 0 61 SetZone 3 3 SetMarkerPath 3 0 21 SetZone 4 4 SetMarkerPath 4 0 9 SetZone 5 4 SetMarkerViewOfs 5 -2 SetMarkerPath 5 0 70 SetMarkerPath 5 1 71 SetMarkerPath 5 2 4 SetMarkerPath 5 3 37 SetZone 6 2 SetMarkerPath 6 0 15 SetZone 7 2 SetMarkerViewOfs 7 -2 SetMarkerPath 7 0 57 SetMarkerPath 7 1 6 SetZone 8 8 SetMarkerPath 8 0 5 SetZone 9 8 SetMarkerViewOfs 9 -2 SetMarkerPath 9 0 93 SetGoal 10 2 SetZone 10 8 SetMarkerPath 10 0 94 SetMarkerPath 10 1 32 SetGoal 11 23 SetZone 11 5 SetMarkerPath 11 0 72 SetMarkerPath 11 1 12 SetGoal 12 23 SetZone 12 5 SetMarkerPath 12 0 11 SetMarkerPath 12 1 13 SetGoal 13 20 SetZone 13 5 SetMarkerPath 13 0 12 SetMarkerPath 13 1 73 SetGoal 14 3 SetZone 14 4 SetMarkerPath 14 0 71 SetZone 15 9 SetMarkerViewOfs 15 -2 SetMarkerPath 15 0 86 SetMarkerPath 15 1 16 SetZone 16 9 SetMarkerPath 16 0 7 SetGoal 17 4 SetZone 17 8 SetMarkerPath 17 0 44 SetGoal 18 5 SetZone 18 5 SetMarkerPath 18 0 74 SetGoal 19 6 SetZone 19 8 SetMarkerPath 19 0 33 SetMarkerPath 19 1 20 SetGoal 20 6 SetZone 20 8 SetMarkerPath 20 0 94 SetMarkerPath 20 1 19 SetZone 21 3 SetMarkerPath 21 0 68 SetMarkerPath 21 1 3 SetGoal 22 7 SetZone 22 2 SetMarkerPath 22 0 53 SetMarkerPath 22 1 54 SetGoal 23 8 SetZone 23 9 SetMarkerPath 23 0 85 SetMarkerPath 23 1 34 SetMarkerPath 23 2 86 SetMarkerPath 23 3 24 SetGoal 24 9 SetZone 24 9 SetMarkerPath 24 0 34 SetMarkerPath 24 1 23 SetGoal 25 10 SetZone 25 1 SetMarkerPath 25 0 45 SetMarkerPath 25 1 46 SetGoal 26 11 SetZone 26 3 SetMarkerPath 26 0 27 SetMarkerPath 26 1 65 SetGoal 27 21 SetZone 27 3 SetMarkerPath 27 0 65 SetMarkerPath 27 1 26 SetGoal 28 12 SetZone 28 10 SetMarkerPath 28 0 29 SetMarkerPath 28 1 35 SetGoal 29 12 SetZone 29 10 SetMarkerPath 29 0 91 SetMarkerPath 29 1 28 SetGoal 30 23 SetZone 30 1 SetMarkerPath 30 0 48 SetMarkerPath 30 1 31 SetMarkerPath 30 2 55 SetGoal 31 19 SetZone 31 1 SetMarkerPath 31 0 30 SetMarkerPath 31 1 55 SetGoal 32 19 SetZone 32 8 SetMarkerPath 32 0 10 SetMarkerPath 32 1 33 SetZone 33 8 SetMarkerViewOfs 33 -7 SetMarkerPath 33 0 94 SetMarkerPath 33 1 19 SetMarkerPath 33 2 32 SetZone 34 9 SetMarkerPath 34 0 23 SetMarkerPath 34 1 24 SetZone 35 10 SetMarkerPath 35 0 28 SetMarkerPath 35 1 91 SetMarkerPath 35 2 92 SetZone 36 1 SetMarkerPath 36 0 47 SetMarkerPath 36 1 49 SetMarkerPath 36 2 56 SetZone 37 4 SetMarkerPath 37 0 70 SetMarkerPath 37 1 5 SetGoal 38 13 SetZone 38 3 SetMarkerPath 38 0 67 SetMarkerPath 38 1 39 SetGoal 39 13 SetZone 39 3 SetMarkerPath 39 0 38 SetMarkerPath 39 1 68 SetGoal 40 14 SetZone 40 6 SetMarkerPath 40 0 78 SetMarkerPath 40 1 46 SetMarkerPathFlags 40 1 j SetZone 41 7 SetMarkerPath 41 0 79 SetMarkerPath 41 1 42 SetZone 42 8 SetMarkerPath 42 0 41 SetMarkerPath 42 1 43 SetZone 43 8 SetMarkerPath 43 0 42 SetMarkerPath 43 1 44 SetZone 44 8 SetMarkerPath 44 0 17 SetMarkerPath 44 1 43 SetMarkerPath 44 2 93 SetMarkerPathFlags 44 2 j SetZone 45 1 SetMarkerPath 45 0 25 SetMarkerPath 45 1 46 SetMarkerPath 45 2 48 SetMarkerPathFlags 45 2 j SetZone 46 1 SetMarkerPath 46 0 47 SetMarkerPath 46 1 45 SetZone 47 1 SetMarkerPath 47 0 46 SetMarkerPath 47 1 36 SetMarkerPath 47 2 49 SetMarkerPath 47 3 48 SetZone 48 1 SetMarkerPath 48 0 47 SetMarkerPath 48 1 30 SetMarkerPath 48 2 55 SetMarkerPath 48 3 49 SetZone 49 1 SetMarkerPath 49 0 36 SetMarkerPath 49 1 47 SetMarkerPath 49 2 48 SetMarkerPath 49 3 56 SetZone 50 1 SetMarkerPath 50 0 56 SetMarkerPath 50 1 51 SetZone 51 2 SetMarkerPath 51 0 50 SetMarkerPath 51 1 52 SetMarkerPath 51 2 53 SetZone 52 2 SetMarkerPath 52 0 51 SetMarkerPath 52 1 53 SetMarkerPath 52 4 57 SetMarkerPathFlags 52 4 j SetZone 53 2 SetMarkerPath 53 0 52 SetMarkerPath 53 1 51 SetMarkerPath 53 2 22 SetZone 54 2 SetMarkerPath 54 0 22 SetMarkerPath 54 1 55 SetZone 55 1 SetMarkerPath 55 0 31 SetMarkerPath 55 1 30 SetMarkerPath 55 2 48 SetMarkerPath 55 3 54 SetZone 56 1 SetMarkerPath 56 0 49 SetMarkerPath 56 1 36 SetMarkerPath 56 2 50 SetZone 57 2 SetMarkerPath 57 0 59 SetMarkerPath 57 1 7 SetMarkerPath 57 2 58 SetZone 58 2 SetMarkerPath 58 0 59 SetMarkerPath 58 1 57 SetMarkerPath 58 2 63 SetZone 59 2 SetMarkerPath 59 0 58 SetMarkerPath 59 1 60 SetMarkerPath 59 2 57 SetZone 60 2 SetMarkerPath 60 0 59 SetMarkerPath 60 1 61 SetZone 61 7 SetMarkerPath 61 0 60 SetMarkerPath 61 1 2 SetMarkerPath 61 2 62 SetZone 62 7 SetMarkerPath 62 0 61 SetMarkerPath 62 1 1 SetMarkerPath 62 2 79 SetZone 63 3 SetMarkerPath 63 0 58 SetMarkerPath 63 1 64 SetZone 64 3 SetMarkerPath 64 0 63 SetMarkerPath 64 1 65 SetZone 65 3 SetMarkerPath 65 0 64 SetMarkerPath 65 1 27 SetMarkerPath 65 2 66 SetMarkerPath 65 3 26 SetZone 66 3 SetMarkerPath 66 0 65 SetMarkerPath 66 1 67 SetZone 67 3 SetMarkerPath 67 0 66 SetMarkerPath 67 1 38 SetMarkerPath 67 2 68 SetZone 68 3 SetMarkerPath 68 0 39 SetMarkerPath 68 1 67 SetMarkerPath 68 2 21 SetZone 69 4 SetMarkerPath 69 0 70 SetZone 70 4 SetMarkerPath 70 0 71 SetMarkerPath 70 1 69 SetMarkerPath 70 2 37 SetMarkerPath 70 3 5 SetZone 71 4 SetMarkerPath 71 0 72 SetMarkerPath 71 1 14 SetMarkerPath 71 2 70 SetMarkerPath 71 3 5 SetZone 72 4 SetMarkerPath 72 0 71 SetMarkerPath 72 1 11 SetMarkerPath 72 2 73 SetZone 73 5 SetMarkerPath 73 0 13 SetMarkerPath 73 1 72 SetMarkerPath 73 2 74 SetMarkerPathFlags 73 2 j SetMarkerPath 73 3 75 SetZone 74 5 SetMarkerPath 74 0 18 SetMarkerPath 74 1 73 SetMarkerPathFlags 74 1 j SetMarkerPath 74 2 59 SetMarkerPathFlags 74 2 j SetZone 75 5 SetMarkerPath 75 0 73 SetMarkerPath 75 1 76 SetZone 76 5 SetMarkerPath 76 0 75 SetMarkerPath 76 1 77 SetZone 77 6 SetMarkerPath 77 0 76 SetMarkerPath 77 1 78 SetZone 78 6 SetMarkerPath 78 0 77 SetMarkerPath 78 1 40 SetZone 79 7 SetMarkerPath 79 0 62 SetMarkerPath 79 1 1 SetMarkerPath 79 2 80 SetMarkerPath 79 3 41 SetZone 80 7 SetMarkerPath 80 0 79 SetMarkerPath 80 1 81 SetZone 81 7 SetMarkerPath 81 0 80 SetMarkerPath 81 1 82 SetZone 82 7 SetMarkerPath 82 0 81 SetMarkerPath 82 1 83 SetZone 83 7 SetMarkerPath 83 0 82 SetMarkerPath 83 1 84 SetZone 84 9 SetMarkerPath 84 0 83 SetMarkerPath 84 1 85 SetZone 85 9 SetMarkerPath 85 0 84 SetMarkerPath 85 1 23 SetMarkerPath 85 2 86 SetZone 86 9 SetMarkerPath 86 0 85 SetMarkerPath 86 1 23 SetMarkerPath 86 2 15 SetMarkerPath 86 3 87 SetZone 87 9 SetMarkerPath 87 0 86 SetMarkerPath 87 1 88 SetMarkerPath 87 2 89 SetZone 88 10 SetMarkerPath 88 0 87 SetMarkerPath 88 1 89 SetMarkerPath 88 2 59 SetMarkerPathFlags 88 2 j SetZone 89 10 SetMarkerPath 89 0 88 SetMarkerPath 89 1 87 SetMarkerPath 89 2 90 SetZone 90 10 SetMarkerPath 90 0 89 SetMarkerPath 90 1 91 SetZone 91 10 SetMarkerPath 91 0 90 SetMarkerPath 91 1 29 SetMarkerPath 91 2 35 SetMarkerPath 91 3 92 SetZone 92 10 SetMarkerPath 92 0 35 SetMarkerPath 92 1 91 SetMarkerPath 92 2 48 SetMarkerPathFlags 92 2 j SetZone 93 8 SetMarkerPath 93 0 9 SetMarkerPath 93 1 94 SetZone 94 8 SetMarkerPath 94 0 93 SetMarkerPath 94 1 20 SetMarkerPath 94 2 10 SetMarkerPath 94 3 33 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ukooldm8.bot000066400000000000000000000142231475442401000265120ustar00rootroot00000000000000CreateMarker 525 -916 328 CreateMarker 370 486 248 CreateMarker 472 690 248 CreateMarker 661 647 248 CreateMarker 743 375 184 CreateMarker 734 248 152 CreateMarker 742 130 136 CreateMarker 693 -15 136 CreateMarker 521 -147 136 CreateMarker 919 -139 248 CreateMarker 364 -127 136 CreateMarker 390 -300 136 CreateMarker 218 -355 136 CreateMarker 171 -758 136 CreateMarker 204 -969 136 CreateMarker 176 -1123 136 CreateMarker 355 -1136 136 CreateMarker 500 -1347 328 CreateMarker 516 -1040 328 CreateMarker 362 -757 328 CreateMarker 200 -569 328 CreateMarker 201 -359 328 CreateMarker 203 -178 328 CreateMarker 11 124 328 CreateMarker -263 11 328 CreateMarker -19 -137 136 CreateMarker 170 -142 136 CreateMarker 197 52 136 CreateMarker 102 136 136 CreateMarker 63 448 136 CreateMarker 218 500 136 CreateMarker 107 634 136 CreateMarker 28 33 24 CreateMarker 554 -786 -8 CreateMarker 365 -981 -8 CreateMarker 219 -794 -8 CreateMarker 542 -1047 -8 CreateMarker 380 -784 -8 CreateMarker 199 -1050 -8 SetZone 1 4 SetMarkerPath 1 0 26 SetMarkerPath 1 1 59 SetZone 2 5 SetMarkerPath 2 0 36 SetMarkerPath 2 1 65 SetZone 3 2 SetMarkerViewOfs 3 10 SetMarkerPath 3 0 35 SetMarkerPath 3 1 54 SetZone 4 5 SetMarkerPath 4 0 66 SetMarkerPath 4 1 3 SetZone 5 6 SetMarkerPath 5 0 30 SetMarkerPath 5 1 44 SetZone 6 1 SetMarkerViewOfs 6 14 SetMarkerPath 6 0 57 SetMarkerPath 6 1 22 SetZone 7 6 SetMarkerPath 7 0 18 SetMarkerPath 7 1 6 SetZone 8 2 SetMarkerPath 8 0 21 SetMarkerPath 8 1 52 SetZone 9 5 SetMarkerViewOfs 9 14 SetMarkerPath 9 0 36 SetMarkerPath 9 1 37 SetMarkerPath 9 2 38 SetZone 10 2 SetMarkerPath 10 0 21 SetMarkerPath 10 1 9 SetGoal 11 1 SetZone 11 5 SetMarkerPath 11 0 36 SetMarkerPath 11 1 37 SetGoal 12 19 SetZone 12 3 SetMarkerPath 12 0 51 SetGoal 13 20 SetZone 13 2 SetMarkerPath 13 0 54 SetMarkerPath 13 1 55 SetGoal 14 23 SetZone 14 5 SetMarkerPath 14 0 37 SetMarkerPath 14 1 38 SetGoal 15 21 SetZone 15 6 SetMarkerPath 15 0 41 SetMarkerPath 15 1 42 SetGoal 16 22 SetZone 16 3 SetMarkerPath 16 0 47 SetMarkerPath 16 1 31 SetGoal 17 24 SetZone 17 3 SetMarkerPath 17 0 31 SetMarkerPath 17 1 48 SetGoal 18 18 SetZone 18 6 SetMarkerPath 18 0 19 SetMarkerPath 18 1 7 SetGoal 19 18 SetZone 19 6 SetMarkerPath 19 0 44 SetMarkerPath 19 1 18 SetGoal 20 23 SetZone 20 1 SetMarkerPath 20 0 33 SetMarkerPath 20 1 59 SetGoal 21 17 SetZone 21 2 SetMarkerPath 21 0 24 SetMarkerPath 21 1 10 SetMarkerPath 21 2 8 SetGoal 22 2 SetZone 22 1 SetMarkerPath 22 0 6 SetMarkerPath 22 1 58 SetGoal 23 3 SetZone 23 4 SetMarkerPath 23 0 46 SetMarkerPath 23 1 47 SetGoal 24 4 SetZone 24 2 SetMarkerPath 24 0 50 SetMarkerPath 24 1 21 SetGoal 25 5 SetZone 25 5 SetMarkerPath 25 0 64 SetMarkerPath 25 1 66 SetGoal 26 6 SetZone 26 4 SetMarkerPath 26 0 1 SetMarkerPath 26 1 60 SetGoal 27 7 SetZone 27 6 SetMarkerPath 27 0 38 SetMarkerPath 27 1 34 SetGoal 28 24 SetZone 28 5 SetMarkerPath 28 0 66 SetZone 29 4 SetMarkerViewOfs 29 17 SetMarkerPath 29 0 63 SetMarkerPath 29 1 64 SetZone 30 6 SetMarkerViewOfs 30 17 SetMarkerPath 30 0 42 SetMarkerPath 30 1 5 SetMarkerPath 30 2 43 SetZone 31 3 SetMarkerViewOfs 31 17 SetMarkerPath 31 0 16 SetMarkerPath 31 1 17 SetZone 32 2 SetMarkerViewOfs 32 17 SetMarkerPath 32 0 52 SetMarkerPath 32 1 53 SetZone 33 1 SetMarkerViewOfs 33 17 SetMarkerPath 33 0 58 SetMarkerPath 33 1 20 SetMarkerPath 33 2 59 SetZone 34 6 SetMarkerPath 34 0 27 SetMarkerPath 34 1 38 SetMarkerPath 34 2 39 SetZone 35 2 SetMarkerPath 35 0 53 SetMarkerPath 35 1 3 SetZone 36 5 SetMarkerPath 36 0 9 SetMarkerPath 36 1 11 SetMarkerPath 36 2 37 SetZone 37 5 SetMarkerPath 37 0 36 SetMarkerPath 37 1 14 SetMarkerPath 37 2 11 SetMarkerPath 37 3 9 SetMarkerPath 37 4 38 SetZone 38 6 SetMarkerPath 38 0 27 SetMarkerPath 38 1 9 SetMarkerPath 38 2 14 SetMarkerPath 38 3 37 SetMarkerPath 38 4 34 SetZone 39 6 SetMarkerPath 39 0 34 SetMarkerPath 39 1 40 SetZone 40 6 SetMarkerPath 40 0 39 SetMarkerPath 40 1 41 SetZone 41 6 SetMarkerPath 41 0 40 SetMarkerPath 41 1 15 SetMarkerPath 41 2 42 SetZone 42 6 SetMarkerPath 42 0 41 SetMarkerPath 42 1 15 SetMarkerPath 42 2 30 SetMarkerPath 42 3 43 SetZone 43 4 SetMarkerPath 43 0 42 SetMarkerPath 43 1 30 SetMarkerPath 43 2 45 SetZone 44 6 SetMarkerPath 44 0 19 SetZone 45 4 SetMarkerPath 45 0 43 SetMarkerPath 45 1 46 SetMarkerPath 45 2 61 SetZone 46 4 SetMarkerPath 46 0 45 SetMarkerPath 46 1 23 SetMarkerPath 46 2 47 SetZone 47 3 SetMarkerPath 47 0 23 SetMarkerPath 47 1 46 SetMarkerPath 47 2 16 SetZone 48 3 SetMarkerPath 48 0 17 SetMarkerPath 48 1 49 SetZone 49 3 SetMarkerPath 49 0 48 SetMarkerPath 49 1 50 SetZone 50 3 SetMarkerPath 50 0 49 SetMarkerPath 50 1 51 SetMarkerPath 50 2 24 SetZone 51 3 SetMarkerPath 51 0 50 SetMarkerPath 51 1 12 SetZone 52 2 SetMarkerPath 52 0 32 SetZone 53 2 SetMarkerPath 53 0 32 SetMarkerPath 53 1 35 SetMarkerPath 53 2 49 SetMarkerPathFlags 53 2 j SetZone 54 2 SetMarkerPath 54 0 3 SetMarkerPath 54 1 13 SetZone 55 1 SetMarkerPath 55 0 13 SetMarkerPath 55 1 56 SetZone 56 1 SetMarkerPath 56 0 55 SetMarkerPath 56 1 57 SetZone 57 1 SetMarkerPath 57 0 56 SetMarkerPath 57 1 6 SetZone 58 1 SetMarkerPath 58 0 22 SetMarkerPath 58 1 33 SetZone 59 1 SetMarkerPath 59 0 20 SetMarkerPath 59 1 33 SetZone 60 4 SetMarkerPath 60 0 61 SetMarkerPath 60 1 26 SetZone 61 4 SetMarkerPath 61 0 60 SetMarkerPath 61 1 62 SetMarkerPath 61 2 45 SetZone 62 4 SetMarkerPath 62 0 61 SetMarkerPath 62 1 63 SetZone 63 4 SetMarkerPath 63 0 62 SetMarkerPath 63 1 29 SetZone 64 5 SetMarkerPath 64 0 29 SetMarkerPath 64 1 65 SetMarkerPath 64 2 25 SetMarkerPath 64 3 66 SetZone 65 5 SetMarkerPath 65 0 64 SetMarkerPath 65 1 66 SetMarkerPath 65 2 2 SetZone 66 5 SetMarkerPath 66 0 64 SetMarkerPath 66 1 25 SetMarkerPath 66 2 4 SetMarkerPath 66 3 28 SetMarkerPath 66 4 65 SetZone 67 7 SetMarkerFlag 67 u SetMarkerPath 67 0 60 SetMarkerPathFlags 67 0 6r SetRocketJumpPathFields 67 0 67.0 82.0 0 SetZone 68 8 SetMarkerFlag 68 u SetMarkerPath 68 0 72 SetMarkerPath 68 1 69 SetMarkerPath 68 2 71 SetZone 69 8 SetMarkerFlag 69 u SetMarkerPath 69 0 73 SetMarkerPath 69 1 70 SetMarkerPath 69 2 68 SetZone 70 8 SetMarkerFlag 70 u SetMarkerPath 70 0 72 SetMarkerPath 70 1 69 SetZone 71 8 SetMarkerFlag 71 u SetMarkerPath 71 0 69 SetMarkerPath 71 1 68 SetZone 72 8 SetMarkerFlag 72 u SetMarkerPath 72 0 69 SetMarkerPath 72 1 68 SetZone 73 8 SetMarkerFlag 73 u SetMarkerPath 73 0 69 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ukpak2.bot000066400000000000000000000364111475442401000261500ustar00rootroot00000000000000CreateMarker -1633 -146 24 CreateMarker -1599 97 24 CreateMarker -2095 -143 24 CreateMarker -1840 96 24 CreateMarker -1390 -382 24 CreateMarker -2041 -280 24 CreateMarker -1869 -347 24 CreateMarker -2024 54 24 CreateMarker -1391 -802 -168 CreateMarker -1412 -541 -168 CreateMarker -1428 -652 -168 CreateMarker -1286 -797 24 CreateMarker -1284 -541 24 CreateMarker -1189 -1115 24 CreateMarker -1189 -836 24 CreateMarker -1184 -581 24 CreateMarker -1491 -782 -168 CreateMarker -1182 -405 24 CreateMarker -1988 -124 24 CreateMarker -1527 -274 24 CreateMarker -1660 -385 24 CreateMarker 1546 -646 -152 CreateMarker 1733 -439 -152 CreateMarker 1535 -447 -152 CreateMarker -1497 -852 24 CreateMarker -1520 -726 24 CreateMarker -1520 -616 24 CreateMarker 1537 -152 -120 CreateMarker 1380 -248 -120 CreateMarker 1526 14 -152 CreateMarker 1751 4 -152 CreateMarker 1315 8 -120 CreateMarker 1134 -16 -120 CreateMarker 1768 -579 -152 CreateMarker 1670 -697 -152 CreateMarker 1414 -440 -120 CreateMarker 666 -37 -120 CreateMarker 906 -22 -120 CreateMarker 638 267 -184 CreateMarker 647 118 -136 CreateMarker 815 318 -184 CreateMarker 923 193 -184 CreateMarker 611 572 -184 CreateMarker 450 718 -184 CreateMarker 436 505 -184 CreateMarker 298 821 -184 CreateMarker 285 501 -136 CreateMarker 653 391 -184 CreateMarker 1429 -557 -136 CreateMarker 120 570 -120 CreateMarker -88 670 -120 CreateMarker -369 661 -120 CreateMarker -520 220 -120 CreateMarker -375 505 -120 CreateMarker -396 302 -120 CreateMarker 71 755 -120 CreateMarker 3 103 280 CreateMarker 6 24 280 CreateMarker 204 48 280 CreateMarker 39 -181 280 CreateMarker 163 -428 280 CreateMarker -152 -435 280 CreateMarker -78 -282 280 CreateMarker -73 -66 280 CreateMarker -911 218 -120 CreateMarker -1101 226 -40 CreateMarker -1250 332 24 CreateMarker -1040 408 24 CreateMarker -1226 108 24 CreateMarker -1045 69 24 CreateMarker -870 55 24 CreateMarker -673 67 24 CreateMarker -660 391 24 CreateMarker -846 395 24 CreateMarker -660 551 24 CreateMarker -786 636 24 CreateMarker -978 645 24 CreateMarker -1160 640 24 CreateMarker -1356 621 24 CreateMarker -1555 521 24 CreateMarker -1618 299 24 CreateMarker 674 -957 24 CreateMarker 666 -552 24 CreateMarker 396 -301 24 CreateMarker 595 -366 24 CreateMarker 560 -773 24 CreateMarker 209 -305 24 CreateMarker -49 -138 24 CreateMarker -229 -184 24 CreateMarker -442 -146 24 CreateMarker -666 -147 24 CreateMarker 28 -812 -40 CreateMarker 267 -654 -40 CreateMarker 239 -977 -40 CreateMarker 143 -520 -8 CreateMarker -169 -513 -8 CreateMarker -8 -535 -24 CreateMarker 393 -815 -40 CreateMarker -318 -685 -40 CreateMarker -197 -1037 -40 CreateMarker -465 -858 -40 CreateMarker -207 -371 24 CreateMarker -901 -250 24 CreateMarker -933 -443 24 CreateMarker -880 -578 24 CreateMarker -843 -777 24 CreateMarker -909 -956 24 CreateMarker -1009 -1138 24 CreateMarker -546 -815 24 SetZone 1 5 SetMarkerPath 1 1 112 SetZone 2 6 SetMarkerPath 2 1 5 SetMarkerPath 2 2 115 SetGoal 3 4 SetZone 3 6 SetMarkerPath 3 1 119 SetMarkerPath 3 2 118 SetZone 4 9 SetMarkerPath 4 1 6 SetMarkerPath 4 2 5 SetZone 5 9 SetMarkerPath 5 1 137 SetMarkerPath 5 2 4 SetZone 6 6 SetMarkerPath 6 1 115 SetZone 7 2 SetMarkerPath 7 1 16 SetMarkerPath 7 2 9 SetZone 8 3 SetMarkerPath 8 1 10 SetZone 9 3 SetMarkerPath 9 1 7 SetMarkerPath 9 2 90 SetMarkerPath 9 3 89 SetZone 10 11 SetMarkerPath 10 1 147 SetMarkerPath 10 2 155 SetMarkerPath 10 3 149 SetGoal 11 5 SetZone 11 4 SetMarkerPath 11 1 94 SetMarkerPath 11 2 100 SetMarkerPath 11 3 42 SetMarkerPath 11 4 41 SetMarkerPath 11 5 103 SetGoal 12 11 SetZone 12 7 SetMarkerPath 12 1 121 SetMarkerPath 12 2 124 SetMarkerPath 12 3 122 SetGoal 13 6 SetZone 13 9 SetMarkerPath 13 1 138 SetMarkerPath 13 2 141 SetMarkerPath 13 3 137 SetGoal 14 12 SetZone 14 12 SetMarkerPath 14 1 161 SetMarkerPath 14 2 164 SetGoal 15 1 SetZone 15 1 SetMarkerPath 15 1 56 SetMarkerPath 15 2 74 SetMarkerPath 15 3 59 SetMarkerPath 15 4 62 SetGoal 16 2 SetZone 16 2 SetMarkerPath 16 1 65 SetMarkerPath 16 2 7 SetGoal 17 9 SetZone 17 3 SetMarkerPath 17 1 104 SetMarkerPath 17 2 77 SetMarkerPath 17 3 45 SetGoal 18 22 SetZone 18 5 SetMarkerPath 18 1 110 SetMarkerPath 18 2 1 SetMarkerPathFlags 18 2 v SetGoal 19 8 SetZone 19 10 SetMarkerPath 19 1 143 SetMarkerPath 19 2 152 SetMarkerPath 19 3 157 SetGoal 20 7 SetZone 20 7 SetMarkerPath 20 1 108 SetMarkerPath 20 2 120 SetGoal 21 20 SetZone 21 5 SetMarkerPath 21 1 22 SetGoal 22 20 SetZone 22 5 SetMarkerPath 22 1 107 SetMarkerPath 22 2 21 SetGoal 23 20 SetZone 23 6 SetMarkerPath 23 1 119 SetGoal 24 19 SetZone 24 6 SetMarkerPath 24 1 25 SetMarkerPath 24 2 118 SetGoal 25 19 SetZone 25 6 SetMarkerPath 25 1 24 SetGoal 26 21 SetZone 26 10 SetMarkerPath 26 1 143 SetMarkerPath 26 2 27 SetGoal 27 21 SetZone 27 10 SetMarkerPath 27 1 26 SetGoal 28 20 SetZone 28 9 SetMarkerPath 28 1 29 SetGoal 29 20 SetZone 29 9 SetMarkerPath 29 1 137 SetMarkerPath 29 2 28 SetGoal 30 20 SetZone 30 12 SetMarkerPath 30 1 161 SetMarkerPath 30 2 31 SetGoal 31 24 SetZone 31 12 SetMarkerPath 31 1 30 SetGoal 32 21 SetZone 32 2 SetMarkerPath 32 1 72 SetGoal 33 20 SetZone 33 1 SetMarkerPath 33 1 34 SetGoal 34 20 SetZone 34 1 SetMarkerPath 34 1 62 SetMarkerPath 34 2 33 SetGoal 35 21 SetZone 35 1 SetMarkerPath 35 1 63 SetGoal 36 23 SetZone 36 8 SetMarkerPath 36 1 37 SetGoal 37 24 SetZone 37 8 SetMarkerPath 37 1 133 SetMarkerPath 37 2 36 SetGoal 38 19 SetZone 38 7 SetMarkerPath 38 1 39 SetGoal 39 20 SetZone 39 7 SetMarkerPath 39 1 122 SetMarkerPath 39 2 38 SetMarkerPath 39 3 123 SetGoal 40 24 SetZone 40 7 SetMarkerPath 40 1 124 SetGoal 41 20 SetZone 41 4 SetMarkerPath 41 1 42 SetMarkerPath 41 2 11 SetGoal 42 21 SetZone 42 4 SetMarkerPath 42 1 11 SetMarkerPath 42 2 41 SetGoal 43 3 SetZone 43 3 SetMarkerPath 43 1 78 SetMarkerPath 43 2 83 SetGoal 44 23 SetZone 44 3 SetMarkerPath 44 1 91 SetMarkerPath 44 2 45 SetMarkerPath 44 3 46 SetGoal 45 23 SetZone 45 3 SetMarkerPath 45 1 44 SetMarkerPath 45 2 17 SetGoal 46 21 SetZone 46 3 SetMarkerPath 46 1 44 SetZone 47 11 SetMarkerPath 47 1 147 SetMarkerPath 47 2 152 SetZone 48 5 SetMarkerPath 48 1 109 SetMarkerPath 48 2 110 SetZone 49 5 SetMarkerPath 49 1 105 SetZone 50 4 SetMarkerPath 50 1 103 SetMarkerPath 50 2 98 SetMarkerPath 50 3 96 SetZone 51 3 SetMarkerPath 51 1 43 SetMarkerPath 51 2 86 SetMarkerPath 51 3 83 SetZone 52 2 SetMarkerPath 52 1 32 SetMarkerPath 52 2 64 SetZone 53 1 SetMarkerPath 53 1 59 SetZone 54 7 SetMarkerPath 54 1 122 SetMarkerPath 54 2 38 SetGoal 55 10 SetZone 55 8 SetMarkerPath 55 1 133 SetZone 56 1 SetMarkerPath 56 1 15 SetMarkerPath 56 2 76 SetMarkerPath 56 3 57 SetMarkerPath 56 4 75 SetZone 57 1 SetMarkerPath 57 1 56 SetMarkerPath 57 2 59 SetMarkerPath 57 3 136 SetZone 58 1 SetMarkerPath 58 1 74 SetMarkerPath 58 2 61 SetMarkerPath 58 3 63 SetZone 59 1 SetMarkerPath 59 1 15 SetMarkerPath 59 2 57 SetMarkerPath 59 3 63 SetMarkerPath 59 4 136 SetZone 60 1 SetMarkerPath 60 1 76 SetMarkerPath 60 2 73 SetMarkerPath 60 3 75 SetZone 61 1 SetMarkerPath 61 1 74 SetMarkerPath 61 2 62 SetMarkerPath 61 3 58 SetZone 62 1 SetMarkerPath 62 1 15 SetMarkerPath 62 2 34 SetMarkerPath 62 3 76 SetMarkerPath 62 4 61 SetZone 63 1 SetMarkerPath 63 1 59 SetMarkerPath 63 2 35 SetMarkerPath 63 3 74 SetMarkerPath 63 4 58 SetZone 64 2 SetMarkerPath 64 1 72 SetMarkerPath 64 2 66 SetZone 65 2 SetMarkerPath 65 1 66 SetMarkerPath 65 2 16 SetZone 66 2 SetMarkerPath 66 1 64 SetMarkerPath 66 2 72 SetMarkerPath 66 3 65 SetZone 67 2 SetMarkerPath 67 1 70 SetMarkerPath 67 2 64 SetMarkerPathFlags 67 2 j SetZone 68 2 SetMarkerPath 68 1 71 SetMarkerPath 68 2 65 SetMarkerPathFlags 68 2 j SetZone 69 2 SetMarkerPath 69 1 70 SetMarkerPath 69 2 163 SetZone 70 2 SetMarkerPath 70 1 71 SetMarkerPath 70 2 69 SetMarkerPath 70 3 67 SetZone 71 2 SetMarkerPath 71 1 73 SetMarkerPath 71 2 70 SetMarkerPath 71 3 68 SetZone 72 2 SetMarkerPath 72 1 64 SetMarkerPath 72 2 32 SetMarkerPath 72 3 66 SetZone 73 2 SetMarkerPath 73 1 60 SetMarkerPath 73 2 71 SetZone 74 1 SetMarkerPath 74 1 63 SetMarkerPath 74 2 58 SetMarkerPath 74 3 15 SetMarkerPath 74 4 61 SetZone 75 1 SetMarkerPath 75 1 56 SetMarkerPath 75 2 76 SetMarkerPath 75 3 60 SetZone 76 1 SetMarkerPath 76 1 75 SetMarkerPath 76 2 62 SetMarkerPath 76 3 56 SetMarkerPath 76 4 60 SetZone 77 3 SetMarkerPath 77 1 90 SetMarkerPath 77 2 79 SetMarkerPath 77 3 17 SetMarkerPath 77 4 104 SetZone 78 3 SetMarkerPath 78 1 89 SetMarkerPath 78 2 43 SetMarkerPath 78 3 79 SetZone 79 3 SetMarkerPath 79 1 78 SetMarkerPath 79 2 77 SetMarkerPath 79 3 91 SetMarkerPath 79 4 83 SetMarkerPath 79 5 104 SetZone 80 2 SetMarkerPath 80 1 72 SetMarkerPathFlags 80 1 j SetZone 81 2 SetMarkerPath 81 1 66 SetMarkerPathFlags 81 1 j SetZone 82 2 SetMarkerPath 82 1 65 SetMarkerPathFlags 82 1 j SetZone 83 3 SetMarkerPath 83 1 79 SetMarkerPath 83 2 85 SetMarkerPath 83 3 43 SetMarkerPath 83 4 84 SetMarkerPath 83 5 87 SetZone 84 3 SetMarkerPath 84 1 91 SetMarkerPath 84 2 83 SetMarkerPath 84 3 87 SetMarkerPath 84 4 88 SetZone 85 3 SetMarkerPath 85 1 83 SetMarkerPath 85 2 86 SetMarkerPath 85 3 87 SetZone 86 3 SetMarkerPath 86 1 85 SetZone 87 3 SetMarkerPath 87 1 84 SetMarkerPath 87 2 88 SetMarkerPath 87 3 85 SetMarkerPath 87 4 83 SetZone 88 3 SetMarkerPath 88 1 87 SetMarkerPath 88 2 84 SetMarkerPath 88 3 93 SetZone 89 3 SetMarkerPath 89 1 8 SetMarkerPath 89 2 78 SetZone 90 3 SetMarkerPath 90 1 8 SetMarkerPath 90 2 77 SetZone 91 3 SetMarkerPath 91 1 79 SetMarkerPath 91 2 44 SetMarkerPath 91 3 104 SetMarkerPath 91 4 84 SetZone 92 4 SetMarkerPath 92 1 93 SetMarkerPath 92 2 95 SetZone 93 4 SetMarkerPath 93 1 88 SetMarkerPath 93 2 92 SetZone 94 4 SetMarkerPath 94 1 95 SetMarkerPath 94 2 96 SetMarkerPath 94 3 11 SetMarkerPath 94 4 103 SetZone 95 4 SetMarkerPath 95 1 92 SetMarkerPath 95 2 94 SetZone 96 4 SetMarkerPath 96 1 94 SetMarkerPath 96 2 97 SetMarkerPath 96 3 103 SetZone 97 4 SetMarkerPath 97 1 96 SetZone 98 4 SetMarkerPath 98 1 100 SetMarkerPath 98 2 99 SetMarkerPath 98 3 103 SetZone 99 4 SetMarkerPath 99 1 98 SetMarkerPath 99 2 100 SetMarkerPath 99 3 101 SetZone 100 4 SetMarkerPath 100 1 11 SetMarkerPath 100 2 102 SetMarkerPath 100 3 98 SetMarkerPath 100 4 99 SetZone 101 4 SetMarkerPath 101 1 99 SetZone 102 4 SetMarkerPath 102 1 100 SetMarkerPath 102 2 105 SetZone 103 4 SetMarkerPath 103 1 94 SetMarkerPath 103 2 98 SetMarkerPath 103 3 11 SetMarkerPath 103 4 96 SetZone 104 3 SetMarkerPath 104 1 91 SetMarkerPath 104 2 77 SetMarkerPath 104 3 17 SetMarkerPath 104 4 79 SetZone 105 5 SetMarkerPath 105 1 102 SetMarkerPath 105 2 106 SetMarkerPath 105 3 111 SetZone 106 5 SetMarkerPath 106 1 105 SetMarkerPath 106 2 107 SetMarkerPath 106 3 111 SetZone 107 5 SetMarkerPath 107 1 106 SetMarkerPath 107 2 109 SetMarkerPath 107 3 22 SetZone 108 5 SetMarkerPath 108 1 110 SetMarkerPath 108 2 20 SetZone 109 5 SetMarkerPath 109 1 107 SetMarkerPath 109 2 110 SetZone 110 5 SetMarkerPath 110 1 109 SetMarkerPath 110 2 18 SetMarkerPath 110 3 108 SetZone 111 5 SetMarkerPath 111 1 105 SetMarkerPath 111 2 106 SetZone 112 6 SetMarkerPath 112 1 113 SetZone 113 6 SetMarkerPath 113 1 112 SetMarkerPath 113 2 119 SetMarkerPath 113 3 115 SetMarkerPath 113 4 114 SetZone 114 6 SetMarkerPath 114 1 113 SetZone 115 6 SetMarkerPath 115 1 113 SetMarkerPath 115 2 119 SetMarkerPath 115 3 118 SetMarkerPath 115 4 116 SetMarkerPath 115 5 2 SetZone 116 6 SetMarkerPath 116 1 115 SetMarkerPath 116 2 150 SetMarkerPathFlags 116 2 j SetZone 117 6 SetMarkerPath 117 1 118 SetMarkerPath 117 2 151 SetMarkerPathFlags 117 2 j SetZone 118 6 SetMarkerPath 118 1 3 SetMarkerPath 118 2 117 SetMarkerPath 118 3 119 SetMarkerPath 118 4 115 SetMarkerPath 118 5 24 SetZone 119 6 SetMarkerPath 119 1 113 SetMarkerPath 119 2 3 SetMarkerPath 119 3 23 SetMarkerPath 119 4 118 SetMarkerPath 119 5 115 SetZone 120 7 SetMarkerPath 120 1 20 SetMarkerPath 120 2 121 SetZone 121 7 SetMarkerPath 121 1 120 SetMarkerPath 121 2 12 SetMarkerPath 121 3 122 SetMarkerPath 121 4 124 SetZone 122 7 SetMarkerPath 122 1 121 SetMarkerPath 122 2 12 SetMarkerPath 122 3 123 SetMarkerPath 122 4 39 SetZone 123 7 SetMarkerPath 123 1 122 SetMarkerPath 123 2 129 SetMarkerPath 123 3 39 SetMarkerPath 123 4 121 SetMarkerPathFlags 123 4 j SetZone 124 7 SetMarkerPath 124 1 121 SetMarkerPath 124 2 12 SetMarkerPath 124 3 40 SetMarkerPath 124 4 125 SetZone 125 7 SetMarkerPath 125 1 124 SetMarkerPath 125 2 126 SetMarkerPath 125 3 121 SetMarkerPathFlags 125 3 j SetZone 126 7 SetMarkerPath 126 1 125 SetMarkerPath 126 2 127 SetMarkerPath 126 3 120 SetMarkerPathFlags 126 3 j SetZone 127 7 SetMarkerPath 127 1 126 SetMarkerPath 127 2 128 SetMarkerPathFlags 127 2 j SetMarkerPath 127 3 146 SetMarkerPath 127 4 20 SetMarkerPathFlags 127 4 j SetZone 128 7 SetMarkerPath 128 1 129 SetMarkerPath 128 2 130 SetMarkerPath 128 3 127 SetMarkerPathFlags 128 3 j SetMarkerPath 128 4 20 SetMarkerPathFlags 128 4 j SetZone 129 7 SetMarkerPath 129 1 123 SetMarkerPath 129 2 128 SetMarkerPath 129 3 130 SetMarkerPath 129 4 120 SetMarkerPathFlags 129 4 j SetZone 130 8 SetMarkerPath 130 1 129 SetMarkerPath 130 2 128 SetMarkerPath 130 3 131 SetZone 131 8 SetMarkerPath 131 1 130 SetMarkerPath 131 2 132 SetZone 132 8 SetMarkerPath 132 1 131 SetMarkerPath 132 2 133 SetZone 133 8 SetMarkerPath 133 1 132 SetMarkerPath 133 2 134 SetMarkerPath 133 3 55 SetMarkerPath 133 4 37 SetZone 134 8 SetMarkerPath 134 1 133 SetMarkerPath 134 2 135 SetZone 135 8 SetMarkerPath 135 1 134 SetMarkerPath 135 2 136 SetZone 136 8 SetMarkerPath 136 1 135 SetMarkerPath 136 2 57 SetMarkerPath 136 3 59 SetZone 137 9 SetMarkerPath 137 1 13 SetMarkerPath 137 2 29 SetMarkerPath 137 3 5 SetZone 138 9 SetMarkerPath 138 1 140 SetMarkerPath 138 2 13 SetZone 139 9 SetMarkerPath 139 1 140 SetMarkerPath 139 2 142 SetZone 140 9 SetMarkerPath 140 1 139 SetMarkerPath 140 2 138 SetZone 141 9 SetMarkerPath 141 1 13 SetZone 142 10 SetMarkerPath 142 1 139 SetMarkerPath 142 2 143 SetMarkerPath 142 3 150 SetZone 143 10 SetMarkerPath 143 1 19 SetMarkerPath 143 2 144 SetMarkerPath 143 3 26 SetMarkerPath 143 4 142 SetZone 144 10 SetMarkerPath 144 1 143 SetMarkerPath 144 2 145 SetMarkerPath 144 3 157 SetZone 145 10 SetMarkerPath 145 1 144 SetMarkerPath 145 2 146 SetZone 146 10 SetMarkerPath 146 1 145 SetMarkerPath 146 2 127 SetMarkerPath 146 3 158 SetZone 147 11 SetMarkerPath 147 1 149 SetMarkerPath 147 2 155 SetMarkerPath 147 3 148 SetMarkerPath 147 4 154 SetMarkerPath 147 5 152 SetZone 148 11 SetMarkerPath 148 1 153 SetMarkerPath 148 2 150 SetMarkerPath 148 3 147 SetZone 149 11 SetMarkerPath 149 1 153 SetMarkerPath 149 2 147 SetZone 150 11 SetMarkerPath 150 1 148 SetMarkerPath 150 2 142 SetMarkerPath 150 3 151 SetMarkerPath 150 4 152 SetZone 151 11 SetMarkerPath 151 1 154 SetMarkerPath 151 2 150 SetMarkerPath 151 3 152 SetMarkerPath 151 4 157 SetZone 152 11 SetMarkerPath 152 1 19 SetMarkerPath 152 2 147 SetMarkerPath 152 3 150 SetMarkerPath 152 4 151 SetZone 153 11 SetMarkerPath 153 1 149 SetMarkerPath 153 2 148 SetZone 154 11 SetMarkerPath 154 1 156 SetMarkerPath 154 2 151 SetMarkerPath 154 3 147 SetZone 155 11 SetMarkerPath 155 1 147 SetMarkerPath 155 2 156 SetZone 156 11 SetMarkerPath 156 1 155 SetMarkerPath 156 2 154 SetZone 157 10 SetMarkerPath 157 1 151 SetMarkerPath 157 2 19 SetMarkerPath 157 3 144 SetZone 158 12 SetMarkerPath 158 1 146 SetMarkerPath 158 2 159 SetZone 159 12 SetMarkerPath 159 1 158 SetMarkerPath 159 2 160 SetZone 160 12 SetMarkerPath 160 1 159 SetMarkerPath 160 2 161 SetZone 161 12 SetMarkerPath 161 1 160 SetMarkerPath 161 2 162 SetMarkerPath 161 3 14 SetMarkerPath 161 4 30 SetZone 162 12 SetMarkerPath 162 1 161 SetMarkerPath 162 2 163 SetZone 163 12 SetMarkerPath 163 1 162 SetMarkerPath 163 2 69 SetZone 164 12 SetMarkerPath 164 1 14 SetMarkerPath 164 2 156 SetMarkerPathFlags 164 2 j QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ultrav.bot000066400000000000000000000256001475442401000262660ustar00rootroot00000000000000CreateMarker -224 547 216 CreateMarker -125 651 216 CreateMarker 64 667 248 CreateMarker 222 647 280 CreateMarker 384 570 312 CreateMarker 298 499 328 CreateMarker 202 403 344 CreateMarker 274 584 312 CreateMarker 509 570 294 CreateMarker 638 558 248 CreateMarker 890 545 264 CreateMarker 168 306 344 CreateMarker 152 175 344 CreateMarker 144 -67 344 CreateMarker 174 -219 344 CreateMarker 207 -286 344 CreateMarker 289 -353 344 CreateMarker 413 -395 344 CreateMarker 455 -450 344 CreateMarker 481 -531 312 CreateMarker 705 -666 312 CreateMarker 513 -697 312 CreateMarker 510 -865 312 CreateMarker 696 -859 312 CreateMarker 816 -770 328 CreateMarker -91 -542 280 CreateMarker -224 -433 280 CreateMarker -253 -290 280 CreateMarker 41 -545 280 CreateMarker 249 -571 296 CreateMarker 254 -664 296 CreateMarker 411 -753 312 CreateMarker -149 -232 280 CreateMarker 27 -240 168 CreateMarker 5 -145 24 CreateMarker 8 -20 24 CreateMarker -4 178 24 CreateMarker -25 309 24 CreateMarker 230 163 24 CreateMarker 225 -35 24 CreateMarker 4 -261 24 CreateMarker 15 -385 24 CreateMarker 90 -447 24 CreateMarker 228 -509 24 CreateMarker 308 -596 24 CreateMarker 372 -970 -40 CreateMarker 246 -966 -40 CreateMarker -173 325 216 CreateMarker -230 451 216 CreateMarker -258 9 24 CreateMarker -161 124 24 CreateMarker -301 210 216 SetZone 1 3 SetMarkerPath 1 0 93 SetZone 2 6 SetMarkerPath 2 0 70 SetMarkerPath 2 1 4 SetZone 3 1 SetMarkerPath 3 0 56 SetMarkerPath 3 1 5 SetZone 4 12 SetMarkerPath 4 0 14 SetMarkerPath 4 1 91 SetZone 5 10 SetMarkerPath 5 0 7 SetMarkerPath 5 1 84 SetMarkerPath 5 2 83 SetGoal 6 16 SetZone 6 4 SetMarkerPath 6 0 44 SetMarkerPath 6 1 13 SetMarkerPath 6 2 59 SetMarkerPath 6 3 58 SetMarkerPath 6 4 30 SetMarkerPathFlags 6 4 j SetMarkerPath 6 5 95 SetMarkerPathFlags 6 5 j SetGoal 7 5 SetZone 7 10 SetMarkerPath 7 0 16 SetMarkerPath 7 1 84 SetMarkerPath 7 2 5 SetGoal 8 23 SetZone 8 13 SetMarkerPath 8 0 70 SetMarkerPath 8 1 45 SetMarkerPath 8 2 77 SetMarkerPath 8 3 39 SetGoal 9 24 SetZone 9 1 SetMarkerPath 9 0 55 SetMarkerPath 9 1 10 SetMarkerPath 9 2 20 SetMarkerPath 9 3 36 SetMarkerPath 9 4 56 SetMarkerPath 9 5 11 SetGoal 10 22 SetZone 10 1 SetMarkerPath 10 0 55 SetMarkerPath 10 1 9 SetMarkerPath 10 2 11 SetGoal 11 21 SetZone 11 1 SetMarkerPath 11 0 10 SetMarkerPath 11 1 56 SetMarkerPath 11 2 9 SetGoal 12 18 SetZone 12 3 SetMarkerPath 12 0 32 SetMarkerPath 12 1 93 SetMarkerPath 12 2 94 SetMarkerPath 12 3 81 SetMarkerPathFlags 12 3 j SetMarkerPath 12 4 82 SetMarkerPathFlags 12 4 j SetMarkerPath 12 5 97 SetGoal 13 17 SetZone 13 4 SetMarkerPath 13 0 44 SetMarkerPath 13 1 58 SetMarkerPath 13 2 6 SetMarkerPath 13 3 12 SetMarkerPathFlags 13 3 j SetMarkerPath 13 4 95 SetMarkerPathFlags 13 4 j SetZone 14 12 SetMarkerPath 14 0 37 SetMarkerPath 14 1 91 SetMarkerPath 14 2 92 SetMarkerPath 14 3 34 SetMarkerPath 14 4 4 SetGoal 15 10 SetZone 15 8 SetMarkerPath 15 0 38 SetGoal 16 5 SetZone 16 10 SetMarkerPath 16 0 85 SetMarkerPath 16 1 7 SetGoal 17 11 SetZone 17 7 SetMarkerPath 17 0 31 SetMarkerPath 17 1 74 SetZone 18 6 SetMarkerPath 18 0 77 SetMarkerPath 18 1 68 SetMarkerPath 18 2 39 SetZone 19 4 SetMarkerPath 19 0 44 SetMarkerPath 19 1 59 SetMarkerPath 19 2 58 SetZone 20 1 SetMarkerPath 20 0 55 SetMarkerPath 20 1 9 SetMarkerPath 20 2 56 SetMarkerPath 20 3 29 SetZone 21 2 SetMarkerPath 21 0 46 SetMarkerPath 21 1 43 SetMarkerPath 21 2 47 SetZone 22 7 SetMarkerPath 22 0 72 SetMarkerPath 22 1 71 SetZone 23 14 SetMarkerPath 23 0 26 SetZone 24 10 SetZone 25 10 SetZone 26 13 SetMarkerPath 26 0 8 SetGoal 28 1 SetZone 28 12 SetMarkerPath 28 0 37 SetMarkerPath 28 1 91 SetGoal 29 20 SetZone 29 1 SetMarkerPath 29 0 36 SetMarkerPath 29 1 20 SetGoal 30 8 SetZone 30 8 SetMarkerPath 30 0 78 SetMarkerPath 30 1 73 SetMarkerPath 30 2 38 SetMarkerPath 30 3 81 SetMarkerPathFlags 30 3 j SetMarkerPath 30 4 82 SetMarkerPathFlags 30 4 j SetMarkerPath 30 5 12 SetMarkerPathFlags 30 5 j SetMarkerPath 30 6 6 SetMarkerPathFlags 30 6 r SetRocketJumpPathFields 30 6 40.0 216.0 0 SetGoal 31 11 SetZone 31 7 SetMarkerPath 31 0 75 SetMarkerPath 31 1 17 SetGoal 32 6 SetZone 32 3 SetMarkerPath 32 0 33 SetMarkerPath 32 1 12 SetMarkerPath 32 2 93 SetMarkerPath 32 3 82 SetMarkerPathFlags 32 3 j SetMarkerPath 32 4 81 SetMarkerPathFlags 32 4 j SetMarkerPath 32 5 97 SetGoal 33 7 SetZone 33 3 SetMarkerPath 33 0 32 SetMarkerPath 33 1 81 SetMarkerPathFlags 33 1 j SetMarkerPath 33 2 82 SetMarkerPathFlags 33 2 j SetMarkerPath 33 3 97 SetZone 34 12 SetMarkerPath 34 0 35 SetMarkerPath 34 1 14 SetZone 35 4 SetMarkerPath 35 0 58 SetMarkerPath 35 1 57 SetGoal 36 20 SetZone 36 1 SetMarkerPath 36 0 9 SetMarkerPath 36 1 56 SetMarkerPath 36 2 29 SetGoal 37 4 SetZone 37 12 SetMarkerPath 37 0 90 SetMarkerPath 37 1 40 SetMarkerPath 37 2 92 SetMarkerPath 37 3 14 SetMarkerPath 37 4 28 SetMarkerPath 37 5 91 SetGoal 38 9 SetZone 38 8 SetMarkerPath 38 0 30 SetMarkerPath 38 1 15 SetMarkerPath 38 2 73 SetGoal 39 14 SetZone 39 6 SetMarkerPath 39 0 18 SetMarkerPath 39 1 68 SetMarkerPath 39 2 69 SetGoal 40 2 SetZone 40 12 SetMarkerPath 40 0 37 SetMarkerPath 40 1 41 SetMarkerPath 40 2 92 SetGoal 41 3 SetZone 41 12 SetMarkerPath 41 0 92 SetMarkerPath 41 1 40 SetGoal 42 13 SetZone 42 6 SetMarkerPath 42 0 66 SetMarkerPath 42 1 45 SetGoal 43 19 SetZone 43 2 SetMarkerPath 43 0 21 SetMarkerPath 43 1 47 SetMarkerPath 43 2 48 SetGoal 44 15 SetZone 44 4 SetMarkerPath 44 0 13 SetMarkerPath 44 1 6 SetMarkerPath 44 2 59 SetMarkerPath 44 3 58 SetMarkerPath 44 4 19 SetGoal 45 12 SetZone 45 6 SetMarkerPath 45 0 65 SetMarkerPath 45 1 67 SetMarkerPath 45 2 42 SetMarkerPath 45 3 66 SetZone 46 2 SetMarkerPath 46 0 94 SetMarkerPath 46 1 47 SetMarkerPath 46 2 21 SetZone 47 2 SetMarkerPath 47 0 46 SetMarkerPath 47 1 21 SetMarkerPath 47 2 48 SetMarkerPath 47 3 43 SetZone 48 2 SetMarkerPath 48 0 47 SetMarkerPath 48 1 43 SetMarkerPath 48 2 49 SetZone 49 2 SetMarkerPath 49 0 48 SetMarkerPath 49 1 50 SetMarkerPath 49 2 53 SetZone 50 2 SetMarkerPath 50 0 49 SetMarkerPath 50 1 53 SetMarkerPath 50 2 51 SetMarkerPath 50 3 54 SetZone 51 2 SetMarkerPath 51 0 53 SetMarkerPath 51 1 50 SetMarkerPath 51 2 52 SetZone 52 2 SetMarkerPath 52 0 51 SetMarkerPath 52 1 57 SetZone 53 2 SetMarkerPath 53 0 49 SetMarkerPath 53 1 50 SetMarkerPath 53 2 51 SetZone 54 1 SetMarkerPath 54 0 50 SetMarkerPath 54 1 55 SetZone 55 1 SetMarkerPath 55 0 54 SetMarkerPath 55 1 20 SetMarkerPath 55 2 9 SetMarkerPath 55 3 10 SetZone 56 1 SetMarkerPath 56 0 9 SetMarkerPath 56 1 11 SetMarkerPath 56 2 20 SetMarkerPath 56 3 36 SetMarkerPath 56 4 3 SetZone 57 4 SetMarkerPath 57 0 58 SetMarkerPath 57 1 35 SetMarkerPath 57 2 52 SetZone 58 4 SetMarkerPath 58 0 44 SetMarkerPath 58 1 19 SetMarkerPath 58 2 13 SetMarkerPath 58 3 57 SetMarkerPath 58 4 35 SetMarkerPath 58 5 6 SetZone 59 4 SetMarkerPath 59 0 44 SetMarkerPath 59 1 19 SetMarkerPath 59 2 6 SetMarkerPath 59 3 60 SetZone 60 5 SetMarkerPath 60 0 59 SetMarkerPath 60 1 61 SetZone 61 5 SetMarkerPath 61 0 60 SetMarkerPath 61 1 62 SetZone 62 5 SetMarkerPath 62 0 61 SetMarkerPath 62 1 63 SetZone 63 5 SetMarkerPath 63 0 62 SetMarkerPath 63 1 64 SetZone 64 5 SetMarkerPath 64 0 63 SetMarkerPath 64 1 65 SetZone 65 6 SetMarkerPath 65 0 64 SetMarkerPath 65 1 75 SetMarkerPath 65 2 66 SetMarkerPath 65 3 67 SetMarkerPath 65 4 45 SetZone 66 6 SetMarkerPath 66 0 67 SetMarkerPath 66 1 69 SetMarkerPath 66 2 70 SetMarkerPath 66 3 42 SetMarkerPath 66 4 45 SetMarkerPath 66 5 65 SetZone 67 6 SetMarkerPath 67 0 65 SetMarkerPath 67 1 68 SetMarkerPath 67 2 66 SetMarkerPath 67 3 75 SetMarkerPath 67 4 76 SetMarkerPath 67 5 77 SetZone 68 6 SetMarkerPath 68 0 69 SetMarkerPath 68 1 67 SetMarkerPath 68 2 77 SetMarkerPath 68 3 18 SetMarkerPath 68 4 39 SetZone 69 6 SetMarkerPath 69 0 39 SetMarkerPath 69 1 66 SetMarkerPath 69 2 70 SetMarkerPath 69 3 68 SetZone 70 6 SetMarkerPath 70 0 69 SetMarkerPath 70 1 66 SetMarkerPath 70 2 2 SetZone 71 7 SetMarkerPath 71 0 74 SetMarkerPath 71 1 72 SetMarkerPath 71 2 22 SetZone 72 8 SetMarkerPath 72 0 71 SetMarkerPath 72 1 22 SetMarkerPath 72 2 78 SetMarkerPath 72 3 73 SetZone 73 8 SetMarkerPath 73 0 72 SetMarkerPath 73 1 78 SetMarkerPath 73 2 30 SetMarkerPath 73 3 38 SetMarkerPath 73 4 81 SetMarkerPathFlags 73 4 j SetZone 74 7 SetMarkerPath 74 0 76 SetMarkerPath 74 1 75 SetMarkerPath 74 2 17 SetMarkerPath 74 3 71 SetZone 75 7 SetMarkerPath 75 0 65 SetMarkerPath 75 1 67 SetMarkerPath 75 2 76 SetMarkerPath 75 3 31 SetMarkerPath 75 4 74 SetMarkerPath 75 5 77 SetZone 76 7 SetMarkerPath 76 1 74 SetMarkerPath 76 2 75 SetMarkerPath 76 3 67 SetMarkerPath 76 4 77 SetZone 77 6 SetMarkerPath 77 0 76 SetMarkerPath 77 1 67 SetMarkerPath 77 2 68 SetMarkerPath 77 3 18 SetMarkerPath 77 4 75 SetZone 78 8 SetMarkerPath 78 0 72 SetMarkerPath 78 1 73 SetMarkerPath 78 2 30 SetMarkerPath 78 3 79 SetMarkerPathFlags 78 3 j SetZone 79 9 SetMarkerPath 79 0 85 SetMarkerPathFlags 79 0 j SetMarkerPath 79 1 80 SetMarkerPathFlags 79 1 j SetZone 80 10 SetMarkerPath 80 0 86 SetMarkerPath 80 1 85 SetMarkerPath 80 2 81 SetMarkerPath 80 3 95 SetZone 81 10 SetMarkerPath 81 0 80 SetMarkerPath 81 1 85 SetMarkerPath 81 2 82 SetMarkerPath 81 3 95 SetMarkerPath 81 4 96 SetZone 82 10 SetMarkerPath 82 0 84 SetMarkerPath 82 1 83 SetMarkerPath 82 2 80 SetMarkerPath 82 3 81 SetMarkerPath 82 4 95 SetMarkerPath 82 5 96 SetMarkerPath 82 6 93 SetMarkerPathFlags 82 6 r SetRocketJumpPathFields 82 6 62.0 311.0 0 SetZone 83 10 SetMarkerPath 83 0 5 SetMarkerPath 83 1 84 SetMarkerPath 83 2 82 SetMarkerPath 83 3 1 SetZone 84 10 SetMarkerPath 84 0 85 SetMarkerPath 84 1 7 SetMarkerPath 84 2 5 SetMarkerPath 84 3 82 SetMarkerPath 84 4 83 SetZone 85 10 SetMarkerPath 85 0 86 SetMarkerPath 85 1 80 SetMarkerPath 85 2 81 SetMarkerPath 85 3 16 SetMarkerPath 85 4 84 SetZone 86 11 SetMarkerPath 86 0 85 SetMarkerPath 86 1 80 SetMarkerPath 86 2 87 SetZone 87 11 SetMarkerPath 87 0 86 SetMarkerPath 87 1 88 SetZone 88 11 SetMarkerPath 88 0 87 SetMarkerPath 88 1 89 SetZone 89 11 SetMarkerPath 89 0 88 SetMarkerPath 89 1 90 SetZone 90 11 SetMarkerPath 90 0 89 SetMarkerPath 90 1 37 SetZone 91 12 SetMarkerPath 91 0 37 SetMarkerPath 91 1 28 SetMarkerPath 91 2 14 SetMarkerPath 91 3 92 SetMarkerPath 91 4 4 SetZone 92 12 SetMarkerPath 92 0 37 SetMarkerPath 92 1 91 SetMarkerPath 92 2 14 SetMarkerPath 92 3 41 SetMarkerPath 92 4 40 SetZone 93 3 SetMarkerPath 93 0 12 SetMarkerPath 93 1 32 SetMarkerPath 93 2 94 SetMarkerPath 93 3 82 SetMarkerPathFlags 93 3 j SetMarkerPath 93 4 81 SetMarkerPathFlags 93 4 j SetMarkerPath 93 5 97 SetZone 94 3 SetMarkerPath 94 0 93 SetMarkerPath 94 1 12 SetMarkerPath 94 2 46 SetZone 95 10 SetMarkerPath 95 0 82 SetMarkerPath 95 1 80 SetMarkerPath 95 2 81 SetMarkerPath 95 3 96 SetMarkerPath 95 4 97 SetMarkerPathFlags 95 4 r SetRocketJumpPathFields 95 4 71.0 281.0 0 SetZone 96 10 SetMarkerPath 96 0 82 SetMarkerPath 96 1 81 SetMarkerPath 96 2 95 SetMarkerPath 96 3 97 SetMarkerPathFlags 96 3 r SetRocketJumpPathFields 96 3 74.0 313.0 0 SetZone 97 3 SetMarkerPath 97 0 93 SetMarkerPath 97 1 12 SetMarkerPath 97 2 32 SetMarkerPath 97 3 33 SetMarkerPath 97 4 30 SetMarkerPathFlags 97 4 r SetRocketJumpPathFields 97 4 37.0 94.0 0 SetMarkerPath 97 5 6 SetMarkerPathFlags 97 5 r SetRocketJumpPathFields 97 5 51.0 158.0 0 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm1.bot000066400000000000000000000255371475442401000261770ustar00rootroot00000000000000CreateMarker -592 -272 88 CreateMarker -436 -272 88 CreateMarker -325 -424 88 CreateMarker -224 -585 88 CreateMarker 0 -575 168 CreateMarker 31 -364 168 CreateMarker -144 -394 88 CreateMarker -11 -1 24 CreateMarker -9 361 168 CreateMarker 258 309 168 CreateMarker 261 722 104 CreateMarker 558 726 104 CreateMarker 764 720 40 CreateMarker 778 426 -40 CreateMarker 641 768 -40 CreateMarker 444 365 8 CreateMarker 219 363 -24 CreateMarker 421 556 -40 CreateMarker 784 157 168 CreateMarker 759 360 168 CreateMarker 815 377 168 CreateMarker 578 463 -24 CreateMarker 438 197 24 CreateMarker -689 -286 232 CreateMarker -704 -500 232 CreateMarker -379 -510 232 CreateMarker -514 -508 232 CreateMarker 105 2 24 CreateMarker -170 2 24 CreateMarker 224 -6 24 CreateMarker -332 -111 24 CreateMarker -298 -312 56 CreateMarker -157 -303 88 CreateMarker -11 -444 88 CreateMarker 314 545 -40 CreateMarker 395 695 -40 CreateMarker 625 599 -40 CreateMarker 745 573 8 CreateMarker 449 721 104 CreateMarker 460 317 168 CreateMarker -150 300 168 CreateMarker -494 348 215 CreateMarker -693 -116 232 CreateMarker -316 -524 88 CreateMarker 219 548 -40 CreateMarker -445 -444 88 CreateMarker -231 -489 88 CreateMarker -590 288 232 CreateMarker -434 -504 232 CreateMarker -387 -410 232 CreateMarker 176 330 168 CreateMarker 235 493 168 CreateMarker 757 293 168 CreateMarker 241 602 136 CreateMarker 241 403 168 CreateMarker 291 361 -8 CreateMarker 342 457 -24 CreateMarker 253 633 -40 CreateMarker 488 628 -40 CreateMarker 698 456 -40 CreateMarker 369 383 168 CreateMarker 368 737 104 CreateMarker 619 342 -8 CreateMarker 443 461 -24 CreateMarker 410 64 24 CreateMarker 361 -48 24 CreateMarker -251 22 24 CreateMarker -324 -201 24 SetZone 1 12 SetMarkerPath 1 0 60 SetGoal 2 9 SetZone 2 10 SetMarkerPath 2 0 85 SetMarkerPath 2 1 3 SetGoal 3 14 SetZone 3 10 SetMarkerPath 3 0 2 SetMarkerPath 3 1 68 SetMarkerPath 3 2 67 SetMarkerPath 3 3 38 SetGoal 4 5 SetZone 4 10 SetMarkerPath 4 0 84 SetMarkerPath 4 1 16 SetMarkerPath 4 2 61 SetMarkerPath 4 3 39 SetMarkerPath 4 4 82 SetMarkerPath 4 5 38 SetGoal 5 3 SetZone 5 15 SetMarkerPath 5 0 81 SetMarkerPath 5 1 79 SetMarkerPath 5 2 11 SetMarkerPath 5 3 39 SetGoal 6 4 SetZone 6 3 SetMarkerPath 6 0 63 SetMarkerPath 6 1 43 SetMarkerPath 6 2 64 SetGoal 7 7 SetZone 7 14 SetMarkerPath 7 0 41 SetMarkerPath 7 1 23 SetMarkerPath 7 2 10 SetMarkerPath 7 3 43 SetGoal 8 13 SetZone 8 12 SetMarkerPath 8 0 83 SetMarkerPath 8 1 12 SetMarkerPath 8 2 22 SetGoal 9 5 SetZone 9 13 SetMarkerPath 9 0 76 SetMarkerPath 9 1 77 SetGoal 10 2 SetZone 10 14 SetMarkerPath 10 0 7 SetMarkerPath 10 1 18 SetMarkerPath 10 2 23 SetMarkerPath 10 3 43 SetGoal 11 3 SetZone 11 15 SetMarkerPath 11 0 81 SetMarkerPath 11 1 5 SetGoal 12 12 SetZone 12 13 SetMarkerPath 12 0 83 SetMarkerPath 12 1 13 SetMarkerPath 12 2 8 SetGoal 13 3 SetZone 13 13 SetMarkerPath 13 0 14 SetMarkerPath 13 1 12 SetGoal 14 3 SetZone 14 13 SetMarkerPath 14 0 77 SetMarkerPath 14 1 83 SetMarkerPath 14 2 13 SetGoal 15 5 SetZone 15 15 SetMarkerPath 15 0 68 SetMarkerPath 15 1 42 SetGoal 16 12 SetZone 16 10 SetMarkerPath 16 0 84 SetMarkerPath 16 1 4 SetMarkerPath 16 2 61 SetZone 17 16 SetMarkerPath 17 0 25 SetMarkerPath 17 1 24 SetMarkerPath 17 2 36 SetZone 18 14 SetMarkerPath 18 0 10 SetMarkerPath 18 1 44 SetZone 19 4 SetMarkerPath 19 0 58 SetMarkerPath 19 1 101 SetMarkerPath 19 2 100 SetZone 20 3 SetMarkerPath 20 0 102 SetMarkerPath 20 1 66 SetGoal 21 15 SetZone 21 3 SetMarkerPath 21 0 63 SetMarkerPath 21 1 43 SetMarkerPath 21 2 64 SetZone 22 12 SetMarkerPath 22 0 8 SetMarkerPath 22 1 78 SetGoal 23 6 SetZone 23 14 SetMarkerPath 23 0 7 SetMarkerPath 23 1 10 SetMarkerPath 23 2 43 SetGoal 24 1 SetZone 24 16 SetMarkerPath 24 0 25 SetMarkerPath 24 1 17 SetGoal 25 2 SetZone 25 16 SetMarkerPath 25 0 24 SetMarkerPath 25 1 17 SetZone 26 9 SetMarkerPath 26 0 54 SetZone 27 5 SetMarkerPath 27 0 71 SetMarkerPath 27 1 1 SetGoal 28 8 SetZone 28 1 SetMarkerPath 28 0 33 SetGoal 29 11 SetZone 29 9 SetMarkerPath 29 0 32 SetMarkerPath 29 1 88 SetMarkerPath 29 2 55 SetMarkerPath 29 3 57 SetGoal 30 3 SetZone 30 6 SetMarkerPath 30 0 49 SetMarkerPath 30 1 31 SetGoal 31 1 SetZone 31 6 SetMarkerPath 31 0 49 SetMarkerPath 31 1 30 SetMarkerPath 31 2 98 SetMarkerPath 31 3 95 SetGoal 32 10 SetZone 32 9 SetMarkerPath 32 0 75 SetMarkerPath 32 1 29 SetMarkerPath 32 2 57 SetGoal 33 9 SetZone 33 1 SetMarkerPath 33 0 56 SetMarkerPath 33 1 28 SetMarkerPath 33 2 48 SetMarkerPath 33 3 47 SetMarkerPath 33 4 95 SetGoal 34 5 SetZone 34 5 SetMarkerPath 34 0 80 SetMarkerPath 34 1 93 SetMarkerPath 34 2 35 SetGoal 35 22 SetZone 35 5 SetMarkerPath 35 0 34 SetZone 36 16 SetMarkerPath 36 0 17 SetMarkerPath 36 1 37 SetZone 37 15 SetMarkerPath 37 0 36 SetMarkerPath 37 1 81 SetMarkerPath 37 2 67 SetMarkerPath 37 3 38 SetZone 38 15 SetMarkerPath 38 0 37 SetMarkerPath 38 1 81 SetMarkerPath 38 2 67 SetMarkerPath 38 3 79 SetMarkerPath 38 4 82 SetMarkerPath 38 5 42 SetZone 39 15 SetMarkerPath 39 0 79 SetMarkerPath 39 1 5 SetMarkerPath 39 2 82 SetMarkerPath 39 3 40 SetZone 40 15 SetMarkerPath 40 0 39 SetMarkerPath 40 1 41 SetZone 41 15 SetMarkerPath 41 0 40 SetMarkerPath 41 1 7 SetMarkerPath 41 2 42 SetZone 42 15 SetMarkerPath 42 0 67 SetMarkerPath 42 1 38 SetMarkerPath 42 2 68 SetMarkerPath 42 3 69 SetMarkerPath 42 4 82 SetMarkerPath 42 5 15 SetZone 43 3 SetMarkerPath 43 0 6 SetMarkerPath 43 1 63 SetMarkerPath 43 2 21 SetMarkerPath 43 3 64 SetZone 44 13 SetMarkerPath 44 0 18 SetMarkerPath 44 1 76 SetMarkerPath 44 2 45 SetMarkerPath 44 3 86 SetZone 45 9 SetMarkerPath 45 0 44 SetMarkerPath 45 1 86 SetMarkerPath 45 2 75 SetMarkerPath 45 3 96 SetMarkerPath 45 4 90 SetZone 46 7 SetMarkerPath 46 0 89 SetMarkerPath 46 1 97 SetMarkerPath 46 2 53 SetZone 47 7 SetMarkerPath 47 0 74 SetMarkerPath 47 1 48 SetMarkerPath 47 2 57 SetMarkerPath 47 3 53 SetZone 48 6 SetMarkerPath 48 0 47 SetMarkerPath 48 1 73 SetZone 49 6 SetMarkerPath 49 0 73 SetMarkerPath 49 1 30 SetMarkerPath 49 2 95 SetMarkerPath 49 3 31 SetZone 50 5 SetMarkerPath 50 0 72 SetZone 51 5 SetMarkerPath 51 0 57 SetMarkerPath 51 1 58 SetMarkerPath 51 2 91 SetMarkerPath 51 3 92 SetMarkerPath 51 4 99 SetZone 52 5 SetMarkerPath 52 0 91 SetMarkerPath 52 1 80 SetZone 53 5 SetMarkerPath 53 0 57 SetMarkerPath 53 1 99 SetMarkerPath 53 2 92 SetMarkerPath 53 3 94 SetMarkerPath 53 4 71 SetMarkerPath 53 5 70 SetZone 54 9 SetMarkerPath 54 0 88 SetMarkerPath 54 1 26 SetZone 55 9 SetMarkerPath 55 0 29 SetMarkerPath 55 1 56 SetMarkerPath 55 2 88 SetZone 56 9 SetMarkerPath 56 0 55 SetMarkerPath 56 1 33 SetMarkerPath 56 2 88 SetZone 57 5 SetMarkerPath 57 0 95 SetMarkerPath 57 1 98 SetMarkerPath 57 2 51 SetMarkerPath 57 3 72 SetMarkerPath 57 4 94 SetMarkerPath 57 5 53 SetZone 58 4 SetMarkerPath 58 0 51 SetMarkerPath 58 1 100 SetMarkerPath 58 2 19 SetZone 59 12 SetMarkerPath 59 0 78 SetMarkerPath 59 1 60 SetZone 60 12 SetMarkerPath 60 0 59 SetMarkerPath 60 1 1 SetMarkerPath 60 2 62 SetZone 61 10 SetMarkerPath 61 0 85 SetMarkerPath 61 1 84 SetMarkerPath 61 2 16 SetMarkerPath 61 3 4 SetMarkerPath 61 4 39 SetMarkerPath 61 5 82 SetZone 62 11 SetMarkerPath 62 0 60 SetMarkerPath 62 1 84 SetZone 63 3 SetMarkerPath 63 0 65 SetMarkerPath 63 1 6 SetMarkerPath 63 2 43 SetMarkerPath 63 3 21 SetZone 64 3 SetMarkerPath 64 0 21 SetMarkerPath 64 1 43 SetMarkerPath 64 2 6 SetMarkerPath 64 3 102 SetZone 65 3 SetMarkerPath 65 0 101 SetMarkerPath 65 1 63 SetZone 66 3 SetMarkerPath 66 0 20 SetMarkerPath 66 1 103 SetZone 67 15 SetMarkerPath 67 0 37 SetMarkerPath 67 1 66 SetMarkerPath 67 2 38 SetMarkerPath 67 3 81 SetMarkerPath 67 4 42 SetMarkerPath 67 5 68 SetZone 68 15 SetMarkerPath 68 0 67 SetMarkerPath 68 1 42 SetMarkerPath 68 2 38 SetMarkerPath 68 3 15 SetMarkerPath 68 4 82 SetMarkerPath 68 5 69 SetZone 69 15 SetMarkerPath 69 0 68 SetMarkerPath 69 1 42 SetZone 70 5 SetMarkerPath 70 0 92 SetMarkerPath 70 1 80 SetMarkerPath 70 2 93 SetMarkerPath 70 3 53 SetMarkerPath 70 4 71 SetZone 71 5 SetMarkerPath 71 0 93 SetMarkerPath 71 1 53 SetMarkerPath 71 2 94 SetMarkerPath 71 3 27 SetMarkerPath 71 4 70 SetZone 72 5 SetMarkerPath 72 0 95 SetMarkerPath 72 1 57 SetMarkerPath 72 2 94 SetMarkerPath 72 3 50 SetZone 73 6 SetMarkerPath 73 0 48 SetMarkerPath 73 1 49 SetMarkerPath 73 2 95 SetZone 74 7 SetMarkerPath 74 0 97 SetMarkerPath 74 1 47 SetMarkerPath 74 2 53 SetMarkerPath 74 3 72 SetZone 75 9 SetMarkerPath 75 0 45 SetMarkerPath 75 1 32 SetMarkerPath 75 2 96 SetMarkerPath 75 3 57 SetZone 76 13 SetMarkerPath 76 0 44 SetMarkerPath 76 1 9 SetZone 77 13 SetMarkerPath 77 0 9 SetMarkerPath 77 1 14 SetMarkerPath 77 2 83 SetZone 78 12 SetMarkerPath 78 0 22 SetMarkerPath 78 1 59 SetZone 79 15 SetMarkerPath 79 0 81 SetMarkerPath 79 1 38 SetMarkerPath 79 2 5 SetMarkerPath 79 3 39 SetMarkerPath 79 4 82 SetZone 80 5 SetMarkerPath 80 0 52 SetMarkerPath 80 1 70 SetMarkerPath 80 2 93 SetMarkerPath 80 3 34 SetZone 81 15 SetMarkerPath 81 0 37 SetMarkerPath 81 1 11 SetMarkerPath 81 2 5 SetMarkerPath 81 3 38 SetMarkerPath 81 4 79 SetMarkerPath 81 5 67 SetZone 82 15 SetMarkerPath 82 0 38 SetMarkerPath 82 1 79 SetMarkerPath 82 2 39 SetMarkerPath 82 3 68 SetMarkerPath 82 4 42 SetZone 83 13 SetMarkerPath 83 0 77 SetMarkerPath 83 1 14 SetMarkerPath 83 2 8 SetMarkerPath 83 3 12 SetZone 84 10 SetMarkerPath 84 0 62 SetMarkerPath 84 1 61 SetMarkerPath 84 2 85 SetMarkerPath 84 3 16 SetMarkerPath 84 4 4 SetZone 85 10 SetMarkerPath 85 0 84 SetMarkerPath 85 1 61 SetMarkerPath 85 2 2 SetMarkerPath 85 3 82 SetMarkerPath 85 4 67 SetMarkerPath 85 5 42 SetZone 86 9 SetMarkerPath 86 0 44 SetMarkerPath 86 1 45 SetMarkerPath 86 2 90 SetZone 87 8 SetMarkerPath 87 0 90 SetMarkerPath 87 1 89 SetMarkerPath 87 2 99 SetZone 88 9 SetMarkerPath 88 0 29 SetMarkerPath 88 1 55 SetMarkerPath 88 2 56 SetMarkerPath 88 3 54 SetZone 89 8 SetMarkerPath 89 0 87 SetMarkerPath 89 1 46 SetMarkerPath 89 2 53 SetZone 90 8 SetMarkerPath 90 0 86 SetMarkerPath 90 1 45 SetMarkerPath 90 2 96 SetMarkerPath 90 3 87 SetMarkerPath 90 4 53 SetZone 91 5 SetMarkerPath 91 0 51 SetMarkerPath 91 1 92 SetMarkerPath 91 2 52 SetZone 92 5 SetMarkerPath 92 0 51 SetMarkerPath 92 1 99 SetMarkerPath 92 2 91 SetMarkerPath 92 3 70 SetMarkerPath 92 4 53 SetZone 93 5 SetMarkerPath 93 0 80 SetMarkerPath 93 1 71 SetMarkerPath 93 2 70 SetMarkerPath 93 3 34 SetZone 94 5 SetMarkerPath 94 0 57 SetMarkerPath 94 1 53 SetMarkerPath 94 2 71 SetMarkerPath 94 3 72 SetZone 95 5 SetMarkerPath 95 0 73 SetMarkerPath 95 1 49 SetMarkerPath 95 2 98 SetMarkerPath 95 3 31 SetMarkerPath 95 4 57 SetMarkerPath 95 5 72 SetZone 96 9 SetMarkerPath 96 0 45 SetMarkerPath 96 1 75 SetMarkerPath 96 2 90 SetMarkerPath 96 3 99 SetZone 97 7 SetMarkerPath 97 0 46 SetMarkerPath 97 1 74 SetMarkerPath 97 2 53 SetZone 98 5 SetMarkerPath 98 0 31 SetMarkerPath 98 1 95 SetMarkerPath 98 2 57 SetZone 99 5 SetMarkerPath 99 0 51 SetMarkerPath 99 1 57 SetMarkerPath 99 2 53 SetMarkerPath 99 3 92 SetZone 100 4 SetMarkerPath 100 0 58 SetMarkerPath 100 1 19 SetMarkerPath 100 2 101 SetZone 101 3 SetMarkerPath 101 0 19 SetMarkerPath 101 1 100 SetMarkerPath 101 2 65 SetZone 102 3 SetMarkerPath 102 0 64 SetMarkerPath 102 1 20 SetZone 103 3 SetMarkerPath 103 0 66 SetMarkerPath 103 1 67 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm2.bot000066400000000000000000000175151475442401000261750ustar00rootroot00000000000000CreateMarker -695 -23 88 CreateMarker -578 76 88 CreateMarker -578 -145 152 CreateMarker -327 297 88 CreateMarker -292 133 126 CreateMarker -11 128 216 CreateMarker -446 427 216 CreateMarker -723 412 216 CreateMarker -1002 403 216 CreateMarker -1024 645 216 CreateMarker -1159 640 224 CreateMarker -762 678 152 CreateMarker 281 187 216 CreateMarker -292 -6 88 CreateMarker 258 846 376 CreateMarker 297 527 376 CreateMarker 290 341 289 CreateMarker -4 840 376 CreateMarker -317 1046 376 CreateMarker -514 1041 334 CreateMarker -785 937 280 CreateMarker -614 861 247 CreateMarker -439 853 170 CreateMarker -250 906 152 CreateMarker -276 1042 152 CreateMarker -188 806 152 CreateMarker -380 700 152 CreateMarker -708 -212 184 CreateMarker -485 -346 152 CreateMarker -670 -388 104 CreateMarker -834 -391 24 CreateMarker -884 -283 -24 CreateMarker -798 -369 248 CreateMarker -635 -369 304 CreateMarker -353 -369 410 CreateMarker -159 -307 440 CreateMarker -472 -198 152 CreateMarker -158 -148 440 CreateMarker -430 -142 440 CreateMarker -860 105 440 CreateMarker -818 401 440 CreateMarker -234 371 440 CreateMarker -835 564 440 CreateMarker -1029 636 440 CreateMarker -604 633 440 CreateMarker -768 826 440 CreateMarker 431 720 536 CreateMarker -90 680 440 SetZone 4 2 SetMarkerPath 4 0 13 SetGoal 5 1 SetZone 5 5 SetMarkerPath 5 1 87 SetMarkerPath 5 2 61 SetMarkerPathFlags 5 2 j SetMarkerPath 5 3 90 SetMarkerPathFlags 5 3 j SetGoal 6 2 SetZone 6 3 SetMarkerPath 6 0 36 SetMarkerPath 6 1 71 SetZone 7 16 SetMarkerPath 7 0 41 SetGoal 8 3 SetZone 8 3 SetMarkerPath 8 0 38 SetMarkerPath 8 1 9 SetMarkerPath 8 2 7 SetGoal 9 3 SetZone 9 3 SetMarkerPath 9 0 38 SetMarkerPath 9 1 8 SetMarkerPath 9 2 7 SetGoal 10 4 SetZone 10 5 SetMarkerPath 10 0 40 SetGoal 11 5 SetZone 11 3 SetMarkerPath 11 0 12 SetMarkerPath 11 1 36 SetGoal 12 5 SetZone 12 3 SetMarkerPath 12 0 79 SetMarkerPath 12 1 11 SetMarkerPath 12 2 36 SetZone 13 6 SetMarkerViewOfs 13 -2 SetMarkerPath 13 1 89 SetMarkerPath 13 2 14 SetMarkerPathFlags 13 2 j SetGoal 14 6 SetZone 14 6 SetMarkerPath 14 0 89 SetMarkerPathFlags 14 0 j SetMarkerPath 14 2 57 SetMarkerPathFlags 14 2 j SetGoal 15 7 SetZone 15 6 SetMarkerPath 15 1 89 SetGoal 16 8 SetZone 16 4 SetMarkerPath 16 0 84 SetMarkerPath 16 1 23 SetGoal 17 20 SetZone 17 1 SetMarkerPath 17 0 50 SetMarkerPath 17 1 28 SetGoal 18 22 SetZone 18 2 SetMarkerPath 18 0 54 SetMarkerPath 18 1 69 SetGoal 19 9 SetZone 19 1 SetMarkerPath 19 0 20 SetMarkerPath 19 1 42 SetGoal 20 9 SetZone 20 1 SetMarkerPath 20 0 56 SetMarkerPath 20 1 19 SetGoal 21 23 SetZone 21 1 SetMarkerPath 21 0 44 SetMarkerPath 21 1 22 SetGoal 22 24 SetZone 22 1 SetMarkerPath 22 0 21 SetMarkerPath 22 1 43 SetGoal 23 8 SetZone 23 4 SetMarkerPath 23 0 16 SetMarkerPath 23 1 80 SetMarkerPath 23 2 81 SetGoal 24 10 SetZone 24 2 SetMarkerPath 24 0 25 SetMarkerPath 24 1 62 SetGoal 25 10 SetZone 25 2 SetMarkerPath 25 0 63 SetMarkerPath 25 1 24 SetGoal 26 11 SetZone 26 4 SetMarkerPath 26 0 83 SetMarkerPath 26 1 27 SetGoal 27 11 SetZone 27 4 SetMarkerPath 27 0 83 SetMarkerPath 27 1 26 SetMarkerPath 27 2 82 SetGoal 28 23 SetZone 28 1 SetMarkerPath 28 0 17 SetMarkerPath 28 1 51 SetGoal 29 19 SetZone 29 2 SetMarkerPath 29 0 30 SetMarkerPath 29 1 68 SetGoal 30 23 SetZone 30 2 SetMarkerPath 30 0 69 SetMarkerPath 30 1 29 SetMarkerPath 30 2 68 SetGoal 31 24 SetZone 31 3 SetMarkerPath 31 0 39 SetMarkerPath 31 1 75 SetZone 32 5 SetMarkerPath 32 0 86 SetMarkerPath 32 1 88 SetZone 33 2 SetMarkerPath 33 0 67 SetZone 34 2 SetMarkerPath 34 0 61 SetMarkerPath 34 1 60 SetZone 35 1 SetMarkerPath 35 0 48 SetMarkerPath 35 1 49 SetZone 36 3 SetMarkerPath 36 0 12 SetMarkerPath 36 1 6 SetMarkerPath 36 2 71 SetMarkerPath 36 3 79 SetMarkerPath 36 4 11 SetZone 37 4 SetMarkerPath 37 0 84 SetMarkerPath 37 1 83 SetZone 38 3 SetMarkerPath 38 0 74 SetMarkerPath 38 1 9 SetMarkerPath 38 2 8 SetGoal 39 21 SetZone 39 3 SetMarkerPath 39 0 70 SetMarkerPath 39 1 31 SetGoal 40 4 SetZone 40 5 SetMarkerPath 40 0 10 SetMarkerPath 40 1 90 SetZone 41 4 SetMarkerViewOfs 41 -10 SetMarkerPath 41 0 81 SetMarkerPath 41 1 82 SetGoal 42 12 SetZone 42 1 SetMarkerPath 42 1 19 SetMarkerPath 42 2 47 SetMarkerPath 42 3 46 SetMarkerPath 42 4 44 SetZone 43 1 SetMarkerPath 43 0 22 SetZone 44 1 SetMarkerPath 44 0 42 SetMarkerPath 44 1 45 SetMarkerPath 44 3 21 SetZone 45 1 SetMarkerPath 45 0 44 SetMarkerPath 45 1 70 SetMarkerPath 45 2 79 SetMarkerPath 45 3 71 SetZone 46 1 SetMarkerPath 46 0 42 SetZone 47 1 SetMarkerPath 47 0 42 SetMarkerPath 47 1 48 SetZone 48 1 SetMarkerPath 48 0 47 SetMarkerPath 48 1 35 SetMarkerPath 48 2 55 SetZone 49 1 SetMarkerPath 49 0 35 SetMarkerPath 49 1 50 SetZone 50 1 SetMarkerPath 50 0 49 SetMarkerPath 50 1 17 SetMarkerPath 50 2 51 SetZone 51 1 SetMarkerPath 51 0 28 SetMarkerPath 51 1 50 SetMarkerPath 51 2 52 SetZone 52 1 SetMarkerPath 52 0 51 SetMarkerPath 52 2 54 SetZone 53 1 SetMarkerPath 53 1 86 SetMarkerPathFlags 53 1 j SetZone 54 1 SetMarkerPath 54 0 52 SetMarkerPath 54 1 18 SetZone 55 1 SetMarkerPath 55 0 48 SetMarkerPath 55 1 59 SetZone 56 1 SetMarkerPath 56 0 20 SetZone 57 2 SetMarkerPath 57 0 60 SetMarkerPath 57 1 58 SetZone 58 2 SetMarkerPath 58 0 57 SetMarkerPath 58 1 59 SetZone 59 2 SetMarkerPath 59 0 58 SetMarkerPath 59 1 55 SetZone 60 2 SetMarkerPath 60 0 34 SetMarkerPath 60 1 61 SetMarkerPath 60 2 57 SetZone 61 2 SetMarkerPath 61 0 62 SetMarkerPath 61 1 34 SetMarkerPath 61 2 60 SetMarkerPath 61 3 69 SetMarkerPathFlags 61 3 j SetZone 62 2 SetMarkerPath 62 0 61 SetMarkerPath 62 1 24 SetMarkerPath 62 2 63 SetZone 63 2 SetMarkerPath 63 0 64 SetMarkerPath 63 1 25 SetMarkerPath 63 2 62 SetZone 64 2 SetMarkerPath 64 0 65 SetMarkerPath 64 1 63 SetMarkerPath 64 2 62 SetMarkerPath 64 3 18 SetMarkerPathFlags 64 3 j SetZone 65 2 SetMarkerPath 65 0 69 SetMarkerPath 65 1 66 SetMarkerPath 65 2 64 SetMarkerPath 65 3 68 SetZone 66 2 SetMarkerPath 66 0 65 SetMarkerPath 66 1 68 SetMarkerPath 66 2 67 SetMarkerPath 66 3 69 SetZone 67 2 SetMarkerPath 67 0 66 SetMarkerPath 67 1 33 SetZone 68 2 SetMarkerPath 68 0 66 SetMarkerPath 68 1 69 SetMarkerPath 68 2 30 SetMarkerPath 68 3 29 SetMarkerPath 68 4 4 SetMarkerPath 68 5 65 SetZone 69 2 SetMarkerPath 69 0 18 SetMarkerPath 69 1 65 SetMarkerPath 69 2 68 SetMarkerPath 69 3 30 SetMarkerPath 69 4 66 SetZone 70 3 SetMarkerPath 70 0 71 SetMarkerPath 70 1 45 SetMarkerPath 70 2 39 SetZone 71 3 SetMarkerPath 71 0 6 SetMarkerPath 71 1 79 SetMarkerPath 71 2 45 SetMarkerPath 71 3 36 SetMarkerPath 71 4 72 SetMarkerPath 71 5 70 SetZone 72 3 SetMarkerPath 72 0 73 SetMarkerPath 72 1 71 SetZone 73 3 SetMarkerPath 73 0 74 SetMarkerPath 73 1 72 SetZone 74 3 SetMarkerPath 74 0 73 SetMarkerPath 74 1 38 SetZone 75 3 SetMarkerPath 75 0 31 SetMarkerPath 75 1 76 SetZone 76 3 SetMarkerPath 76 0 75 SetMarkerPath 76 1 77 SetZone 77 3 SetMarkerPath 77 0 76 SetMarkerPath 77 1 78 SetZone 78 3 SetMarkerPath 78 0 77 SetMarkerPath 78 1 80 SetZone 79 3 SetMarkerPath 79 0 45 SetMarkerPath 79 1 12 SetMarkerPath 79 2 71 SetMarkerPath 79 3 36 SetZone 80 4 SetMarkerPath 80 0 23 SetMarkerPath 80 1 81 SetMarkerPath 80 2 78 SetZone 81 4 SetMarkerPath 81 0 80 SetMarkerPath 81 1 23 SetMarkerPath 81 2 41 SetZone 82 4 SetMarkerPath 82 0 27 SetMarkerPath 82 1 83 SetMarkerPath 82 2 41 SetZone 83 4 SetMarkerPath 83 0 85 SetMarkerPath 83 1 37 SetMarkerPath 83 2 26 SetMarkerPath 83 3 27 SetMarkerPath 83 4 82 SetZone 84 4 SetMarkerPath 84 0 37 SetMarkerPath 84 1 16 SetZone 85 4 SetMarkerPath 85 0 83 SetMarkerPath 85 1 86 SetMarkerPath 85 2 88 SetMarkerPath 85 3 87 SetZone 86 5 SetMarkerPath 86 0 85 SetMarkerPath 86 1 32 SetMarkerPath 86 2 88 SetZone 87 5 SetMarkerPath 87 0 88 SetMarkerPath 87 1 5 SetMarkerPath 87 2 85 SetZone 88 5 SetMarkerPath 88 0 86 SetMarkerPath 88 1 85 SetMarkerPath 88 2 32 SetMarkerPath 88 3 87 SetZone 89 6 SetMarkerPath 89 0 13 SetMarkerPath 89 1 15 SetMarkerPath 89 2 14 SetMarkerPathFlags 89 2 j SetMarkerPath 89 4 58 SetMarkerPathFlags 89 4 j SetZone 90 5 SetMarkerPath 90 0 5 SetMarkerPathFlags 90 0 j SetMarkerPath 90 1 40 SetMarkerPath 90 2 30 SetMarkerPathFlags 90 2 j QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm3.bot000066400000000000000000000433201475442401000261670ustar00rootroot00000000000000CreateMarker -418 159 284 CreateMarker -94 -869 -40 CreateMarker -97 -216 24 CreateMarker -662 483 280 CreateMarker -947 416 280 CreateMarker -818 446 280 CreateMarker -982 248 264 CreateMarker -988 107 216 CreateMarker -987 -18 216 CreateMarker -977 -206 216 CreateMarker -961 -407 216 CreateMarker -838 -341 220 CreateMarker -774 -449 216 CreateMarker -586 -474 200 CreateMarker -429 -503 152 CreateMarker -411 -772 152 CreateMarker -418 -640 152 CreateMarker -299 -770 152 CreateMarker -277 -869 152 CreateMarker 80 -861 152 CreateMarker 117 -713 152 CreateMarker 107 -547 168 CreateMarker 1 -403 216 CreateMarker 102 -417 216 CreateMarker -33 -142 280 CreateMarker -7 -289 248 CreateMarker -94 -339 24 CreateMarker -98 -498 24 CreateMarker -630 563 280 CreateMarker -606 683 280 CreateMarker -458 674 280 CreateMarker -335 698 264 CreateMarker -447 558 280 CreateMarker -760 -170 220 CreateMarker -751 6 220 CreateMarker -724 -72 220 CreateMarker -861 14 216 CreateMarker -460 -62 284 CreateMarker -464 47 284 CreateMarker -341 103 284 CreateMarker -156 148 284 CreateMarker -131 284 280 CreateMarker -133 426 280 CreateMarker -222 495 248 CreateMarker -185 577 216 CreateMarker -205 706 216 CreateMarker -62 576 216 CreateMarker -21 676 216 CreateMarker 96 702 200 CreateMarker 198 688 152 CreateMarker 237 626 120 CreateMarker 196 566 88 CreateMarker 100 559 40 CreateMarker -31 526 24 CreateMarker -94 381 24 CreateMarker -139 42 24 CreateMarker -145 -59 24 CreateMarker -260 -5 24 CreateMarker -506 -7 -19 CreateMarker -641 -2 -35 CreateMarker -729 3 -35 CreateMarker -698 -99 -40 CreateMarker -860 -103 -40 CreateMarker -872 102 -40 CreateMarker -922 295 -40 CreateMarker -951 186 -40 CreateMarker -98 -652 24 CreateMarker -95 -801 -8 CreateMarker 20 -569 24 CreateMarker 132 -562 24 CreateMarker 260 -590 24 CreateMarker 287 -660 56 CreateMarker 287 -763 104 CreateMarker 264 -880 152 CreateMarker 164 -888 152 CreateMarker -214 -796 8 CreateMarker 30 -804 8 CreateMarker -189 -626 24 CreateMarker -312 819 344 CreateMarker -144 496 24 CreateMarker -370 504 296 CreateMarker -366 632 312 CreateMarker -940 -83 -40 CreateMarker -356 3 24 CreateMarker -623 156 284 CreateMarker -363 -115 284 SetZone 1 1 SetMarkerPath 1 0 110 SetMarkerPath 1 1 48 SetMarkerPath 1 2 111 SetZone 2 8 SetMarkerPath 2 0 3 SetGoal 3 18 SetZone 3 8 SetMarkerPath 3 0 71 SetMarkerPath 3 1 73 SetMarkerPath 3 2 10 SetMarkerPath 3 3 129 SetZone 4 7 SetMarkerPath 4 0 6 SetZone 5 4 SetMarkerPath 5 0 50 SetZone 6 7 SetMarkerPath 6 0 56 SetMarkerPath 6 1 58 SetMarkerPath 6 2 57 SetGoal 7 1 SetZone 7 5 SetMarkerPath 7 0 86 SetMarkerPath 7 4 136 SetGoal 8 22 SetZone 8 9 SetMarkerPath 8 0 33 SetMarkerPath 8 1 41 SetMarkerPath 8 2 11 SetMarkerPath 8 3 84 SetMarkerPath 8 4 95 SetMarkerPath 8 5 132 SetGoal 9 5 SetZone 9 6 SetMarkerPath 9 0 79 SetMarkerPath 9 1 129 SetMarkerPath 9 2 13 SetMarkerPathFlags 9 2 r SetRocketJumpPathFields 9 2 78.3 -1.0 0 SetMarkerPath 9 3 10 SetMarkerPathFlags 9 3 r SetRocketJumpPathFields 9 3 50.0 110.0 0 SetGoal 10 4 SetZone 10 8 SetMarkerPath 10 0 70 SetMarkerPath 10 1 71 SetMarkerPath 10 2 30 SetMarkerPath 10 3 118 SetMarkerPath 10 4 74 SetMarkerPathFlags 10 4 r SetRocketJumpPathFields 10 4 45.0 260.0 0 SetGoal 11 15 SetZone 11 9 SetMarkerPath 11 0 32 SetMarkerPath 11 1 33 SetMarkerPath 11 2 84 SetMarkerPath 11 3 8 SetMarkerPath 11 4 34 SetMarkerPathFlags 11 4 r SetRocketJumpPathFields 11 4 40.0 235.0 0 SetZone 12 7 SetMarkerPath 12 0 62 SetMarkerPath 12 1 22 SetZone 13 8 SetMarkerPath 13 0 74 SetMarkerPath 13 1 120 SetMarkerPath 13 2 118 SetZone 14 9 SetMarkerPath 14 0 95 SetMarkerPath 14 1 96 SetZone 15 8 SetMarkerPath 15 0 76 SetMarkerPath 15 1 43 SetMarkerPath 15 2 44 SetZone 16 2 SetMarkerPath 16 0 106 SetMarkerPath 16 1 19 SetMarkerPath 16 2 107 SetGoal 17 17 SetZone 17 9 SetMarkerPath 17 0 80 SetMarkerPath 17 1 18 SetMarkerPath 17 2 55 SetMarkerPath 17 3 57 SetGoal 18 17 SetZone 18 9 SetMarkerPath 18 0 17 SetMarkerPath 18 1 55 SetMarkerPath 18 2 57 SetMarkerPath 18 3 80 SetGoal 19 20 SetZone 19 3 SetMarkerPath 19 0 16 SetMarkerPath 19 1 107 SetMarkerPath 19 2 20 SetGoal 20 20 SetZone 20 3 SetMarkerPath 20 0 19 SetMarkerPath 20 1 108 SetMarkerPath 20 2 54 SetGoal 21 12 SetZone 21 1 SetMarkerPath 21 0 110 SetMarkerPath 21 1 111 SetMarkerPath 21 2 38 SetMarkerPath 21 3 113 SetMarkerPath 21 4 87 SetMarkerPathFlags 21 4 r SetRocketJumpPathFields 21 4 70.0 360.0 0 SetMarkerPath 21 5 7 SetMarkerPathFlags 21 5 r SetRocketJumpPathFields 21 5 80.0 290.0 0 SetGoal 22 10 SetZone 22 7 SetMarkerPath 22 0 12 SetMarkerPath 22 1 23 SetMarkerPath 22 2 64 SetMarkerPath 22 3 24 SetGoal 23 10 SetZone 23 7 SetMarkerPath 23 0 22 SetMarkerPath 23 1 24 SetMarkerPath 23 2 64 SetGoal 24 10 SetZone 24 7 SetMarkerPath 24 0 23 SetMarkerPath 24 1 64 SetMarkerPath 24 2 22 SetGoal 25 9 SetZone 25 8 SetMarkerPath 25 0 67 SetMarkerPath 25 1 26 SetMarkerPath 25 2 70 SetGoal 26 9 SetZone 26 8 SetMarkerPath 26 0 25 SetMarkerPath 26 1 31 SetMarkerPath 26 2 70 SetGoal 27 18 SetZone 27 11 SetMarkerPath 27 0 122 SetMarkerPath 27 1 29 SetMarkerPath 27 2 123 SetMarkerPath 27 3 121 SetGoal 28 14 SetZone 28 1 SetMarkerPath 28 0 5 SetMarkerPath 28 1 116 SetGoal 29 23 SetZone 29 11 SetMarkerPath 29 0 27 SetMarkerPath 29 1 122 SetMarkerPath 29 2 121 SetMarkerPath 29 3 123 SetGoal 30 8 SetZone 30 8 SetMarkerPath 30 0 70 SetMarkerPath 30 1 71 SetMarkerPath 30 2 10 SetGoal 31 24 SetZone 31 8 SetMarkerPath 31 0 26 SetMarkerPath 31 1 70 SetGoal 32 23 SetZone 32 9 SetMarkerPath 32 0 33 SetMarkerPath 32 1 11 SetGoal 33 23 SetZone 33 9 SetMarkerPath 33 0 32 SetMarkerPath 33 1 41 SetMarkerPath 33 2 11 SetMarkerPath 33 3 8 SetGoal 34 6 SetZone 34 10 SetMarkerPath 34 0 130 SetMarkerPath 34 1 97 SetMarkerPath 34 2 96 SetMarkerPath 34 3 83 SetMarkerPath 34 4 98 SetGoal 35 11 SetZone 35 7 SetMarkerPath 35 0 40 SetMarkerPath 35 1 42 SetMarkerPath 35 2 61 SetGoal 36 16 SetZone 36 2 SetMarkerPath 36 0 105 SetMarkerPath 36 1 39 SetMarkerPath 36 2 37 SetMarkerPath 36 3 131 SetGoal 37 19 SetZone 37 2 SetMarkerPath 37 0 36 SetMarkerPath 37 1 131 SetMarkerPath 37 2 39 SetGoal 38 18 SetZone 38 1 SetMarkerPath 38 0 113 SetMarkerPath 38 1 111 SetGoal 39 19 SetZone 39 2 SetMarkerPath 39 0 105 SetMarkerPath 39 1 36 SetMarkerPath 39 2 37 SetGoal 40 11 SetZone 40 7 SetMarkerPath 40 0 85 SetMarkerPath 40 1 35 SetMarkerPath 40 2 87 SetMarkerPath 40 3 42 SetGoal 41 23 SetZone 41 9 SetMarkerPath 41 0 33 SetMarkerPath 41 1 8 SetMarkerPath 41 2 95 SetGoal 42 7 SetZone 42 7 SetMarkerPath 42 0 87 SetMarkerPath 42 1 86 SetMarkerPath 42 2 88 SetMarkerPath 42 3 60 SetMarkerPath 42 4 35 SetMarkerPath 42 5 40 SetGoal 43 21 SetZone 43 8 SetMarkerPath 43 0 15 SetMarkerPath 43 1 44 SetMarkerPath 43 2 137 SetGoal 44 24 SetZone 44 8 SetMarkerPath 44 0 43 SetMarkerPath 44 1 137 SetMarkerPath 44 2 15 SetGoal 45 3 SetZone 45 1 SetMarkerPath 45 0 46 SetMarkerPath 45 1 134 SetMarkerPath 45 2 115 SetMarkerPath 45 3 47 SetMarkerPath 45 4 117 SetGoal 46 2 SetZone 46 1 SetMarkerPath 46 0 47 SetMarkerPath 46 1 45 SetMarkerPath 46 2 134 SetMarkerPath 46 3 117 SetMarkerPath 46 4 115 SetGoal 47 13 SetZone 47 1 SetMarkerPath 47 0 114 SetMarkerPath 47 1 46 SetMarkerPath 47 2 45 SetMarkerPath 47 3 134 SetGoal 48 22 SetZone 48 1 SetMarkerPath 48 0 1 SetMarkerPath 48 1 110 SetMarkerPath 48 2 111 SetMarkerPath 48 3 49 SetMarkerPath 48 4 112 SetMarkerPath 48 5 86 SetMarkerPathFlags 48 5 r SetRocketJumpPathFields 48 5 72.0 30.0 0 SetMarkerPath 48 6 135 SetGoal 49 23 SetZone 49 1 SetMarkerPath 49 0 111 SetMarkerPath 49 1 112 SetZone 50 4 SetMarkerPath 50 0 92 SetMarkerPath 50 1 91 SetMarkerPath 50 2 93 SetZone 51 1 SetMarkerPath 51 0 112 SetMarkerPath 51 1 113 SetMarkerPath 51 2 114 SetMarkerPath 51 3 115 SetMarkerPath 51 4 111 SetZone 52 4 SetMarkerPath 52 0 90 SetMarkerPath 52 1 91 SetMarkerPath 52 2 86 SetMarkerPath 52 3 112 SetMarkerPath 52 4 113 SetZone 53 6 SetMarkerPath 53 0 4 SetMarkerPath 53 1 127 SetMarkerPath 53 2 119 SetMarkerPath 53 3 128 SetZone 54 3 SetMarkerPath 54 0 20 SetMarkerPath 54 1 108 SetMarkerPath 54 2 78 SetZone 55 9 SetMarkerPath 55 0 80 SetMarkerPath 55 1 57 SetMarkerPath 55 2 18 SetMarkerPath 55 3 17 SetZone 56 7 SetMarkerPath 56 0 6 SetMarkerPath 56 1 58 SetMarkerPath 56 2 57 SetZone 57 7 SetMarkerPath 57 0 55 SetMarkerPath 57 1 56 SetMarkerPath 57 2 17 SetZone 58 7 SetMarkerPath 58 0 56 SetMarkerPath 58 1 59 SetZone 59 7 SetMarkerPath 59 0 58 SetMarkerPath 59 1 60 SetMarkerPath 59 2 88 SetZone 60 7 SetMarkerPath 60 0 59 SetMarkerPath 60 1 61 SetMarkerPath 60 2 88 SetMarkerPath 60 3 42 SetZone 61 7 SetMarkerPath 61 0 60 SetMarkerPath 61 1 62 SetMarkerPath 61 2 35 SetMarkerPath 61 3 63 SetZone 62 7 SetMarkerPath 62 0 61 SetMarkerPath 62 1 64 SetMarkerPath 62 2 63 SetMarkerPath 62 3 12 SetZone 63 7 SetMarkerPath 63 0 85 SetMarkerPath 63 1 61 SetMarkerPath 63 2 62 SetMarkerPath 63 3 64 SetZone 64 7 SetMarkerPath 64 0 62 SetMarkerPath 64 1 65 SetMarkerPath 64 2 85 SetMarkerPath 64 3 63 SetMarkerPath 64 4 23 SetMarkerPath 64 5 22 SetZone 65 7 SetMarkerPath 65 0 64 SetMarkerPath 65 1 66 SetZone 66 8 SetMarkerPath 66 0 65 SetMarkerPath 66 1 68 SetZone 67 8 SetMarkerPath 67 0 68 SetMarkerPath 67 1 69 SetMarkerPath 67 2 70 SetMarkerPath 67 3 25 SetZone 68 8 SetMarkerPath 68 0 66 SetMarkerPath 68 1 67 SetZone 69 8 SetMarkerPath 69 0 67 SetMarkerPath 69 1 70 SetMarkerPath 69 2 119 SetMarkerPath 69 3 118 SetZone 70 8 SetMarkerPath 70 0 69 SetMarkerPath 70 1 67 SetMarkerPath 70 2 10 SetMarkerPath 70 3 118 SetMarkerPath 70 4 25 SetMarkerPath 70 5 26 SetZone 71 8 SetMarkerPath 71 0 10 SetMarkerPath 71 1 30 SetMarkerPath 71 2 126 SetMarkerPath 71 3 72 SetMarkerPath 71 4 118 SetZone 72 8 SetMarkerPath 72 0 71 SetMarkerPath 72 1 73 SetMarkerPath 72 2 126 SetMarkerPath 72 3 119 SetMarkerPath 72 4 118 SetZone 73 8 SetMarkerPath 73 0 72 SetMarkerPath 73 1 75 SetMarkerPath 73 2 118 SetMarkerPath 73 3 79 SetZone 74 8 SetMarkerPath 74 0 75 SetMarkerPath 74 1 13 SetMarkerPath 74 2 77 SetMarkerPath 74 3 120 SetMarkerPath 74 4 118 SetMarkerPath 74 5 72 SetMarkerPathAngleHint 74 5 -15 SetZone 75 8 SetMarkerPath 75 0 73 SetMarkerPath 75 1 74 SetMarkerPath 75 2 118 SetZone 76 8 SetMarkerPath 76 0 77 SetMarkerPath 76 1 15 SetZone 77 8 SetMarkerPath 77 0 74 SetMarkerPath 77 1 76 SetZone 78 3 SetMarkerPath 78 0 54 SetMarkerPath 78 1 79 SetZone 79 6 SetMarkerPath 79 0 78 SetMarkerPath 79 1 120 SetMarkerPath 79 2 9 SetMarkerPath 79 3 118 SetMarkerPath 79 4 129 SetMarkerPath 79 5 10 SetMarkerPathFlags 79 5 r SetRocketJumpPathFields 79 5 50.0 90.0 0 SetMarkerPath 79 6 70 SetMarkerPathFlags 79 6 r SetRocketJumpPathFields 79 6 60.0 60.0 0 SetZone 80 9 SetMarkerPath 80 0 81 SetMarkerPath 80 1 55 SetMarkerPath 80 2 17 SetZone 81 9 SetMarkerPath 81 0 82 SetMarkerPath 81 1 80 SetZone 82 9 SetMarkerPath 82 0 84 SetMarkerPath 82 1 81 SetMarkerPath 82 2 83 SetMarkerPath 82 3 34 SetMarkerPathFlags 82 3 r SetRocketJumpPathFields 82 3 45.0 210.0 0 SetZone 83 9 SetMarkerPath 83 0 97 SetMarkerPath 83 1 82 SetMarkerPath 83 2 34 SetMarkerPathFlags 83 2 r SetRocketJumpPathFields 83 2 50.0 7.0 0 SetZone 84 9 SetMarkerPath 84 0 11 SetMarkerPath 84 1 8 SetMarkerPath 84 2 82 SetMarkerPath 84 3 132 SetMarkerPath 84 4 133 SetMarkerPathFlags 84 4 j SetZone 85 7 SetMarkerPath 85 0 87 SetMarkerPath 85 1 40 SetMarkerPath 85 2 63 SetMarkerPath 85 3 64 SetMarkerPath 85 4 7 SetMarkerPathFlags 85 4 r SetRocketJumpPathFields 85 4 30.0 250.0 0 SetZone 86 7 SetMarkerPath 86 0 88 SetMarkerPath 86 1 87 SetMarkerPath 86 2 42 SetMarkerPath 86 3 111 SetMarkerPath 86 4 136 SetMarkerPathFlags 86 4 r SetRocketJumpPathFields 86 4 35.0 240.0 0 SetMarkerPath 86 5 90 SetMarkerPathFlags 86 5 r SetRocketJumpPathFields 86 5 78.3 -1.0 0 SetMarkerPath 86 6 89 SetMarkerPathFlags 86 6 r SetRocketJumpPathFields 86 6 78.3 -1.0 0 SetMarkerPath 86 7 110 SetZone 87 7 SetMarkerPath 87 0 86 SetMarkerPath 87 1 85 SetMarkerPath 87 2 40 SetMarkerPath 87 3 42 SetMarkerPath 87 4 111 SetMarkerPath 87 5 89 SetMarkerPathFlags 87 5 r SetRocketJumpPathFields 87 5 40.0 180.0 0 SetMarkerPath 87 6 90 SetMarkerPathFlags 87 6 r SetRocketJumpPathFields 87 6 40.0 200.0 0 SetMarkerPath 87 7 110 SetZone 88 7 SetMarkerPath 88 0 59 SetMarkerPath 88 1 86 SetMarkerPath 88 2 42 SetMarkerPath 88 3 60 SetZone 89 8 SetMarkerPath 89 0 137 SetMarkerPath 89 2 90 SetMarkerPath 89 3 87 SetMarkerPath 89 4 113 SetMarkerPath 89 5 112 SetZone 90 4 SetMarkerPath 90 0 89 SetMarkerPath 90 1 91 SetMarkerPath 90 2 86 SetMarkerPath 90 3 136 SetMarkerPathAngleHint 90 3 20 SetMarkerPath 90 4 52 SetMarkerPath 90 5 112 SetMarkerPath 90 6 87 SetZone 91 4 SetMarkerPath 91 0 90 SetMarkerPath 91 1 92 SetMarkerPath 91 2 52 SetZone 92 4 SetMarkerPath 92 0 93 SetMarkerPath 92 1 91 SetZone 93 4 SetMarkerPath 93 0 92 SetMarkerPath 93 1 94 SetMarkerPath 93 2 34 SetMarkerPathFlags 93 2 r SetRocketJumpPathFields 93 2 38.0 275.0 0 SetZone 94 4 SetMarkerPath 94 0 93 SetMarkerPath 94 1 98 SetMarkerPath 94 2 96 SetMarkerPath 94 3 95 SetMarkerPath 94 4 41 SetZone 95 9 SetMarkerPath 95 0 94 SetMarkerPath 95 1 14 SetMarkerPath 95 2 96 SetZone 96 9 SetMarkerPath 96 0 94 SetMarkerPath 96 1 14 SetMarkerPath 96 2 95 SetMarkerPath 96 3 98 SetMarkerPath 96 4 97 SetMarkerPath 96 5 99 SetZone 97 9 SetMarkerPath 97 0 96 SetMarkerPath 97 1 83 SetMarkerPath 97 2 98 SetMarkerPath 97 3 99 SetMarkerPath 97 4 34 SetMarkerPathFlags 97 4 r SetRocketJumpPathFields 97 4 70.0 260.0 6 SetZone 98 9 SetMarkerPath 98 0 94 SetMarkerPath 98 1 99 SetMarkerPath 98 2 96 SetMarkerPath 98 3 97 SetZone 99 2 SetMarkerPath 99 0 98 SetMarkerPath 99 1 100 SetMarkerPath 99 2 97 SetMarkerPath 99 3 96 SetMarkerPath 99 5 130 SetMarkerPathFlags 99 5 r SetRocketJumpPathFields 99 5 50.0 335.0 0 SetZone 100 2 SetMarkerPath 100 0 99 SetMarkerPath 100 1 101 SetZone 101 2 SetMarkerPath 101 0 100 SetMarkerPath 101 1 102 SetZone 102 2 SetMarkerPath 102 0 101 SetMarkerPath 102 1 103 SetZone 103 2 SetMarkerPath 103 0 102 SetMarkerPath 103 1 104 SetZone 104 2 SetMarkerPath 104 0 103 SetMarkerPath 104 1 105 SetZone 105 2 SetMarkerPath 105 0 104 SetMarkerPath 105 1 39 SetMarkerPath 105 2 36 SetMarkerPath 105 3 131 SetMarkerPath 105 4 106 SetZone 106 2 SetMarkerPath 106 0 105 SetMarkerPath 106 1 131 SetMarkerPath 106 2 16 SetZone 107 3 SetMarkerPath 107 0 16 SetMarkerPath 107 1 19 SetMarkerPath 107 2 108 SetMarkerPath 107 3 109 SetZone 108 3 SetMarkerPath 108 0 20 SetMarkerPath 108 1 54 SetMarkerPath 108 2 107 SetMarkerPath 108 3 109 SetZone 109 3 SetMarkerPath 109 0 108 SetMarkerPath 109 1 110 SetMarkerPath 109 2 107 SetMarkerPath 109 3 135 SetZone 110 1 SetMarkerPath 110 0 21 SetMarkerPathFlags 110 0 j SetMarkerPath 110 1 1 SetMarkerPathFlags 110 1 j SetMarkerPath 110 2 111 SetMarkerPath 110 3 109 SetMarkerPath 110 4 135 SetMarkerPath 110 5 38 SetZone 111 1 SetMarkerPath 111 0 38 SetMarkerPath 111 1 110 SetMarkerPath 111 2 49 SetMarkerPath 111 3 112 SetMarkerPath 111 4 113 SetMarkerPath 111 5 51 SetZone 112 1 SetMarkerPath 112 0 111 SetMarkerPath 112 1 51 SetMarkerPath 112 2 115 SetMarkerPath 112 3 49 SetMarkerPath 112 4 113 SetZone 113 1 SetMarkerPath 113 0 38 SetMarkerPath 113 1 111 SetMarkerPath 113 2 51 SetMarkerPath 113 3 114 SetMarkerPath 113 4 112 SetZone 114 1 SetMarkerPath 114 0 113 SetMarkerPath 114 1 47 SetMarkerPath 114 2 134 SetMarkerPath 114 3 51 SetZone 115 1 SetMarkerPath 115 0 46 SetMarkerPath 115 1 45 SetMarkerPath 115 2 51 SetMarkerPath 115 3 112 SetMarkerPath 115 4 117 SetZone 116 1 SetMarkerPath 116 0 117 SetMarkerPath 116 1 28 SetZone 117 1 SetMarkerPath 117 0 46 SetMarkerPath 117 1 115 SetMarkerPath 117 2 45 SetMarkerPath 117 3 116 SetZone 118 6 SetMarkerPath 118 0 79 SetMarkerPath 118 1 129 SetMarkerPath 118 2 120 SetMarkerPath 118 3 119 SetMarkerPath 118 4 128 SetMarkerPath 118 5 127 SetMarkerPath 118 6 10 SetMarkerPathFlags 118 6 r SetRocketJumpPathFields 118 6 78.3 -1.0 0 SetMarkerPath 118 7 74 SetMarkerPathFlags 118 7 r SetRocketJumpPathFields 118 7 73.0 250.0 0 SetZone 119 6 SetMarkerPath 119 0 129 SetMarkerPath 119 1 118 SetMarkerPath 119 2 53 SetMarkerPath 119 3 127 SetMarkerPath 119 4 128 SetZone 120 6 SetMarkerPath 120 0 79 SetMarkerPath 120 1 121 SetMarkerPath 120 2 118 SetMarkerPath 120 3 128 SetZone 121 11 SetMarkerPath 121 0 120 SetMarkerPath 121 1 122 SetZone 122 11 SetMarkerPath 122 0 121 SetMarkerPath 122 1 123 SetMarkerPath 122 2 27 SetZone 123 11 SetMarkerPath 123 0 122 SetMarkerPath 123 1 124 SetMarkerPath 123 2 27 SetZone 124 11 SetMarkerPath 124 0 123 SetMarkerPath 124 1 125 SetZone 125 11 SetMarkerPath 125 0 124 SetMarkerPath 125 1 126 SetZone 126 8 SetMarkerPath 126 0 71 SetMarkerPath 126 1 125 SetMarkerPath 126 2 72 SetZone 127 6 SetMarkerPath 127 0 129 SetMarkerPath 127 1 118 SetMarkerPath 127 2 53 SetMarkerPath 127 3 119 SetZone 128 6 SetMarkerPath 128 0 118 SetMarkerPath 128 1 53 SetMarkerPath 128 2 119 SetMarkerPath 128 3 120 SetZone 129 6 SetMarkerPath 129 0 79 SetMarkerPath 129 1 118 SetMarkerPath 129 2 9 SetMarkerPath 129 3 127 SetMarkerPath 129 4 119 SetMarkerPath 129 5 120 SetMarkerPath 129 6 74 SetMarkerPathFlags 129 6 r SetRocketJumpPathFields 129 6 78.3 -1.0 0 SetMarkerPath 129 7 10 SetMarkerPathFlags 129 7 r SetRocketJumpPathFields 129 7 78.3 -1.0 0 SetZone 130 10 SetMarkerPath 130 0 83 SetMarkerPath 130 1 97 SetMarkerPath 130 2 34 SetMarkerPath 130 3 82 SetZone 131 2 SetMarkerPath 131 0 105 SetMarkerPath 131 1 37 SetMarkerPath 131 2 36 SetMarkerPath 131 3 106 SetZone 132 9 SetMarkerPath 132 0 133 SetMarkerPath 132 1 8 SetMarkerPath 132 2 84 SetMarkerPath 132 3 95 SetMarkerPath 132 4 96 SetZone 133 9 SetMarkerPath 133 0 132 SetMarkerPath 133 1 130 SetMarkerPathFlags 133 1 j SetMarkerPath 133 2 82 SetMarkerPath 133 3 84 SetMarkerPath 133 4 97 SetMarkerPath 133 5 95 SetZone 134 1 SetMarkerPath 134 0 114 SetMarkerPath 134 1 46 SetMarkerPath 134 2 45 SetMarkerPath 134 3 47 SetZone 135 1 SetMarkerPath 135 0 21 SetMarkerPathAngleHint 135 0 -45 SetMarkerPath 135 1 1 SetMarkerPathAngleHint 135 1 45 SetMarkerPath 135 2 110 SetMarkerPath 135 3 109 SetZone 136 5 SetMarkerPath 136 0 7 SetMarkerPath 136 2 90 SetMarkerPath 136 3 86 SetMarkerPath 136 4 110 SetMarkerPath 136 5 111 SetZone 137 8 SetMarkerPath 137 0 89 SetMarkerPath 137 1 44 SetMarkerPath 137 2 43 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm4.bot000066400000000000000000000223341475442401000261720ustar00rootroot00000000000000CreateMarker 929 -111 376 CreateMarker 1118 228 88 CreateMarker 857 -142 88 CreateMarker 777 -149 72 CreateMarker 645 -156 24 CreateMarker 515 34 24 CreateMarker 357 -25 24 CreateMarker 169 -18 24 CreateMarker 667 16 -8 CreateMarker 742 17 -56 CreateMarker 891 17 -104 CreateMarker 1045 29 -104 CreateMarker 1014 318 -104 CreateMarker 931 271 -136 CreateMarker 797 248 -200 CreateMarker 855 164 -200 CreateMarker 680 448 -200 CreateMarker 714 551 -200 CreateMarker 714 836 -184 CreateMarker 714 1004 -136 CreateMarker 504 713 -200 CreateMarker 369 703 -168 CreateMarker 196 686 -136 CreateMarker 73 684 -136 CreateMarker -55 840 -136 CreateMarker -41 967 -104 CreateMarker -172 1121 -24 CreateMarker -345 886 24 CreateMarker -343 539 24 CreateMarker -163 279 24 CreateMarker 43 279 24 CreateMarker 57 136 24 CreateMarker -173 911 -264 CreateMarker -169 694 -264 CreateMarker 42 519 -264 CreateMarker -153 507 -264 CreateMarker 972 281 88 CreateMarker 958 485 88 CreateMarker 1036 674 88 CreateMarker 1298 637 88 CreateMarker 1321 855 88 CreateMarker 1328 1030 88 CreateMarker 1094 1007 88 CreateMarker 964 961 120 CreateMarker 788 1005 152 CreateMarker 929 1170 152 CreateMarker 614 993 168 CreateMarker 571 1117 152 CreateMarker 590 785 184 CreateMarker 373 702 184 CreateMarker 106 686 184 CreateMarker 113 844 184 CreateMarker -66 977 184 CreateMarker -360 811 184 CreateMarker -99 689 -136 CreateMarker 79 846 -264 CreateMarker -24 746 -264 SetZone 1 8 SetMarkerViewOfs 1 -6 SetMarkerPath 1 0 104 SetMarkerPath 1 1 20 SetMarkerPathFlags 1 1 j SetZone 2 3 SetMarkerPath 2 0 1 SetZone 3 6 SetMarkerViewOfs 3 -10 SetMarkerPath 3 0 52 SetZone 4 5 SetMarkerPath 4 0 25 SetMarkerPath 4 1 15 SetMarkerPath 4 2 3 SetZone 5 7 SetMarkerPath 5 0 6 SetZone 6 4 SetMarkerViewOfs 6 -10 SetMarkerPath 6 0 70 SetMarkerPath 6 1 33 SetMarkerPath 6 2 34 SetZone 7 1 SetMarkerViewOfs 7 17 SetMarkerPath 7 0 57 SetMarkerPath 7 1 56 SetMarkerPath 7 2 55 SetZone 8 8 SetMarkerViewOfs 8 17 SetMarkerPath 8 0 102 SetMarkerPath 8 1 103 SetZone 9 1 SetMarkerViewOfs 9 17 SetMarkerPath 9 0 26 SetMarkerPath 9 1 23 SetMarkerPath 9 2 52 SetMarkerPathFlags 9 2 j SetZone 10 7 SetMarkerViewOfs 10 17 SetMarkerPath 10 0 92 SetZone 11 2 SetMarkerViewOfs 11 17 SetMarkerPath 11 0 58 SetMarkerPath 11 1 82 SetZone 12 4 SetMarkerViewOfs 12 17 SetMarkerPath 12 0 71 SetMarkerPath 12 1 68 SetMarkerPath 12 2 69 SetZone 13 2 SetMarkerViewOfs 13 17 SetMarkerPath 13 0 80 SetMarkerPath 13 1 79 SetGoal 14 1 SetZone 14 6 SetMarkerPath 14 0 37 SetMarkerPath 14 1 56 SetMarkerPathFlags 14 1 j SetGoal 15 2 SetZone 15 5 SetMarkerPath 15 0 65 SetMarkerPath 15 1 24 SetMarkerPath 15 2 4 SetGoal 16 3 SetZone 16 8 SetMarkerPath 16 0 103 SetMarkerPath 16 1 28 SetMarkerPath 16 2 104 SetGoal 17 20 SetZone 17 7 SetMarkerPath 17 0 39 SetMarkerPath 17 1 18 SetMarkerPathFlags 17 1 j SetGoal 18 4 SetZone 18 7 SetMarkerPath 18 0 92 SetMarkerPathFlags 18 0 j SetGoal 19 21 SetZone 19 3 SetMarkerPath 19 0 27 SetMarkerPath 19 1 78 SetGoal 20 5 SetZone 20 8 SetMarkerPath 20 0 101 SetMarkerPathFlags 20 0 j SetMarkerPath 20 1 79 SetMarkerPathFlags 20 1 j SetGoal 21 6 SetZone 21 3 SetMarkerPath 21 0 77 SetMarkerPath 21 1 76 SetGoal 22 7 SetZone 22 7 SetMarkerPath 22 0 5 SetMarkerPath 22 1 98 SetMarkerPath 22 2 96 SetGoal 23 8 SetZone 23 1 SetMarkerPath 23 0 9 SetGoal 24 9 SetZone 24 5 SetMarkerPath 24 0 15 SetMarkerPath 24 1 25 SetGoal 25 9 SetZone 25 5 SetMarkerPath 25 0 24 SetMarkerPath 25 1 4 SetGoal 26 10 SetZone 26 1 SetMarkerPath 26 0 53 SetMarkerPath 26 1 9 SetGoal 27 24 SetZone 27 3 SetMarkerPath 27 0 79 SetMarkerPath 27 1 19 SetGoal 28 11 SetZone 28 8 SetMarkerPath 28 0 16 SetGoal 29 23 SetZone 29 5 SetMarkerPath 29 0 66 SetMarkerPath 29 1 30 SetGoal 30 19 SetZone 30 5 SetMarkerPath 30 0 29 SetMarkerPath 30 1 66 SetGoal 31 12 SetZone 31 3 SetMarkerPath 31 0 78 SetMarkerPath 31 1 32 SetGoal 32 12 SetZone 32 3 SetMarkerPath 32 0 31 SetMarkerPath 32 1 77 SetGoal 33 13 SetZone 33 4 SetMarkerPath 33 0 6 SetMarkerPath 33 1 35 SetGoal 34 13 SetZone 34 4 SetMarkerPath 34 0 6 SetMarkerPath 34 1 41 SetGoal 35 13 SetZone 35 4 SetMarkerPath 35 0 33 SetMarkerPath 35 1 41 SetGoal 36 14 SetZone 36 7 SetMarkerPath 36 0 39 SetMarkerPath 36 1 5 SetMarkerPath 36 2 96 SetGoal 37 15 SetZone 37 6 SetMarkerPath 37 0 38 SetMarkerPath 37 1 14 SetMarkerPathFlags 37 1 j SetGoal 38 15 SetZone 38 6 SetMarkerPath 38 0 87 SetMarkerPath 38 1 37 SetGoal 39 14 SetZone 39 7 SetMarkerPath 39 0 50 SetMarkerPath 39 1 17 SetMarkerPath 39 2 36 SetGoal 40 22 SetZone 40 5 SetMarkerPath 40 0 63 SetMarkerPath 40 1 62 SetGoal 41 13 SetZone 41 4 SetMarkerPath 41 0 34 SetMarkerPath 41 1 35 SetGoal 42 16 SetZone 42 9 SetMarkerPath 42 0 51 SetGoal 44 17 SetZone 44 10 SetMarkerPath 44 0 45 SetMarkerPath 44 1 106 SetMarkerPath 44 2 107 SetGoal 45 17 SetZone 45 10 SetMarkerPath 45 0 44 SetMarkerPath 45 1 46 SetMarkerPath 45 2 84 SetGoal 46 17 SetZone 46 10 SetMarkerPath 46 0 45 SetMarkerPath 46 1 85 SetGoal 47 18 SetZone 47 10 SetMarkerPath 47 0 49 SetMarkerPath 47 1 48 SetGoal 48 18 SetZone 48 10 SetMarkerPath 48 0 47 SetMarkerPath 48 1 106 SetGoal 49 19 SetZone 49 10 SetMarkerPath 49 0 47 SetMarkerPath 49 1 84 SetGoal 50 14 SetZone 50 7 SetMarkerPath 50 0 96 SetMarkerPath 50 1 39 SetZone 51 9 SetMarkerPath 51 0 42 SetMarkerPath 51 1 87 SetMarkerPathFlags 51 1 j SetZone 52 6 SetMarkerPath 52 0 3 SetMarkerPath 52 1 87 SetZone 53 1 SetMarkerPath 53 0 54 SetMarkerPath 53 1 26 SetZone 54 1 SetMarkerPath 54 0 55 SetMarkerPath 54 1 53 SetZone 55 1 SetMarkerPath 55 0 59 SetMarkerPath 55 1 7 SetMarkerPath 55 2 54 SetZone 56 1 SetMarkerPath 56 0 59 SetMarkerPath 56 1 57 SetMarkerPath 56 2 7 SetZone 57 1 SetMarkerPath 57 0 56 SetMarkerPath 57 1 58 SetMarkerPath 57 2 7 SetZone 58 2 SetMarkerPath 58 0 57 SetMarkerPath 58 1 11 SetZone 59 5 SetMarkerPath 59 0 60 SetMarkerPath 59 1 56 SetMarkerPath 59 2 55 SetZone 60 5 SetMarkerPath 60 0 61 SetMarkerPath 60 1 59 SetZone 61 5 SetMarkerPath 61 0 62 SetMarkerPath 61 1 60 SetZone 62 5 SetMarkerPath 62 0 40 SetMarkerPath 62 1 61 SetZone 63 5 SetMarkerPath 63 0 64 SetMarkerPath 63 1 40 SetZone 64 5 SetMarkerPath 64 0 65 SetMarkerPath 64 1 63 SetZone 65 5 SetMarkerPath 65 0 67 SetMarkerPath 65 1 15 SetMarkerPath 65 2 66 SetMarkerPath 65 3 64 SetZone 66 5 SetMarkerPath 66 0 65 SetMarkerPath 66 1 29 SetMarkerPath 66 2 30 SetZone 67 4 SetMarkerPath 67 0 68 SetMarkerPath 67 1 65 SetZone 68 4 SetMarkerPath 68 0 12 SetMarkerPath 68 1 67 SetZone 69 4 SetMarkerPath 69 0 12 SetMarkerPath 69 1 70 SetZone 70 4 SetMarkerPath 70 0 69 SetMarkerPath 70 1 6 SetZone 71 4 SetMarkerPath 71 0 72 SetMarkerPath 71 1 12 SetZone 72 4 SetMarkerPath 72 0 73 SetMarkerPath 72 1 71 SetZone 73 3 SetMarkerPath 73 0 74 SetMarkerPath 73 1 72 SetZone 74 3 SetMarkerPath 74 0 75 SetMarkerPath 74 1 105 SetMarkerPath 74 2 73 SetZone 75 3 SetMarkerPath 75 0 74 SetMarkerPath 75 1 76 SetMarkerPath 75 2 105 SetZone 76 3 SetMarkerPath 76 0 21 SetMarkerPath 76 1 75 SetZone 77 3 SetMarkerPath 77 0 32 SetMarkerPath 77 1 21 SetZone 78 3 SetMarkerPath 78 0 19 SetMarkerPath 78 1 31 SetZone 79 2 SetMarkerPath 79 0 13 SetMarkerPath 79 1 27 SetZone 80 2 SetMarkerPath 80 0 81 SetMarkerPath 80 1 13 SetZone 81 2 SetMarkerPath 81 0 82 SetMarkerPath 81 1 80 SetZone 82 2 SetMarkerPath 82 0 11 SetMarkerPath 82 1 81 SetZone 83 10 SetMarkerPath 83 0 75 SetMarkerPathFlags 83 0 j SetMarkerPath 83 1 49 SetMarkerPath 83 2 84 SetMarkerPath 83 3 107 SetZone 84 10 SetMarkerPath 84 0 86 SetMarkerPath 84 1 83 SetMarkerPath 84 2 107 SetZone 85 10 SetMarkerPath 85 0 74 SetMarkerPathFlags 85 0 j SetMarkerPath 85 1 46 SetMarkerPath 85 2 86 SetMarkerPath 85 3 84 SetMarkerPath 85 4 107 SetZone 86 10 SetMarkerPath 86 0 85 SetMarkerPath 86 1 84 SetMarkerPath 86 2 105 SetMarkerPathFlags 86 2 j SetZone 87 6 SetMarkerPath 87 0 52 SetMarkerPath 87 1 88 SetMarkerPath 87 2 38 SetZone 88 6 SetMarkerPath 88 0 87 SetMarkerPath 88 1 89 SetZone 89 6 SetMarkerPath 89 0 88 SetMarkerPath 89 1 90 SetZone 90 7 SetMarkerPath 90 0 89 SetMarkerPath 90 1 91 SetZone 91 7 SetMarkerPath 91 0 90 SetMarkerPath 91 1 92 SetZone 92 7 SetMarkerPath 92 0 91 SetMarkerPath 92 1 10 SetMarkerPath 92 2 93 SetZone 93 7 SetMarkerPath 93 0 92 SetMarkerPath 93 1 94 SetZone 94 7 SetMarkerPath 94 0 93 SetMarkerPath 94 1 95 SetZone 95 7 SetMarkerPath 95 0 96 SetMarkerPath 95 1 94 SetMarkerPath 95 2 97 SetZone 96 7 SetMarkerPath 96 0 95 SetMarkerPath 96 1 50 SetMarkerPath 96 2 36 SetMarkerPath 96 3 22 SetMarkerPath 96 4 5 SetZone 97 7 SetMarkerPath 97 0 98 SetMarkerPath 97 1 95 SetMarkerPath 97 2 99 SetZone 98 7 SetMarkerPath 98 0 22 SetMarkerPath 98 1 97 SetZone 99 8 SetMarkerPath 99 0 97 SetMarkerPath 99 1 100 SetZone 100 8 SetMarkerPath 100 0 99 SetMarkerPath 100 1 101 SetZone 101 10 SetMarkerPath 101 0 86 SetMarkerPathFlags 101 0 j SetMarkerPath 101 1 100 SetMarkerPath 101 2 102 SetMarkerPath 101 3 20 SetMarkerPathFlags 101 3 j SetZone 102 8 SetMarkerPath 102 0 101 SetMarkerPath 102 1 8 SetZone 103 8 SetMarkerPath 103 0 8 SetMarkerPath 103 1 16 SetZone 104 8 SetMarkerPath 104 0 16 SetMarkerPath 104 1 1 SetZone 105 4 SetMarkerPath 105 0 74 SetMarkerPath 105 1 75 SetMarkerPath 105 2 2 SetZone 106 10 SetMarkerPath 106 0 75 SetMarkerPathFlags 106 0 j SetMarkerPath 106 1 74 SetMarkerPathFlags 106 1 j SetMarkerPath 106 2 44 SetMarkerPath 106 3 48 SetMarkerPath 106 4 107 SetZone 107 10 SetMarkerPath 107 0 106 SetMarkerPath 107 1 84 SetMarkerPath 107 2 83 SetMarkerPath 107 3 44 SetMarkerPath 107 4 85 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm5.bot000066400000000000000000000136131475442401000261730ustar00rootroot00000000000000CreateMarker 98 210 24 CreateMarker -160 45 24 CreateMarker -287 290 24 CreateMarker -134 253 24 CreateMarker -376 446 24 CreateMarker -468 414 72 CreateMarker -478 211 88 CreateMarker -456 73 88 CreateMarker 100 393 24 CreateMarker 103 687 88 CreateMarker -93 694 88 CreateMarker 245 708 88 CreateMarker 478 573 88 CreateMarker 460 380 134 CreateMarker 440 155 203 CreateMarker 449 -22 216 CreateMarker 132 -177 216 CreateMarker -25 -307 216 CreateMarker -127 -317 242 CreateMarker -308 -228 280 CreateMarker -316 14 280 CreateMarker -478 168 280 CreateMarker -245 436 280 CreateMarker -311 573 280 CreateMarker -505 634 280 CreateMarker -530 816 280 CreateMarker -430 978 280 CreateMarker -171 1030 280 CreateMarker -28 1028 280 CreateMarker 98 867 280 CreateMarker 90 516 280 CreateMarker -401 768 88 CreateMarker -365 941 24 CreateMarker -627 199 280 CreateMarker -251 1157 280 SetZone 1 1 SetMarkerViewOfs 1 -7 SetMarkerPath 1 0 71 SetZone 2 1 SetMarkerPath 2 0 1 SetZone 3 5 SetMarkerPath 3 0 4 SetZone 4 5 SetMarkerPath 4 0 3 SetMarkerPath 4 1 72 SetZone 5 5 SetMarkerPath 5 0 18 SetMarkerPath 5 1 31 SetZone 6 3 SetMarkerViewOfs 6 -6 SetMarkerPath 6 0 53 SetZone 7 2 SetMarkerPath 7 0 13 SetMarkerPath 7 1 59 SetZone 8 5 SetMarkerViewOfs 8 17 SetMarkerPath 8 0 14 SetMarkerPath 8 1 69 SetZone 9 3 SetMarkerViewOfs 9 17 SetMarkerPath 9 0 27 SetMarkerPath 9 1 55 SetGoal 10 3 SetZone 10 3 SetMarkerPath 10 0 19 SetMarkerPath 10 1 53 SetMarkerPath 10 2 54 SetMarkerPath 10 3 39 SetMarkerPathFlags 10 3 j SetGoal 11 1 SetZone 11 6 SetMarkerPath 11 0 68 SetMarkerPath 11 1 10 SetMarkerPathFlags 11 1 j SetMarkerPath 11 2 39 SetMarkerPathFlags 11 2 j SetGoal 12 2 SetZone 12 1 SetMarkerPath 12 0 45 SetMarkerPath 12 1 30 SetGoal 13 21 SetZone 13 2 SetMarkerPath 13 0 58 SetMarkerPath 13 1 7 SetMarkerPath 13 2 59 SetMarkerPath 13 3 36 SetMarkerPath 13 4 37 SetMarkerPath 13 5 60 SetGoal 14 4 SetZone 14 5 SetMarkerPath 14 0 48 SetMarkerPath 14 1 21 SetMarkerPath 14 2 69 SetMarkerPath 14 3 8 SetGoal 15 7 SetZone 15 5 SetMarkerPath 15 0 48 SetMarkerPath 15 1 16 SetGoal 16 7 SetZone 16 5 SetMarkerPath 16 0 15 SetMarkerPath 16 1 21 SetGoal 17 14 SetZone 17 2 SetMarkerPath 17 0 36 SetMarkerPath 17 1 37 SetGoal 18 5 SetZone 18 5 SetMarkerPath 18 0 70 SetMarkerPath 18 1 5 SetMarkerPath 18 2 4 SetGoal 19 6 SetZone 19 3 SetMarkerPath 19 0 20 SetMarkerPath 19 1 10 SetGoal 20 6 SetZone 20 3 SetMarkerPath 20 0 53 SetMarkerPath 20 1 19 SetGoal 21 7 SetZone 21 5 SetMarkerPath 21 0 16 SetMarkerPath 21 1 14 SetMarkerPath 21 2 18 SetMarkerPathFlags 21 2 j SetGoal 23 8 SetZone 23 7 SetMarkerPath 23 0 4 SetGoal 24 9 SetZone 24 6 SetMarkerPath 24 0 70 SetMarkerPathFlags 24 0 j SetGoal 25 22 SetZone 25 1 SetMarkerPath 25 0 28 SetMarkerPath 25 1 26 SetMarkerPath 25 2 39 SetGoal 26 23 SetZone 26 1 SetMarkerPath 26 0 25 SetMarkerPath 26 1 38 SetGoal 27 10 SetZone 27 3 SetMarkerPath 27 0 54 SetMarkerPath 27 1 9 SetZone 28 1 SetMarkerViewOfs 28 17 SetMarkerPath 28 0 25 SetMarkerPath 28 1 39 SetGoal 29 11 SetZone 29 4 SetMarkerPath 29 0 49 SetMarkerPath 29 1 50 SetZone 30 1 SetMarkerPath 30 0 12 SetMarkerPath 30 1 6 SetZone 31 2 SetMarkerViewOfs 31 -6 SetMarkerPath 31 0 56 SetMarkerPath 31 1 57 SetGoal 32 20 SetZone 32 6 SetMarkerPath 32 0 67 SetMarkerPath 32 1 35 SetGoal 33 12 SetZone 33 6 SetMarkerPath 33 0 34 SetMarkerPath 33 1 67 SetZone 34 6 SetMarkerPath 34 0 66 SetMarkerPath 34 1 33 SetGoal 35 23 SetZone 35 6 SetMarkerPath 35 0 32 SetMarkerPath 35 1 68 SetGoal 36 13 SetZone 36 2 SetMarkerPath 36 0 13 SetMarkerPath 36 1 17 SetGoal 37 14 SetZone 37 2 SetMarkerPath 37 0 17 SetMarkerPath 37 1 13 SetZone 38 1 SetMarkerPath 38 0 26 SetMarkerPath 38 1 46 SetMarkerPath 38 2 41 SetZone 39 1 SetMarkerPath 39 0 41 SetMarkerPath 39 1 25 SetZone 40 1 SetMarkerPath 40 0 41 SetMarkerPath 40 1 42 SetZone 41 1 SetMarkerPath 41 0 38 SetMarkerPath 41 1 39 SetMarkerPath 41 2 40 SetZone 42 1 SetMarkerPath 42 0 40 SetMarkerPath 42 1 43 SetZone 43 1 SetMarkerPath 43 0 42 SetMarkerPath 43 1 44 SetZone 44 1 SetMarkerPath 44 0 43 SetMarkerPath 44 1 2 SetMarkerPath 44 2 45 SetZone 45 1 SetMarkerPath 45 0 44 SetMarkerPath 45 1 12 SetZone 46 1 SetMarkerPath 46 0 38 SetMarkerPath 46 1 47 SetZone 47 4 SetMarkerPath 47 0 46 SetMarkerPath 47 1 49 SetMarkerPath 47 2 48 SetZone 48 4 SetMarkerPath 48 0 47 SetMarkerPath 48 1 14 SetMarkerPath 48 2 15 SetZone 49 4 SetMarkerPath 49 0 47 SetMarkerPath 49 1 29 SetZone 50 4 SetMarkerPath 50 0 29 SetMarkerPath 50 1 51 SetZone 51 4 SetMarkerPath 51 0 50 SetMarkerPath 51 1 52 SetZone 52 3 SetMarkerPath 52 0 51 SetMarkerPath 52 1 53 SetZone 53 3 SetMarkerPath 53 0 52 SetMarkerPath 53 1 6 SetMarkerPath 53 2 20 SetMarkerPath 53 3 10 SetZone 54 3 SetMarkerPath 54 0 10 SetMarkerPath 54 1 55 SetMarkerPath 54 2 27 SetZone 55 3 SetMarkerPath 55 0 54 SetMarkerPath 55 1 9 SetMarkerPath 55 2 56 SetZone 56 3 SetMarkerPath 56 0 55 SetMarkerPath 56 1 31 SetMarkerPath 56 2 57 SetZone 57 2 SetMarkerPath 57 0 31 SetMarkerPath 57 1 56 SetMarkerPath 57 2 58 SetZone 58 2 SetMarkerPath 58 0 59 SetMarkerPath 58 1 13 SetMarkerPath 58 2 57 SetMarkerPath 58 3 10 SetMarkerPathFlags 58 3 j SetMarkerPath 58 4 38 SetMarkerPathFlags 58 4 j SetZone 59 2 SetMarkerPath 59 0 58 SetMarkerPath 59 1 7 SetMarkerPath 59 2 13 SetZone 60 2 SetMarkerPath 60 0 13 SetMarkerPath 60 1 61 SetZone 61 6 SetMarkerPath 61 0 60 SetMarkerPath 61 1 62 SetZone 62 6 SetMarkerPath 62 0 61 SetMarkerPath 62 1 63 SetZone 63 6 SetMarkerPath 63 0 62 SetMarkerPath 63 1 64 SetZone 64 6 SetMarkerPath 64 0 63 SetMarkerPath 64 1 65 SetZone 65 6 SetMarkerPath 65 0 64 SetMarkerPath 65 1 66 SetMarkerPath 65 2 24 SetMarkerPathFlags 65 2 j SetZone 66 6 SetMarkerPath 66 0 34 SetMarkerPath 66 1 65 SetZone 67 6 SetMarkerPath 67 0 33 SetMarkerPath 67 1 66 SetMarkerPath 67 2 32 SetZone 68 6 SetMarkerPath 68 0 35 SetMarkerPath 68 1 11 SetZone 69 5 SetMarkerPath 69 0 14 SetMarkerPath 69 1 8 SetMarkerPath 69 2 70 SetZone 70 5 SetMarkerPath 70 0 69 SetMarkerPath 70 1 18 SetZone 71 2 SetMarkerPath 71 0 59 SetZone 72 6 SetMarkerPath 72 0 65 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/bots/maps/ztndm6.bot000066400000000000000000000177621475442401000262050ustar00rootroot00000000000000CreateMarker 701 755 24 CreateMarker 702 463 24 CreateMarker 869 624 -152 CreateMarker 697 1033 24 CreateMarker 716 167 24 CreateMarker 581 1112 24 CreateMarker 378 893 40 CreateMarker 373 740 88 CreateMarker 74 602 88 CreateMarker -72 295 88 CreateMarker -255 473 40 CreateMarker -661 407 24 CreateMarker -625 26 24 CreateMarker -407 -36 24 CreateMarker -432 84 -136 CreateMarker -189 135 24 CreateMarker 4 113 24 CreateMarker 593 80 24 CreateMarker 206 -120 24 CreateMarker 270 -190 -40 CreateMarker 421 -23 -136 CreateMarker 364 108 -168 CreateMarker 410 288 -168 CreateMarker 245 423 -168 CreateMarker 119 656 -168 CreateMarker 5 743 -136 CreateMarker -191 893 -136 CreateMarker 203 1086 24 CreateMarker -657 -125 24 CreateMarker -674 374 -616 CreateMarker 416 -160 -88 SetGoal 1 1 SetZone 1 1 SetMarkerPath 1 0 63 SetMarkerPath 1 1 23 SetMarkerPath 1 2 16 SetGoal 2 2 SetZone 2 1 SetMarkerPath 2 0 62 SetMarkerPathFlags 2 0 j SetMarkerPath 2 1 1 SetMarkerPathFlags 2 1 j SetMarkerPath 2 2 61 SetMarkerPathFlags 2 2 j SetZone 3 1 SetMarkerPath 3 0 63 SetMarkerPath 3 1 40 SetZone 4 5 SetMarkerPath 4 0 5 SetMarkerPath 4 1 89 SetZone 5 5 SetMarkerPath 5 0 12 SetMarkerPath 5 1 4 SetZone 6 7 SetMarkerPath 6 0 7 SetMarkerPath 6 1 9 SetZone 7 7 SetMarkerViewOfs 7 -2 SetMarkerPath 7 0 22 SetMarkerPath 7 1 71 SetMarkerPath 7 2 6 SetZone 8 4 SetMarkerPath 8 0 7 SetZone 9 4 SetMarkerViewOfs 9 -2 SetMarkerPath 9 0 83 SetMarkerPath 9 1 8 SetGoal 10 3 SetZone 10 5 SetMarkerPath 10 0 73 SetMarkerPathFlags 10 0 j SetMarkerPath 10 1 74 SetMarkerPathFlags 10 1 j SetMarkerPath 10 2 75 SetMarkerPathFlags 10 2 j SetGoal 11 21 SetZone 11 5 SetMarkerPath 11 0 75 SetMarkerPath 11 1 13 SetGoal 12 24 SetZone 12 5 SetMarkerPath 12 0 13 SetMarkerPath 12 1 5 SetGoal 13 24 SetZone 13 5 SetMarkerPath 13 0 11 SetMarkerPath 13 1 12 SetGoal 16 14 SetZone 16 1 SetMarkerPath 16 0 1 SetMarkerPath 16 1 23 SetGoal 17 4 SetZone 17 2 SetMarkerPath 17 0 41 SetMarkerPath 17 1 31 SetMarkerPath 17 2 69 SetGoal 18 5 SetZone 18 4 SetMarkerPath 18 0 20 SetMarkerPath 18 1 19 SetMarkerPath 18 2 28 SetGoal 19 19 SetZone 19 4 SetMarkerPath 19 0 20 SetMarkerPath 19 1 18 SetMarkerPath 19 2 83 SetMarkerPath 19 3 84 SetGoal 20 19 SetZone 20 4 SetMarkerPath 20 0 82 SetMarkerPath 20 1 19 SetMarkerPath 20 2 18 SetGoal 21 6 SetZone 21 2 SetMarkerPath 21 0 68 SetMarkerPath 21 1 29 SetMarkerPath 21 2 41 SetMarkerPath 21 3 69 SetGoal 22 7 SetZone 22 7 SetMarkerPath 22 0 71 SetMarkerPath 22 1 25 SetMarkerPath 22 2 24 SetMarkerPath 22 3 7 SetMarkerPath 22 4 36 SetGoal 23 14 SetZone 23 1 SetMarkerPath 23 0 1 SetMarkerPath 23 1 16 SetGoal 24 8 SetZone 24 7 SetMarkerPath 24 0 25 SetMarkerPath 24 1 22 SetMarkerPath 24 2 36 SetMarkerPath 24 3 72 SetGoal 25 8 SetZone 25 7 SetMarkerPath 25 0 71 SetMarkerPath 25 1 22 SetMarkerPath 25 2 24 SetGoal 26 9 SetZone 26 4 SetMarkerPath 26 0 28 SetMarkerPath 26 1 27 SetGoal 27 9 SetZone 27 4 SetMarkerPath 27 0 28 SetMarkerPath 27 1 26 SetGoal 28 10 SetZone 28 4 SetMarkerPath 28 0 18 SetMarkerPath 28 1 84 SetMarkerPath 28 2 85 SetMarkerPath 28 3 27 SetMarkerPath 28 4 26 SetGoal 29 11 SetZone 29 2 SetMarkerPath 29 0 21 SetMarkerPath 29 1 68 SetGoal 30 12 SetZone 30 6 SetMarkerPath 30 0 77 SetMarkerPath 30 1 46 SetMarkerPath 30 2 79 SetGoal 31 4 SetZone 31 2 SetMarkerPath 31 0 17 SetMarkerPath 31 1 39 SetMarkerPath 31 2 69 SetGoal 32 13 SetZone 32 7 SetMarkerPath 32 0 70 SetMarkerPath 32 1 71 SetGoal 33 20 SetZone 33 3 SetMarkerPath 33 0 87 SetMarkerPath 33 1 35 SetMarkerPath 33 2 34 SetMarkerPath 33 3 43 SetMarkerPath 33 4 45 SetGoal 34 23 SetZone 34 3 SetMarkerPath 34 0 35 SetMarkerPath 34 1 43 SetMarkerPath 34 2 33 SetGoal 35 23 SetZone 35 3 SetMarkerPath 35 0 87 SetMarkerPath 35 1 34 SetMarkerPath 35 2 33 SetZone 36 7 SetMarkerPath 36 0 22 SetMarkerPath 36 1 24 SetMarkerPath 36 2 72 SetZone 37 6 SetMarkerViewOfs 37 17 SetMarkerPath 37 0 46 SetMarkerPath 37 1 78 SetZone 38 5 SetMarkerPath 38 0 75 SetMarkerPath 38 1 59 SetZone 39 2 SetMarkerViewOfs 39 17 SetMarkerPath 39 0 31 SetMarkerPath 39 1 47 SetMarkerPath 39 2 69 SetZone 40 3 SetMarkerViewOfs 40 -10 SetMarkerPath 40 0 86 SetMarkerPath 40 1 87 SetGoal 41 4 SetZone 41 2 SetMarkerPath 41 0 17 SetMarkerPath 41 1 21 SetMarkerPath 41 2 68 SetZone 42 3 SetMarkerPath 42 0 45 SetMarkerPath 42 1 88 SetZone 43 3 SetMarkerViewOfs 43 17 SetMarkerPath 43 0 34 SetMarkerPath 43 1 33 SetMarkerPath 43 2 45 SetGoal 44 15 SetZone 44 8 SetMarkerPath 44 0 88 SetZone 45 3 SetMarkerPath 45 0 33 SetMarkerPath 45 1 43 SetMarkerPath 45 2 42 SetGoal 46 16 SetZone 46 6 SetMarkerPath 46 0 30 SetMarkerPath 46 1 77 SetMarkerPath 46 2 37 SetMarkerPath 46 3 79 SetGoal 47 23 SetZone 47 2 SetMarkerPath 47 0 39 SetMarkerPath 47 1 48 SetMarkerPath 47 2 69 SetGoal 48 19 SetZone 48 2 SetMarkerPath 48 0 47 SetMarkerPath 48 1 69 SetMarkerPath 48 2 70 SetZone 49 5 SetMarkerPath 49 0 74 SetMarkerPath 49 1 76 SetZone 50 9 SetMarkerPath 50 0 58 SetZone 51 9 SetMarkerViewOfs 51 -10 SetMarkerPath 51 0 90 SetGoal 52 17 SetZone 52 9 SetMarkerPath 52 0 90 SetGoal 53 17 SetZone 53 9 SetMarkerPath 53 0 90 SetGoal 54 17 SetZone 54 9 SetMarkerPath 54 0 90 SetGoal 55 17 SetZone 55 9 SetMarkerPath 55 0 90 SetGoal 56 17 SetZone 56 9 SetMarkerPath 56 0 90 SetZone 57 7 SetMarkerViewOfs 57 -2 SetMarkerPath 57 0 51 SetZone 58 2 SetMarkerViewOfs 58 -10 SetMarkerPath 58 0 66 SetMarkerPath 58 1 67 SetMarkerPath 58 2 88 SetZone 59 5 SetMarkerViewOfs 59 -10 SetMarkerPath 59 0 38 SetZone 60 1 SetMarkerViewOfs 60 33 SetMarkerPath 60 0 59 SetZone 61 1 SetMarkerPath 61 0 1 SetMarkerPathFlags 61 0 j SetMarkerPath 61 1 2 SetMarkerPathFlags 61 1 j SetMarkerPath 61 2 62 SetMarkerPathFlags 61 2 j SetMarkerPath 61 3 64 SetZone 62 1 SetMarkerPath 62 0 65 SetMarkerPath 62 1 2 SetMarkerPathFlags 62 1 j SetMarkerPath 62 2 1 SetMarkerPathFlags 62 2 j SetMarkerPath 62 3 61 SetMarkerPathFlags 62 3 j SetZone 63 1 SetMarkerPath 63 0 1 SetMarkerPath 63 1 3 SetZone 64 1 SetMarkerPath 64 0 61 SetMarkerPath 64 1 66 SetZone 65 6 SetMarkerPath 65 0 62 SetMarkerPath 65 1 78 SetZone 66 2 SetMarkerPath 66 0 64 SetMarkerPath 66 1 58 SetZone 67 2 SetMarkerPath 67 0 58 SetMarkerPath 67 1 68 SetZone 68 2 SetMarkerPath 68 0 67 SetMarkerPath 68 1 21 SetMarkerPath 68 2 29 SetMarkerPath 68 3 41 SetZone 69 2 SetMarkerPath 69 0 17 SetMarkerPath 69 1 31 SetMarkerPath 69 2 39 SetMarkerPath 69 3 47 SetMarkerPath 69 4 48 SetMarkerPath 69 5 21 SetZone 70 7 SetMarkerPath 70 0 48 SetMarkerPath 70 1 69 SetMarkerPath 70 2 32 SetZone 71 7 SetMarkerPath 71 0 32 SetMarkerPath 71 1 25 SetMarkerPath 71 2 22 SetMarkerPath 71 3 7 SetZone 72 7 SetMarkerPath 72 0 36 SetMarkerPath 72 1 24 SetMarkerPath 72 2 73 SetZone 73 5 SetMarkerPath 73 0 74 SetMarkerPath 73 1 72 SetMarkerPath 73 2 10 SetMarkerPath 73 3 89 SetMarkerPath 73 4 75 SetMarkerPathFlags 73 4 j SetZone 74 5 SetMarkerPath 74 0 73 SetMarkerPath 74 1 10 SetMarkerPathFlags 74 1 j SetMarkerPath 74 2 49 SetMarkerPath 74 3 89 SetZone 75 5 SetMarkerPath 75 0 11 SetMarkerPath 75 1 38 SetZone 76 6 SetMarkerPath 76 0 49 SetMarkerPath 76 1 77 SetZone 77 6 SetMarkerPath 77 0 76 SetMarkerPath 77 1 30 SetMarkerPath 77 2 46 SetZone 78 6 SetMarkerPath 78 0 65 SetMarkerPath 78 1 37 SetZone 79 6 SetMarkerPath 79 0 30 SetMarkerPath 79 1 46 SetMarkerPath 79 2 80 SetZone 80 6 SetMarkerPath 80 0 79 SetMarkerPath 80 1 91 SetZone 81 6 SetMarkerPath 81 0 91 SetMarkerPath 81 1 82 SetZone 82 6 SetMarkerPath 82 0 81 SetMarkerPath 82 1 20 SetMarkerPath 82 2 83 SetZone 83 4 SetMarkerPath 83 0 82 SetMarkerPath 83 1 19 SetMarkerPath 83 3 9 SetMarkerPath 83 4 84 SetZone 84 4 SetMarkerPath 84 0 19 SetMarkerPath 84 1 83 SetMarkerPath 84 2 28 SetMarkerPath 84 3 85 SetZone 85 4 SetMarkerPath 85 0 28 SetMarkerPath 85 1 84 SetMarkerPath 85 2 86 SetZone 86 3 SetMarkerPath 86 0 85 SetMarkerPath 86 1 40 SetZone 87 3 SetMarkerPath 87 0 40 SetMarkerPath 87 1 35 SetMarkerPath 87 2 33 SetZone 88 3 SetMarkerPath 88 0 42 SetMarkerPath 88 1 58 SetZone 89 5 SetMarkerPath 89 0 4 SetMarkerPath 89 1 74 SetMarkerPath 89 2 73 SetZone 90 9 SetMarkerPath 90 0 52 SetMarkerPath 90 1 54 SetMarkerPath 90 2 53 SetMarkerPath 90 3 55 SetMarkerPath 90 4 56 SetMarkerPath 90 5 51 SetZone 91 6 SetMarkerPath 91 0 81 SetMarkerPath 91 1 80 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/000077500000000000000000000000001475442401000237615ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/reset.cfg000066400000000000000000000000171475442401000255620ustar00rootroot00000000000000exec server.cfgQW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/000077500000000000000000000000001475442401000257675ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/10on10/000077500000000000000000000000001475442401000267055ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/10on10/default.cfg000066400000000000000000000000001475442401000310000ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/1on1/000077500000000000000000000000001475442401000265455ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/1on1/default.cfg000066400000000000000000000000511475442401000306460ustar00rootroot00000000000000set k_idletime 60 // 60 seconds idlebot QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/1on1/ra/000077500000000000000000000000001475442401000271475ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/1on1/ra/default.cfg000066400000000000000000000001741475442401000312560ustar00rootroot00000000000000timelimit 0 fraglimit 10 set k_mode 1 set k_rocketarena 1 set k_lockmode 0 set k_exclusive 0 set k_spectalk 1 maxclients 10 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2/000077500000000000000000000000001475442401000265475ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2/aerowalk.cfg000066400000000000000000000000241475442401000310310ustar00rootroot00000000000000set add_q_aerowalk 1QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2/default.cfg000066400000000000000000000000001475442401000306420ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2/dm4.cfg000066400000000000000000000000141475442401000277070ustar00rootroot00000000000000set k_pow 0 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2/dm6.cfg000066400000000000000000000000131475442401000277100ustar00rootroot00000000000000set k_pow 0QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2on2/000077500000000000000000000000001475442401000271665ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/2on2on2/default.cfg000066400000000000000000000000001475442401000312610ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/3on3/000077500000000000000000000000001475442401000265515ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/3on3/default.cfg000066400000000000000000000000001475442401000306440ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/3on3on3/000077500000000000000000000000001475442401000271715ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/3on3on3/default.cfg000066400000000000000000000000001475442401000312640ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/4on4/000077500000000000000000000000001475442401000265535ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/4on4/default.cfg000066400000000000000000000000001475442401000306460ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/4on4on4/000077500000000000000000000000001475442401000271745ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/4on4on4/default.cfg000066400000000000000000000000001475442401000312670ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/XonX/000077500000000000000000000000001475442401000266635ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/XonX/default.cfg000066400000000000000000000000001475442401000307560ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/amphi.cfg000066400000000000000000000001751475442401000275510ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/amphi2.cfg000066400000000000000000000001751475442401000276330ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/aqui.cfg000066400000000000000000000000511475442401000274030ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/arena3.cfg000066400000000000000000000000511475442401000276150ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ca/000077500000000000000000000000001475442401000263525ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ca/default.cfg000066400000000000000000000000741475442401000304600ustar00rootroot00000000000000// add Clan Arena specific configuration here maxclients 20 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ctf/000077500000000000000000000000001475442401000265435ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ctf/default.cfg000066400000000000000000000000471475442401000306510ustar00rootroot00000000000000// add CTF specific configuration here QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ctf/qwq3wcp9.cfg000066400000000000000000000006311475442401000307220ustar00rootroot00000000000000// qwq3wcp9 was mapped in the mind that players should spawn on bases, so k_ctf_based_spawn is a MUST. set k_ctf_based_spawn 1 // No need for hook on that map. set k_ctf_hook 0 // Runes are way too powerful ATM and they spawn on info_player_deathmatch which present only on the RED base, nice? // Actually I fixed runes and they spawns on the bases with k_ctf_based_spawn 1 now, if enabled. set k_ctf_runes 0 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/default.cfg000066400000000000000000000001401475442401000300670ustar00rootroot00000000000000set k_spm_show 0 // do not show spawn markers set k_spm_glow 0 // spawn markers do not glow QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dm2dmm4.cfg000066400000000000000000000001751475442401000277170ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dm2dmm4_2.cfg000066400000000000000000000001751475442401000301400ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_1.cfg000066400000000000000000000000511475442401000275250ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_2.cfg000066400000000000000000000000511475442401000275260ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_3.cfg000066400000000000000000000000511475442401000275270ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_4.cfg000066400000000000000000000000511475442401000275300ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_5.cfg000066400000000000000000000000511475442401000275310ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_6.cfg000066400000000000000000000000511475442401000275320ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_7.cfg000066400000000000000000000000511475442401000275330ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_8.cfg000066400000000000000000000000511475442401000275340ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/dmm4_9.cfg000066400000000000000000000000511475442401000275350ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/end.cfg000066400000000000000000000001751475442401000272210ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/end2.cfg000066400000000000000000000001751475442401000273030ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/endif.cfg000066400000000000000000000000701475442401000275320ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_midair 1QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ffa/000077500000000000000000000000001475442401000265235ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/ffa/default.cfg000066400000000000000000000001241475442401000306250ustar00rootroot00000000000000timelimit 20 teamplay 0 deathmatch 3 set k_overtime 2 set k_pow 1 set k_idletime 180QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/hammer.cfg000066400000000000000000000001161475442401000277170ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/hammerv2.cfg000066400000000000000000000000511475442401000301650ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/hammerv3.cfg000066400000000000000000000000511475442401000301660ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/000077500000000000000000000000001475442401000277525ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/arena3.cfg000066400000000000000000000000571475442401000316060ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/arena5.cfg000066400000000000000000000000571475442401000316100ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/barrel.cfg000066400000000000000000000000571475442401000317040ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/bloodfest.cfg000066400000000000000000000004201475442401000324100ustar00rootroot00000000000000set k_bloodfest 1 set deathmatch 0 set coop 1 set k_pow_q 1 set k_pow_p 0 set k_pow_r 0 set k_pow_s 0 set skill 3 set k_nightmare_pu 1 set k_nightmare_pu_droprate 0.04 // so trigger_custom_monsterjump working right with high speed. sv_maxvelocity 9999 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/ctf.cfg000066400000000000000000000022701475442401000312100ustar00rootroot00000000000000samelevel 0 set k_mode 4 set k_matchless_countdown 0 set k_pow_min_players 4 set k_pow_check_time 10 set k_no_vote_map 0 set k_no_vote_break 0 timelimit 10 set k_spectalk 1 // spectators can talk to players during game (0 = no, 1 = yes) set k_allowvoteadmin 1 set k_admins 1 watervis 1 // turn on watervis for CTF k_ctf_runes 1 // allow runes k_ctf_hook 1 // allow hook k_ctf_hookstyle 1 // default hook style - 1: smooth, 2: fast, 3: classic k_ctf_based_spawn 0 // pm_airstep 0 // turn off jumping up stairs k_spw 1 // KT spawnsafety sv_loadentfiles 1 // load CTF-specific .ent files for id maps sv_loadentfiles_dir "ctf" set k_lockmode 0 // number of players gets locked on game start (0 =no, 1=yes) set k_lockmax 32 // map rotation set k_defmap "e2m2" set k_ml_0 "e2m2" set k_ml_1 "e1m5" set k_ml_2 "e1m3" set k_ml_3 "e2m5 set k_ml_4 "e1m4 set k_ml_5 "e3m3 // make sure you have the following: //set k_ml_6 "ctf2m3" //set k_ml_7 "ctf2m7" //set k_ml_8 "ctf2m8" //set k_ml_9 "ctf5" //set k_ml_10 "ctf8" //set k_ml_11 "head" //set k_ml_12 "capit" //set k_ml_13 "pound" //set k_ml_14 "gym" //set k_ml_15 "bastard" //set k_ml_16 "softbox" //set k_ml_17 "pigremix" QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/default.cfg000066400000000000000000000027571475442401000320720ustar00rootroot00000000000000// server mode set k_mode 3 // server mode (1 = duel, 2 = team, 3 = ffa, 4 = ctf) // matchless settings set k_matchless_countdown 0 // countdown in matchless mode (0 = off, 1 = on) set k_matchless_max_idle_time 0 // maximum time a user can be idle before being forced to spectator in matchless set k_pow_min_players 1 // number of players on server required for powerups to be turned on set k_pow_check_time 10 // how often should ktx check if the k_pow_min_players requirement has been met (seconds) set k_no_vote_map 0 // allow map voting and /next_map (0 = allow voting, 1 = disallow voting) set k_no_vote_break 1 // allow vote break (0 = allow break, 1 = disallow break) set k_pow 1 // enable powerups (1 = enabled, 0 = disabled) set dq 1 // dropquad (1 = enabled, 0 = disabled) set dr 1 // dropring (1 = enabled, 0 = disabled) // Other settings samelevel 0 // change level after match ends timelimit 10 // round timelimit in minutes maxclients 8 // maximum number of clients to connect set k_specktalk 1 // spectators can talk to players during round // map rotation set k_ml_0 "dm2" set k_ml_1 "dm3" set k_ml_2 "e1m2" //set k_ml_3 "e1m3" // etc set k_random_maplist 0 // select random map from k_ml_XXX variables (0 = off, 1 = on) QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/dm4ish.cfg000066400000000000000000000000571475442401000316250ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/e1m7.cfg000066400000000000000000000000571475442401000312060ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/genocide.cfg000066400000000000000000000000571475442401000322120ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/hohoho.cfg000066400000000000000000000000571475442401000317210ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/kenya.cfg000066400000000000000000000000571475442401000315440ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/q1dm17.cfg000066400000000000000000000000571475442401000314470ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/matchless/slaug.cfg000066400000000000000000000000571475442401000315500ustar00rootroot00000000000000exec configs/usermodes/matchless/bloodfest.cfg QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/nacmidair.cfg000066400000000000000000000000701475442401000303740ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_midair 1QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/noentry.cfg000066400000000000000000000001161475442401000301440ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/oldcrat.cfg000066400000000000000000000001751475442401000301030ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/outpost.cfg000066400000000000000000000001751475442401000301700ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/povdmm4.cfg000066400000000000000000000000511475442401000300320ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/povdmm4a.cfg000066400000000000000000000000511475442401000301730ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/povdmm4b.cfg000066400000000000000000000000511475442401000301740ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/pushdmm4.cfg000066400000000000000000000001751475442401000302140ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/schlossdmm4.cfg000066400000000000000000000001751475442401000307130ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/sewer.cfg000066400000000000000000000001751475442401000276000ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2 set k_disallow_weapons 80 // disallow gl + lg set k_noitems 1 // disable items QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/tearena.cfg000066400000000000000000000000511475442401000300630ustar00rootroot00000000000000timelimit 3 deathmatch 4 set k_overtime 2QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/tot/000077500000000000000000000000001475442401000265755ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/tot/dm4.cfg000066400000000000000000000001321475442401000277360ustar00rootroot00000000000000k_fb_break_on_death 0 k_disallow_weapons 16 set dq 1 set k_pow 1 timelimit 5 deathmatch 4 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/tot/e1m2.cfg000066400000000000000000000001041475442401000300150ustar00rootroot00000000000000k_fb_break_on_death 1 set dq 0 set k_pow 1 timelimit 5 deathmatch 4 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/configs/usermodes/tot/schloss.cfg000066400000000000000000000001041475442401000307270ustar00rootroot00000000000000k_fb_break_on_death 1 set dq 0 set k_pow 1 timelimit 5 deathmatch 4 QW-Group-ktx-d05d6ca/resources/example-configs/ktx/ktx.cfg000066400000000000000000000227321475442401000236260ustar00rootroot00000000000000// server set k_minrate 2500 // minimum rate setting for players/spectators set sv_maxrate 500000 // maximum rate setting for players/spectators set k_noframechecks 0 // disable check for fps/speed manipulation (0 = no, 1 = yes) set k_no_fps_physics 0 // fps independent physics (0 = off, 1 = on) set k_short_gib 1 // remove gibs after 2 seconds (0 = no, 1 = yes) set k_exclusive 1 // number of players gets locked on game start (0 = no, 1 = yes) set k_lockmax 32 // maximum number of teams in game set k_lockmin 0 // minimum number of teams in game set k_membercount 1 // minimum number of players in each team to start match set k_lock_hdp 0 // allow handicap (0 = yes, 1 = no) set k_count 10 // countdown before match starts (seconds) set k_idletime 0 // after how many seconds the idlebot kick players who are not ready (0 = disable) set k_defmap dm3 // server homemap. server will change to this when last player leaves the server // gameplay set k_highspeed 320 // maximum allowed runspeed (cmd speed will switch between this setting and sv_maxspeed) set k_timetop 30 // maximum time in minutes allocateable by a player for a game set k_dm2mod 1 // modified deathmatch 2 mode (0 = standard qw dmm2, 1 = modified dmm2) set k_mode 2 // server mode (1 = duel, 2 = team, 3 = ffa, 4 = ctf) set k_midair 0 // midair (0 = off, 1 = on) set k_spw 4 // spawn mode (0 = qw respawns, 1 = kombat teams spawn safety, 2 = kombat teams respawns, 3 = ktx respawns, 4 = ktx2 respawns) set k_pow 1 // powerups (0 = off, 1 = on) set dq 0 // drop quad (0 = off, 1 = on) set dr 0 // drop ring (0 = off, 1 = on) set dp 1 // drop backpacks (0 = off, 1 = on) set k_dis 1 // discharge (0 = off, 1 = on, 2 = only discharge players in liquid) set k_666 0 // respawn 666 (0 = off, 1 = on) set k_bzk 0 // berzerk (0 = off, 1 = on) set k_btime 20 // berzerk time (seconds) set k_frp 0 // fairpacks (0 = drop equipped weapon, 1 = drop best weapon, 2 = drop last fired weapon) set k_overtime 1 // overtime mode (0 = off, 1 = time, 2 = suddendeath) set k_exttime 5 // overtime length in minutes if k_overtime = 1 set k_fallbunny 1 // fallbunny (0 = off (broken ankle), 1 = on (standard qw behaviour)) set k_disallow_kfjump 1 // kfjump (0 = on, 1 = off) set k_disallow_krjump 1 // krjump (0 = on, 1 = off) set k_teamoverlay 0 // team overlay (0 = disabled, 1 = enabled) set k_classic_shotgun 1 // use precisely shown sg/ssg hits for each pellet fired // matchless mode // qqshka: I commented out k_matchless variable here, // so you can use same quake dir for FFA-matchless server and non matchless server. //set k_matchless 0 // run ktx as a regular match server or as a matchless (ffa) server (0 = regular, 1 = matchless) set k_use_matchless_dir 1 // use configs/usermodes/matchless instead of [...]/ffa (0 = no, 1 = yes) // dmm4 set dmm4_invinc_time 0 // spawn invincibility time for dmm4 in seconds (-1 = disable, 0 = default (2 seconds)) set k_dmm4_gren_mode 0 // grenade explosions (0 = default, 1 = only on direct impact) set k_disallow_weapons 16 // weapons allowed in dmm4 (bit mask): // 1=sg, 2=ssg, 4=ng, 8=sng, 16=gl, 32=rl, 64=lg, 4096=axe // map support set add_q_aerowalk 1 // add quad on aerowalk (0 = no, 1 = yes) set k_end_tele_spawn 0 // remove tele spawn on map end (0 = yes, 1 = no) set k_remove_end_hurt 1 // end modifications (0 = no modifications, 1 = remove hurt and changelevel triggers, 2 = remove hurt trigger) // free modes set k_defmode 4on4 // default mode on server set k_free_mode 5 // who can issue XonX/ffa/ctf commands (0 = noone, 1 = admins, 2 = elected admins, 3 = judges, 4 = elected judges, 5 = all) set k_allowed_free_modes 4095 // allowed free modes (bit mask): // 1=1on1, 2=2on2, 4=3on3, 8=4on4, 16=10on10, 32=ffa, 64=ctf, 128=hoonymode, 256=2on2on2, 512=3on3on3, 1024=4on4on4, 2048=XonX // ctf set k_ctf_custom_models 1 // ctf models (0 = use original quake models, 1 = use ctf models) set k_ctf_hookstyle 1 // hook style (1 = smooth, 2 = fast, 3 = classic) set k_ctf_rune_power_str 2.0 // strength rune power (default is 2) set k_ctf_rune_power_res 2.0 // resistance rune power (default is 2) set k_ctf_rune_power_rgn 2.0 // regeneration rune power (default is 2) set k_ctf_rune_power_hst 2.0 // haste rune power (default is 2) // prewar set k_prewar 1 // prewar setting (0 = prewar fire is disallowed, 1 = prewar fire is allowed, 2 = no fire or jump until ready) set k_sready 0 // players glow when not ready (0 = no, 1 = yes) set k_freeze 0 // freeze platforms and doors before matchstart (0 = no, 1 = yes) // timing players set allow_timing 1 // timing/lagged players manipulation (0 = off, 1 = on) set timing_players_time 2 // how long a player should lag before manipulation starts (seconds) set timing_players_action 3 // timing/lagged players manipulation (bit mask): // 1=info, 2=glow, 4=invincible, 8=autokpause // demo recording set demo_tmp_record 1 // enable mvd-autorecording (0 = off) set demo_skip_ktffa_record 0 // record ffa games (0 = yes, 1 = no) set demo_scoreslength 6 // how many seconds to show score table at end of game set k_demo_mintime 360 // if the game is breaked, save demo if this many seconds has passed set k_demotxt_format "json" // format of stats set k_demoname_date "%Y%m%d-%H%M" // will add date at end of demoname in form of YYYY-MM-DD set k_keepspectalkindemos 0 // enable recording of spectalk in demos (0 = off, 1 = enabled) set k_extralog 0 // enable detailed KTX statistics (0 = no, 1 = yes) // voting set k_allowvoteadmin 1 // allow admin election (0 = no, 1 = yes) set k_lockmap 0 // prevent players from changing map (0 = no, 1 = yes) set k_vp_break 51 // vote percentage for breaking set k_vp_admin 51 // vote percentage for admin election set k_vp_captain 51 // vote percentage for captain election set k_vp_coach 51 // vote percentage for coach election set k_vp_map 51 // vote percentage for map change set k_vp_pickup 51 // vote percentage for pickup set k_vp_rpickup 51 // vote percentage for random pickup set k_vp_nospecs 51 // vote percentage for /nospecs set k_vp_teamoverlay 51 // vote percentage for /teamoverlay set k_vp_coop 51 // vote percentage for cooperative mode aka /votecoop set k_vp_hookstyle 51 // vote percentage for changing grappling hook style in ctf /hookstyle set k_vp_antilag 51 // vote percentage for antilag mode aka /antilag // flood protection set k_fp 1 // floodprot: max X messages per Y seconds, else silence for Z seconds (1 = 9 1 1, 2 = 4 1 5, 3 = 5 3 7) set k_cmd_fp_kick 3 // warnings given before kicking set k_cmd_fp_dontkick 0 // kick command flooders (0 = on, 1 = off) set k_cmd_fp_disabled 0 // flood protection (0 = on, 1 = off) // practice set allow_toggle_practice 5 // toggle practice mode (0 = noone, 1 = admins, 2 = elected admins, 3 = judges, 4 = elected judges, 5 = all) set lock_practice 1 // lock practice mode (0 = unlock on reset, 1 = allow_toggle_practice, 2 = locked) set srv_practice_mode 0 // practice mode (0 = off, 1 = on) // spectators set k_ann 0 // announce spectator join/quits during game (0 = no, 1 = yes) set k_spectalk 0 // spectators can talk to players during game (0 = no, 1 = yes) set k_spec_info 1 // moreinfo (bit mask): // 0=infospec off, 1=infospec on, 2=infolock admins set k_sayteam_to_spec 1 // send say_team to specs (0 = never, 1 = only during game, 2 = only during prewar, 3 = always) set allow_spec_wizard 0 // allow spectator wizards (0 = no, 1 = only when no players are on the server, 2 = only in prewar) set k_no_wizard_animation 0 // wizard animation (0 = on, 1 = off) QW-Group-ktx-d05d6ca/resources/example-configs/ktx/listip.cfg000066400000000000000000000000001475442401000243040ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/matchless.cfg000066400000000000000000000010611475442401000247730ustar00rootroot00000000000000// // This file intended just to simplify enabling matchless mode. // For changing matchless related settings you most likely should look // in configs/usermodes/matchless/default.cfg. // // this must enable matchless mode set k_matchless 1 // run ktx as a regular match server or as a matchless (ffa) server (0 = regular, 1 = matchless) set k_mode 3 // server mode (1 = duel, 2 = team, 3 = ffa, 4 = ctf) set k_use_matchless_dir 1 // use configs/usermodes/matchless instead of [...]/ffa (0 = no, 1 = yes) QW-Group-ktx-d05d6ca/resources/example-configs/ktx/mvdfinish.qws000066400000000000000000000016151475442401000250570ustar00rootroot00000000000000#!/bin/bash # Do you want to use compression? (yes/no) COMPRESS=no # What archiver do you want to use? (gzip, bzip2, zip) ARCHIVER=gzip # Do not touch below this line if you don't know what you are doing. if [ $1 != 0 ] then exit fi # Compression code for gzip/bzip2/zip if [ ${COMPRESS} = yes ] then if [ -f $2/$3.mvd ] then if [ ${ARCHIVER} = gzip ] then tar -czf $2/$3.gz $2/"$3".* fi if [ ${ARCHIVER} = bzip2 ] then tar -cjf $2/$3.bz2 $2/"$3".* fi if [ ${ARCHIVER} = zip ] then zip -9 $2/$3.zip $2/"$3".* fi fi fi # Cleanup code, let's remove .mvd .xml .txt if we compressed it if [ ${COMPRESS} = yes ] then if [ ${ARCHIVER} != gzip ] && [ ${ARCHIVER} != bzip2 ] && [ ${ARCHIVER} != zip ] then exit fi if [ -f $2/$3.mvd ] then rm -f $2/"$3".mvd fi if [ -f $2/$3.xml ] then rm -f $2/"$3".xml fi if [ -f $2/$3.txt ] then rm -f $2/"$3".txt fi fi QW-Group-ktx-d05d6ca/resources/example-configs/ktx/mvdsv.cfg000066400000000000000000000141771475442401000241630ustar00rootroot00000000000000fraglimit 0 // fraglimit timelimit 20 // timelimit teamplay 2 // teamplay deathmatch 1 // deathmatch mode maxclients 8 // maximum clients maxspectators 4 // maximum spectators maxvip_spectators 4 // maximum vip spectators timeout 65 // seconds to wait for zombies pausable 0 // pausable samelevel 1 // same level after match ends floodprot 10 1 1 // flood protection - allow x messages per y seconds, else silence for z seconds floodprotmsg "quiet!" // flood protection message for client sv_antilag 2 // antilag server setting (affect hit scan weapon) (0 = off, 2 = on, 1 is unsupported by KTX) sv_gamedir qw // gamedir sv_maxspeed 320 // maximum player (walking) speed sv_mintic 0.01 // mintic sv_maxtic 0.03 // maxtic sv_loadentfiles 1 // load .ent files (0 = no, 1 = yes) sv_loadentfiles_dir "" // load .ent files from this subdir. sv_getrealip 2 // get real ip (0 = off, 1 = on connect failure, 2 = on failure drop) sv_use_dns 0 // dns lookup (0 = off, 1 = on) sv_hashpasswords 1 // hash account passwords (0 = off, 1 = on) sv_timestamplen 60 // time (seconds) during rcon command which encryption is valid sv_rconlim 3 // limit of rcon requests per second sv_unfake 1 // auto unfake any mm1 messages (0 = no, 1 = yes) sv_kicktop 1 // kick topcolor spammers (0 = no, 1 = yes) sv_speedcheck 1 // anti speed cheat code from AM101, slows cheaters down to normal speed sv_mapcheck 1 // check map checksums (0 = no, 1 = yes) sv_specprint 0 // show spectators some info (1 = centerprint, 2 = sprint, 4 = stuffcmd) sv_reconnectlimit 5 // throttle reconnecting players for x seconds sv_forcespec_onfull 1 // turn connecting players into spectators if the server is full (0 = no, 1 = yes) sv_sayteam_to_spec 0 // send say_team messages to spectators (0 = no, 1 = yes) sv_reliable_sound 0 // reliable sounds channel, prevents missing sounds during PL (0 = off, 1 = on) sys_select_timeout 10000 // timeout in micro seconds for function select in main loop sys_restart_on_error 0 // restart on error (0 = no, 1 = yes) sv_progtype 1 // progtype (0 = .dat, 1 = .so/.dll, 2 = .qvm) sv_progsname qwprogs // name of mod file without extention sv_forcenick 0 // force player name to the name in accounts file (0 = no, 1 = yes) serverinfo fpd 222 // fpd values from qizmo.txt // 1 = disable %-reporting // 2 = disable use of powerup timer // 4 = disable use of soundtrigger // 8 = disable use of lag features // 16 = make qizmo report any changes in lag settins // 32 = silent %e enemy vicinity reporting (reporter doesn't see the message) // 64 = spectators can't talk to players and vice versa (voice) // 128 = silent %x and %y (reporter doesn't see the message) // 256 = disable skin forcing // 512 = disable color forcing serverinfo pm_ktjump 1 // jumpfix (0 = off, 1 = on) set maxfps 77 // maxfps // ktx vip password values (do not change) vip_values "1 8 4 20 12 28" // qtv qtv_maxstreams 1 // maximum amount of qtv proxies to connect directly to the server // mvd recording sv_demoExtraNames 0 // show player names in demo filenames (0 = show team only, 1 = show player names) sv_demotxt 2 // create demo .txt (0 = off, 1 = on, 2 = json) sv_demodir demos // demos directory name sv_maxdownloadrate 100000 // maximum download client rate sv_downloadchunksperframe 4 // increase chunked download speed rate (1=77kB/s, 4=308kB/s) sv_onrecordfinish mvdfinish // name.qws will be started after demo recording is finished sv_demoMaxDirSize 262144 // maximum demos dir size. 4096000=4GB sv_demoClearOld 10 // if total demos size > sv_demoMaxDirSize, this will delete x demos // downloading allow_download 1 // allow downloads from server (0 = no, 1 = yes) allow_download_maps 1 // allow map downloads from server (0 = no, 1 = yes) allow_download_pakmaps 0 // allow pak map downloads from server (0 = no, 1 = yes) allow_download_skins 1 // allow skin downloads from server (0 = no, 1 = yes) allow_download_sounds 1 // allow sound downloads from server (0 = no, 1 = yes) allow_download_models 1 // allow model downloads from server (0 = no, 1 = yes) allow_download_demos 1 // allow demo downloads from server (0 = no, 1 = yes) allow_download_other 0 // allow other downloads from server (0 = no, 1 = yes) // minping sv_minping 0 // minping for server (0 = off) sv_enable_cmd_minping 0 // cmd minping (0 = off, 1 = on) // display this url to people downloading maps from the server download_map_url "http://maps.quakeworld.nu/" QW-Group-ktx-d05d6ca/resources/example-configs/ktx/port1.cfg000066400000000000000000000012461475442401000240620ustar00rootroot00000000000000// hostname hostname "My KTX Server #1" sv_admininfo "my.own@email.here" sv_serverip "192.168.0.1:28001" qtv_streamport 28001 // motd (15 rows) set k_motd1 "My #1 Server" set k_motd2 " " set k_motd3 " " set k_motd4 "Available game modes:" set k_motd5 "1on1, 2on2, 3on3, 4on4 and 10on10" set k_motd6 " " set k_motd7 " " set k_motd8 "Contact:" set k_motd9 "my.own@email.here" set k_motd_time 5 // time motd is displayed in seconds QW-Group-ktx-d05d6ca/resources/example-configs/ktx/port2.cfg000066400000000000000000000012461475442401000240630ustar00rootroot00000000000000// hostname hostname "My KTX Server #2" sv_admininfo "my.own@email.here" sv_serverip "192.168.0.1:28002" qtv_streamport 28002 // motd (15 rows) set k_motd1 "My #2 Server" set k_motd2 " " set k_motd3 " " set k_motd4 "Available game modes:" set k_motd5 "1on1, 2on2, 3on3, 4on4 and 10on10" set k_motd6 " " set k_motd7 " " set k_motd8 "Contact:" set k_motd9 "my.own@email.here" set k_motd_time 5 // time motd is displayed in seconds QW-Group-ktx-d05d6ca/resources/example-configs/ktx/port3.cfg000066400000000000000000000012461475442401000240640ustar00rootroot00000000000000// hostname hostname "My KTX Server #3" sv_admininfo "my.own@email.here" sv_serverip "192.168.0.1:28003" qtv_streamport 28003 // motd (15 rows) set k_motd1 "My #3 Server" set k_motd2 " " set k_motd3 " " set k_motd4 "Available game modes:" set k_motd5 "1on1, 2on2, 3on3, 4on4 and 10on10" set k_motd6 " " set k_motd7 " " set k_motd8 "Contact:" set k_motd9 "my.own@email.here" set k_motd_time 5 // time motd is displayed in seconds QW-Group-ktx-d05d6ca/resources/example-configs/ktx/problem.cfg000066400000000000000000000043171475442401000244570ustar00rootroot00000000000000maxvip_spectators 4 vip_password "none none none none none none" // // PASSWORD BASED VIP // // To use it, the admin has to set the following things: // maxvip_spectators // vip_password - use "none" as pass if you want to disable a specific level! // // The client needs use "password pass" or "spectator pass" if he wants to become a VIP. // // level 1 ( "1" in binary form, ie set first bit ) just vip // level 2 ( "10" in binary form, ie set second bit ) demo admin // level 3 ( "11" in binary form, ie set first and second bit ) admin // level 4 ( "100" in binary form, ie set 3-t bit ) judge (judge including admin) // level 5 ( "101" in binary form, ie set 3-t and 1-t bit ) admin and demo admin // level 6 ( "110" in binary form, ie set 3-t and 2-t bit ) judge admin and demo admin // // // IP BASED VIP // // Changed way of using *VIP value in mod. // Every VIP can still connect as spectator with every level (it is made serverside) // but now you can set extra flags (like fpd) // 1 ( "1" in binary form, ie set first bit ) - normal VIP (default) // 2 ( "10" in binary form, ie set second bit ) - not kickable VIP by elected admins // 4 ( "100" in binary form, ie set 3-t bit ) - VIP with admin rights // 8 ( "1000" in binary form, ie set 4-t bit ) - VIP with demo admin rights // 16 ( "10000" in binary form, ie set 5-t bit ) - VIP with judge rights // 32 ( "100000" in binary form, ie set 6-t bit ) - VIP with rcon admin rights // // example: // - vip_addip 1.2.3.4 2 = not kickable VIP // - vip_addip 1.2.3.4 6 = not kickable VIP with admin rights // - vip_addip 1.2.3.4 63 = VIP with all permissions THE PROBLEM: So if u authorized with pass, and for example get level 6 ( "110" in binary form, ie set 3-t and 2-t bit ) judge admin and demo admin. Actually, insted of this "judge admin and demo admin" u get rights wich equal to 3-t and 2-t bits for ip based vips, ie: 4 ( "100" in binary form, ie set 3-t bit ) - VIP with admin rights 2 ( "10" in binary form, ie set second bit ) - not kickable VIP by elected admins Thats not we are expected, right? QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/000077500000000000000000000000001475442401000234635ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/bit.mdl000066400000000000000000000020241475442401000247350ustar00rootroot00000000000000IDPO; < <5?(ϳ?                                                                                   bit&@w @QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/check.mdl000066400000000000000000003422241475442401000252450ustar00rootroot00000000000000IDPOf=i$WmAQBvy@ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>>99>9>9>999>>9>9>9>9>9>9>9>9>>>99>9>9>999>>9>9>>>99>9>9>9>9>9>9>9>999>>9>9>9>99>>9>9>9>9>9>>>99>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>999>>9>9>9>9>9>9>9>9>>>99>9>9>9>999>>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>>>99>9>9>9>9>9>9>9>99>>>9999>>>>9999>>>>9999>>>>99>>99>>99>>99>>9999>>99>>9>9>9>9>9>>>99>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>999>>9>9>9>9>9>9>9>9>>>99>9>9>9>999>>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>9>>>99>9>9>9>9>9>9>9>99>>>99>999>>>>99>999>>>>9999>>>>9999>>!!  !!  .*,.(.,&,$,,$,*"*"*!*!*!*((((((:97<((9<>:@:@B<BD<DE>EE>GG>GG>GI>I>I@I@I@I>G(((!*>G!*!>GG>GE>ED<DB<B:@>:<9::77553311.1/,.*.(&,$,"*G..G7G7G((G/7/7>G>.*,.(.,&,$,,$,*"*"*!*!*!*((((((:97<((9<>:@:@B<BD<DE>EE>GG>GG>GI>I>I@I@I@I>G(((!*>G!*!>GG>GE>ED<DB<B:@>:<9::77553311.1/,.*.(&,$,"*//GG7G>G]]]]QQr!rx!xxrxrwqwququqtpt pq oonllqoonll   !!      .,*.(.,&,$,,$,*"*"*!*!*!*((((((:79<((9<>:@:@B<BD<DE>EE>GG>GG>GI>I>I@I@I@I>G(((!*>G!*!>GG>GE>ED< D B< B: @ >: <9 : :7 75 5 33 11 .1/ ,. *. ( &, $,"*%G%.1++.1G+7+G%7%GC(C4:(4G:/C7C/:7:>DGD>S.X,W*S.W(S.S,W&R,W$R,R,W$R,R*V"R*U"R*U!Q*T!Q*S!Q*Q(RQ(QQ(Q(QQ(Q(X:S7S9X<PP(P(S9X<W>S:W@R:W@WBR<WBWDR<VDVER>UEUEQ>TGTGQ>SGSGQ>RGQIQ>QIQ>QIP@PIP@OIO@NIO>MGNO(O(MN(L!N*N>LGL!M*J!N>LGLGM>KGKEM>JEIDM<IDHBL<HBL:G@G>L:G<L9G:G:L7G7L5G5G3L3G1L1G.L1L/G,L.G*L.G(H&L,I$L,I"M*g/nfa/gGoGd7a[[Ga>aG&] ]=n]S]SQ&Q     ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*/.,-/,210320541251764574986796;:89;8=<:;=:?><=?<BA@CB@EDABEAGFDEGDIHFGIFHIHLKJMLJONKLOKQPNOQNTSRUTRWVSTWSYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`fedgfdihefiekjhikhmljkmjonlmolqpnoqnsrpqsputrsurwvtuwtzyx{zx}|yz}y~|}|~~MJM               ! !#" !# %$"#%"'&$%'$*)(+*(-,)*-)/.,-/,10./1.320130542352764574986796;:89;8=<:;=:?><=?<A@>?A>CB@AC@EDBCEBGFDEGDIHFGIFLKJMLJONKLOKQPNOQNSRPQSPUTRSURWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebgfdegdihfgifkjhikhmljkmjponqpnsropsoutrsurwvtuwtyxvwyv{zxy{x}|z{}z~|}|~~       ! !#" !# %$"#%"('&)(&+*'(+'-,*+-*/.,-/,10./1.320130542352764574986796;:89;8=<:;=:?><=?<A@>?A>DCBEDBGFCDGCIHFGIFKJHIKHMLJKMJONLMOLQPNOQNSRPQSPUTRSURWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebhgfihfkjghkgmljkmjonlmolqpnoqnsrpqsputrsurwvtuwtyxvwyv{zxy{x}|z{}z~|}|~~               ! !#" !# &%$'&$)(%&)%+*()+(-,*+-*/.,-/,10./1.320130542352764574:98;:8<=<@?>A@>DCBEDBGFCDGCJIHKJHNMLONLRQPSRPUTQRUQXWVYXV\[Z]\Z`_^a`^dcbedbhgfihflkjmljponqpntsrutrxwvyxv|{z}|z~~mjm                 !"!!"##"$"%$$%&&%'%(''())(*(+**+,+-,,-..-/-0//010211233242544565766788797:99:;:<;;<=<>=>?==?@?A@@ABACBBCDDCECFEEFGFHGGHIHJIIJJMLKKLNQPOOPRTRSRPSSPUPNUNLUULVYXWWXZX[ZZ[\^\]]\_\[__[`[a``abedccdfdgffghhgigjiijkjlkklmmlnlonnoppoqorqqrsrtsstutvuuvwvxwwxyxzyyz{{z|z}||}~}~~                 !" !"!#$"#$#%&$%&%'(&'(')*()*)+,*+,+-.,-.-/0./0/1201213423435645657867879:89:9;<:;<;<?>=?=@A?@A@BABCDACDCEFDEFEGFGHIFHIHJIJKLIKLKMNLMNMOPNOPOQRPQRQSTRSTSUTUVWTVWVXYWXYXZYZ[\Y[\[]\]^a`_a_bc\^c^dcdefabfbgfghifhihjkijkjlklmnkmnmonopqnpqprqrstqstsutuvwtvwvxwxyzwyzy{z{|}z|}|~}~}cee                 ! ! "#!"#"$%#$%$&'%&'&()'()(*++,+,-.+-.-/0./0/12)*2*3401415645723738789:79:9;:;<=:<=<>=>?@=?@?A@ABC@BCBDECDEDFEFGHEGHGIJHIJIKJKLMJLMLNOMNONPOPQROQRQSTRSTSUVTUWVUWUXYWXYXZ[YZ[Z\[\]^[]^]_`^_`_ab`aba6b65edcfecchgcgifcilkjljflfilimnlmqposrqoutqotsqtFrame1rJ !! !  j kjkkhh-h-h"g"gZg[Z [ [ ]]] ]YYTTTTSSOO O O GG G""- - -h'k'k-h#j#kjj    #!# '! '! - -  GGGOOOOSSTTTTYY]]]][Z[[gZgghh0k0k0k0k0k0k/j/j/j/j.j.j.j.j.--.--,,++****))((''& &% % $ $ $ $ $##$##"!"!"!"!!!!!! ! ! ! ! ! ! ! ! ! !!""""""###G#$G$G$O%O%O$O&O&O'V'S(T(T)T)T*T*T*T*T+Y+T+Y+Y+Y+Y,],],],]-]-]-]-].].].[.[.[.[.[/Z/Z.[/Z/Z/Z/Z/Z/Z/Z/Z0g0g0g0g0g0g0g0g0S;S;S0S;!:!:!;!9988887776 674 4 3 3 2 2 00..--++))&&$Մ$!Ԅ!ԄӉӉщщωῶ͂͂jj͂jjkkkkkkhhhhhhhhggggggZZZZZZ[Z[[[]][]]]]]] Y Y!Y!Y#Y#Y$T$T&T&T(T(T)T)T+T+T,T,T-T-T/S/V0S0S1S1S2O2O3O3O4O4O5O5O5O5O6G6G6G7G7G6G88889999::::;;;;;00;0k0kATMTMTATM M M M MTZTZTMTZhZhZhZhZTfTfTZTf f f f fZZfZhZhZhZhZMMZM M M M MAAMAhAhAhAhnTTTnT {{{ { { { {TTT{T {{{ { { { {TTT{T nnnhnhnhnhkkkkkkjjjjjjjj  !!!!!! GGGOOOOOOVSTTTTTTTTYTYYYY]]]]]]]]]][[[[[ZZ[ZZZZZZZZggggggggSSSS!!!!  ՄԄԄӉӉщщωῶ͂͂jj͂jjkkkkkkhhhhhhhhggggggZZZZZZ[Z[[[]][]]]]]]YYYYYYTTTTTTTTTTTTTTSVSSSSOOOOOOOOOOGGGGGGkkT͑T͑TT͑ ͑͡͡ ӭGӭGӭZۑZۑZӭZۑTTTۑTۻۻ GGjͻjͻjjͻ ͻ hhhh%TlOlO%Tlllll l OOOhOlhOlhOhOlllOll]l]ҏҏ--"'ݏ؏#܏  #" '- -ҏ ҏݏ ؏܏ 0:ď;09Ǐ008ɏ/8ˏ//7͏//6Ϗ.Ï4я.Ï3ҏ.ď2ӏ-ď0ԏ-ŏ,ŏ.Տ,ŏ-֏+Ə+Ə+֏+Ə*Ə;00;)֏*Ə)Ə0::09/98/87.65.54-32-10,/-+,*+*))((&'$&֏(Ə'Ə$Տ&ŏ!ԏ%ď&#ӏ$Ïя%! $$##""!!!!!!!"ď"Ǐʏ"͏#Ϗ#MՏAAՏMfՏZZՏfZZMMƏnՏՏ{Ən{{{ďǏɏˏ͏ϏÏяÏҏďӏďԏŏŏՏŏ֏ƏƏ֏ƏƏ֏ƏƏ֏ƏƏՏŏԏďӏÏяďǏʏ͏ϏۻՏՏͻۑꑏӭՏՏ͑͡Ol%lllO4-44-4"4'4444#4444444 4444444444444444444444 44444#4"4 '4-4 -44 44 44444 4444444404;4:40494040484/484/4/474/4/464.444.434.424-404-4,4.4,4-4+4+4+4+4*4;40404;4)4*4)404:4:40494/49484/48474.46454.45444-43424-41404,4/4-4+4,4*4+4*4)4)4(4(4&4'4$4&4(4'4$4&4!4%4&4#44$44%4!4 4$444$444#444#44"444"44!444!44!444!44!44!4!44"44"444"44#44#4M4A4A4M4f4Z4Z4f4Z4Z4M4M444n4{4n4{444{4{444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444ۻ444ͻ4ۑ44ӭ4444͡4͑4Ol4l4%4l4l44O4QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/finish.mdl000066400000000000000000003171641475442401000254550ustar00rootroot00000000000000IDPOZ=]$WmAQBD@oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooWWWWUUTT&&$$########$$&&TTUUWWWWVVVVUUTTTT&&%%$$$$$$$$%%&&TTTTUUVV=UU=UGGUG22G2%%2%%%((%(,,(,((,(--(-%%-.11.1..135539<<9<99<5335=@@=@==@CCCCCCDDDDEEFFFFGGGGGGGGGGHHHHHHIIIIIIIIIIIIIIIIHHHHHHGGGGGGGGFFFFFFFFEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFGGGGGGGGGGGGGJJGIIIIHHHHGGGGGGGGFFFFEEEEEEDDDDDDCCCCCCCCCCBCCBCCCCDDDDEEEEFFFFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGFFFFFFFFEEEEEEEBBELNNLNQQNQTTQTQQTQNNQNLLN  \\\\OO&&G.7.7GGGGG/5GGGG*(*9:9&*$(""(!!(&&&&&$$$$$9<:>@:B<B<D<DE<E>G>G>>G@G@@G@$$@G@G>$$$G>G>&E>E>E>E&D<D<BB<@@<>>:<<::99:775:553391119//9/9..9.7.77,7,7,75,,5*5**3*3**1*1/*/(..,(**((((&&$($""("!&!&&&G,,G7G7Grrxxxrxrwqwququqtpt pqoonllqoonll         &\ \=n\S\SO&O& & G.7.7G#G#G-((G-G-/454G:G:4D>>GDGR*W*W(L9G9G:W&R*W$R(W"W"R(V!V!Q(UQ&TSQ&RQ&Q&QQ&QQ$Q$PP$P$OO$L9G<L:G>H@M:HBM<IBM<IDM<JDKEM<LEM>LGN>MGN>O>OGO@PGP@P@QGQ@O$NO$Q@QGQ@RGQ>MN$N$MN$SGQ>SGQ>LN&TER>UER>UER>VELN&VDR<WDR<WBWBR<W@W@R<X>X>R:X<X<X:R:X9X9R:X7X7X5R:X5X5W3W3R9W1W1W1R9V/V/R9U/R9U.T.Q9S.Q7R.Q7Q7Q,P7Q,P7P,O7N5O,O,M5N*L5N*N*L3N*K3M*M*J1M*I1I/M*H/M(H.H.H,M(G*G*M(G(H(M(H&H&H$M(H$H"I"M(I"I!M&J!JM&KM&LM&a\\Ga,nhh,nGh7hGa7aG       ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*0/.10.32/03/542352764574986796;:89;8=<:;=:@?>A@>CB?@C?EDBCEBGFDEGDFGFJIHKJHMLIJMIONLMOLRQPSRPUTQRUQWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^dcbedbgfcdgcihfgifkjhikhmljkmjonlmolqpnoqnsrpqsputrsurxwvyxv{zwx{w}|z{}z~|}|~~KHK       ! !#" !# %$"#%"'&$%'$*)(+*(-,)*-)/.,-/,10./1.320130542352764574986796;:89;8=<:;=:?><=?<A@>?A>CB@AC@EDBCEBGFDEGDIHFGIFKJHIKHMLJKMJONLMOLRQPSRPUTQRUQWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebgfdegdihfgifkjhikhmljkmjonlmolqpnoqnsrpqsputrsurwvtuwtzyx{zx}|yz}y~|}|~~               ! !#" !# %$"#%"('&)(&+*'(+'-,*+-*/.,-/,10./1.320130542352764574986796;:89;8=<:;=:?><=?<A@>?A>CB@AC@EDBCEBHGFIHFKJGHKGMLJKMJONLMOLQPNOQNSRPQSPUTRSURWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebgfdegdjihkjhmlijmionlmolqpnoqnsrpqsputrsurwvtuwtyxvwyv{zxy{x}|z{}z~|}|~~                !  !"!#""#$#%$$%&%'&&''*)(,+).(-()-)+-10//02032234645547437738;:99:<?>=>@=@A==ABACBCDBDEBBEFIHGGHJMLKPONLQKKQRQSRRSTSUTUVTTVWVXWXYWWYZY[ZZ[\[]\]^\\^_^`__`aa`b`cbbcdceddeffegehgghiihjhkjjklNOmOnmmnonpopqooqrqsrrstsuttuvuwvvwxwyxyzxxz{z|{{|}|~}}~~lkk               !" !"!#$%$%$&'%&("#(#)*()*)+,*+,+-.,-.-/'&01'010231232453454675676897898:;9:;:<=;<=<>?=>?>@A?@A@BCABCBDECDEDFGEFGFHIGHIHJKIJKJLMKLMLNOMNONPQOPQPRSQRSRTUSTUT./U.XWVZYXV\[XV[ZX[_^]_]`a_`a`bbdcbceabeaefihgigjmlknmkonkokpqoprqpsrpsptwvuwux{zy~}|{yy~|~                 !"!"!#"#$%"$%$&%&'%'()%()(*)*+)+,-),-,.-./0-/0/1012302324534546756767:98:8;>=<><??A@>?@>@B;>B:;B:BCFrame1rJ !! !  j kjkkhh-h-h"g"gZg[Z [ [ ]]] ]YYTTTTSSOO O O GG G""- - -h'k'k-h#j#kjj    #!# '! '! - -  GGGOOOOSSTTTTYY]]]][Z[[gZgghh%TlOlO%Tlllll l OOOhOlhOlhOhOlllOll]l]T#T#TT# # # # #T3T3T#T3 3 3 3 3##3# # # # #T6T6T#T6 6 6 6 66hhhh=TJTJT=TJ J J J J==J=h=h=h=hST_T_TST_ _ _ _ _ZnZnZ_ZnTzTzTnTz z z z znnznhnhnhnhn^^n^SS^ShShShShTTTT hhhhggggggZZZZ[Z\\]]]]]]YYYYTTTTTTTTTTTTSSSSSSOOOOOOOOGOGGGG ! !!!!!!   !!! ! GGGOOGOOOOSSSSTTTTTTTTTT``Y`]]]]]][[ZZZZZZgZggggggTTTT!!!!!!!  ՄՄՄԄԄӉӉ҉҉҉҉щщωω΂΂΂jj΂jjjjkjkkkkkkhhhhhhggggZZZZZZ[]][]]]]]]`]Y`YYYYYYYYYY]Y]]]]]][[ZZZZZZgggghghhkhkkjkjjjj !!!!!!!!!!hhTΐTΐTTΐ Ϋ Ϋ ΐ ΫTܫTܫTΫTܫhܐhܐhܫhܐTTTܐT hܼhܼhhܼμμܼμ μ hhhhҏҏ--"'ݏ؏#܏  #" '- -ҏ ҏݏ ؏܏ Ol%lllO6ƏՏ6Տ#Ə#33##JՏ==ՏJ^ՏSSՏ__nnzzՏnՏՏՏďǏɏÏ̏ΏďЏяŏҏƏӏԏƏՏǏǏ֏ȏ֏ȏɏ֏ɏɏ֏ɏɏ֏ɏՏɏɏՏȏՏȏԏǏÏÏÏŏďƏȏɏďʏ̏͏ŏΏϏŏяҏƏҏƏӏǏՏՏμՏܼՏ萏ܫܐΫΐ4-44-4"4'4444#4444444 4444444444444444444444 44444#4"4 '4-4 -44 44 44444 44444444Ol4l4%4l4l44O464644#44#43434#4#4J4=4=4J4^4S4S4_4_4n4n4z4z4n4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444μ444ܼ44ܫ4ܐ4Ϋ4ΐ4QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/flag.mdl000066400000000000000000001744401475442401000251040ustar00rootroot00000000000000IDPO#=+\>>=VUR@@@@@@@@FFFHHHHHHHHHHJJJJJJJJJJJJD@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJHHHHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@@@RU:ZWUUT@@@@@@@@FFFFHHHHHHHHHHHJJJJJJJJJJF@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@JJJJJJJJJJJHHHJJJHHHHHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@@qTU:=VU@@@@@@@FFHHHHHHHHHHHJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DJJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@@8U:Uq@@@@@@@FFFHHHHHHHHHHJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@UWVU@@@@@@FHHHHHHHHHHJJJJJJJJJJJJJE@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@UV?WU̯@@@@@@FHHHHHHHHHHHJJJJJJJJJJJJF@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@BJJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@UW>?Vq@@@@@FHHHHHHHHHJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@q8V?>WU@@@@@FHHHHHHHHHHJJJJJJJJJJJJJD@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@R8V?UT@@@@FHHHHHHHHJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@DJJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@TU=VR@@@@@FHHHHHHHHJJJJJJJJJJJJJJJ@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@EJJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@TU=Vq@@@@FHHHHHHHJJJJJJJJJJJJJJJF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@Q8VWU@@@@FHHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CJJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@qV=:8@@@@FHHHHHHHJJJJJJJJJJJJJJJD@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@UWUTP@@@@FHHHHHHHJJJJJJJJJJJJJJJE@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@R8:>W8̯@@@FHHHHHHHJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@FJHHHJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@TU?UR@@@@FHHHHHHHJJJJJJJJJJJJJJJC@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@FJHJJJJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@8:>W8̯@@@FHHHHHHJJJJJJJJJJJJJJJJ@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@EJHHHHHJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@UU@@@@FHHHHHHJJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@FJHHHHJJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@8::8TP@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@DHHHHHHHJJJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@qU??U@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@EJHHHHHJJJJJJJJJJJJHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@8:==V8TP@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@DHHHHHHHHJJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@qU>WU@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@DHHHHHHHJJJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@VUT̯@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@DHHHHHHHHHJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@PTUW?=V8T@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@DHHHHHHHHHJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@RUW:8̯@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DHHHHHHHHHJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@T8VUTR@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@DHHHHHHHHHJJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@qT8V>??>WU@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@DHHHHHHHHHHJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@UW=??:8q@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DHHHHHHHHHHJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@U:>>V8R@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DHHHHHHHHHHJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@RT8VW?WUͯ@@@@FHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@DHHHHHHHHHHJJJJJJJHHHHHHFFFC@@@@@@@@@@@@@@@@@@@@@@@TU:?VUT̯@@@@FHHHHHHJJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@UVW>???>WUR@@@@@FHHHHHHJJJJJJJJJJJJJJJJ@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@EHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@T8UVW==WVUR@@@@@FHHHHHHHJJJJJJJJJJJJJJJC@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@RTUU:W=VU8T̯@@@@@FHHHHHHHJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@RT8UUV:WW:VUU8Tͯ@@@@@FHHHHHHHJJJJJJJJJJJJJJJE@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@8UUV::WW:VUUTR@@@@@@FHHHHHHHJJJJJJJJJJJJJJJD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@@RT8UUU88TTP@@@@@@FHHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@BHHHHHHHHHHJJJJJJJJJHHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@TT88UUU88TR@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HHHHHHHHHHHJJJJJJJJHHHHHHFFC@@@@@@@@@@@@@@@@@@@@@@@@@@RTTTTTTTP@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJJ@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@EHHHHHHHHHHJJJJJJJJJJHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@TTTTTTTR@@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@CHHHHHHHHHHJJJJJJJJJHHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@qR@@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJJD@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@Rq@@@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJJJHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@qR@@@@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJJF@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@BHHHHHHHHHHJJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@Rq@@@@@@@@@@FHHHHHHHJJJJJJJJJJJJJJJJE@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@HHHHHHHHHHHJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PPP@@@@@@@@@@@@FHHHHHHHHHJJJJJJJJJJJJJJJB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHJJJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ϯPP@@@@@@@@@@@@@FHHHHHHHHJJJJJJJJJJJJJJJH@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@DHHHHHHHHHJJJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHJJJJJJJJJJJJJJF@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@HHHHHHHHHJJJJJJJJJJJJJJHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHJJJJJJJJJJJJJJJD@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHJJJJJJJJJJJJJHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHFFFFHHHJJJJJJJJJJJJJJB@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@EJHHHHHHHJJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHFFHHHJJJJJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CHHHHHHHHHJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHFFEEEFHHHJJJJJJJJJJJJJF@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@BHJHHHHJJJJJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHFFFFFHHJJJJJJJJJJJJJJD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@HJHHHHHJJJJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHFECBEFHHHHHHJHHJJJJJJJC@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHFFECDFFHHHHHJJJJJJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFD@@@BFFFFFFHHHHHHJJJJJH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@DJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHFE@@CFFHHHHHHHHHJJJJJJF@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@BHJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFC@@@@DEDCDEFFFFHHHJJJJJF@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@BJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFD@@@EFFEEFFFHHHHHJJJJJC@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFEC@@@@CD@CDDEFFHHHHHHJJE@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@BHJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFC@@@@CEBBDEEFFFHHHHJJJHB@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFE@@@@CC@@@BBBBDFFHHHHHHHJD@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@HJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFEB@@@@CC@@BCDDEFFHHHHHHJH@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFD@@@@@CC@@@B@@CEFHHHHHHHHHC  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@BHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFE@@@@CC@@@BDEFHHHHHHHJH@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFD@@@@@CC@@@@@@BEFHHHHHHHHHB  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@BHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFD@@@@@CC@@@@@BEFHHHHHHHHJB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFE@@@@@BDB@@@B@CEFFHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@EJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFD@@@@@CC@@@@@CEFFHHHHHHHF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFE@@@@BDDBBDDBEFFFHHHHHHFDD@@@@@@@@@@@@@@@@@@@@@@@@@@@BFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFE@@@@BDC@@@CBDFFFHHHHHHHB  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@CHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFFC@@@@BEEEEEEFFFFFFHHHHHFB EHHFC@@@@@@@@@@@@@@@@@@@@@@@FHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFEB@@@@BEEDCCEEEFFFFHHHHHHC FFC@@@@@@@@@@@@@@@@@@@@@@@@@BFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFFD@@@EFFFFFFFFFFFFFFFHC FHHHHHFD@@@@@@@@@@@@@@@@@@BFHJJHHJHHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFFC@@@@BEFFFFFFFFFFFFFHHHE DFHHHFC@@@@@@@@@@@@@@@@@@@@@BEHJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFECB@BEFFFFFFFFFFFFFFFF FHHHHHHHHHFC@@@@@@@@@@@BEFHJHHHHHHHHHHHHHHHHJJJJJJJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFDC@@EFFFFFFFFFFFFFFFF DHHHHHHHFDB@@@@@@@@@@@@@@@CFHJJHHHHHHHHHHHHHHJJJJJJJJJJJJJJJJJJJJJJHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFFEDCDEFFFFFFFFFFFFFFFFFDFFFFFFHHHHHHHHFFEDDDDDDFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHJJJJJJJJJJJJJJHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHFFEDCBBCEFFFFFFFFFFFFFFFEEHFFHHHHHHHHFEDB@@@@CEFHHHHHHHHHHHHHHHHHHHHHHHHHJJJJJJJJJJJJJJJJHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFHFFFFEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHJJHJJJJHHHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHFFFFFEDEEFFFFFFFFFFFFFFFFFEEFFFFFFFFHHHHHHHHHFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHJJJJJJJJJJJHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHD@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFFHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFFHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHFHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFFHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFHHHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHFHHHHHHHHHHHHHHHHHHHHFFHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFFHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHFFHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FHHHHHHHHHHHHHHHHFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFHFFFFFFFHHHHHHHHHHHHHHHHHHHHHHHHHHHHFHC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CCCCDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDCCCCCCCC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RP@@@@@RP@@@@@VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV@@@@@VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV@@@@@WT@@@@@WT@@@@@Y@@@@@Y@@@@@8@@@@@8@@@@@:@@@@@:@@@=@@@@@=@@@@@@@@ʯ@@@U@@@@@U@@@T@@@@@T@@@@@@@@@@@@@@@@@@@@@@@@@VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWR@@@@@VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ڿ@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ߿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ߽  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ߽ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ۿ@@@  @@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@ @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qTTR@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RTTq@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RT8UVVVVUUP@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UUVVVVUUTR@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8UW=>=VUR@@@@@@@@ۿ@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RU:ZWUUT@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qTU:=VU@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8U:Uq@@@@@@ۿ@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UWVU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UV?WU̯@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UW>?Vq@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@q8V?>WU@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@R8V?UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@TU=VR@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@TU=Vq@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Q8VWU@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qV=:8@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@߽@@@@@@@@@@@@@@@@@@@@@@UWUTP@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@R8:>W8̯@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$@@@@@@@@@@@@@@@@@@@@@TU?UR@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@"@@@@@@@@@@@@@@@@@@@@@@@8:>W8̯@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UU@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8::8TP@@@޿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qU??U@@@޿@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8:==V8TP@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qU>WU@@@@@@@߿@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@VUT̯@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PTUW?=V8T@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RUW:8̯@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@T8VUTR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qT8V>??>WU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UW=??:8q@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U:>>V8R@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RT8VW?WUͯ@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@TU:?VUT̯@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@UVW>???>WUR@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@T8UVW==WVUR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RTUU:W=VU8T̯@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RT8UUV:WW:VUU8Tͯ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8UUV::WW:VUUTR@@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RT8UUU88TTP@@@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@TT88UUU88TR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RTTTTTTTP@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@TTTTTTTR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qR@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Rq@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@qR@@@@@@@@@@޿@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Rq@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@PPP@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ϯPP@@@@@@@@@@@@ݿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@޿@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@߿ݿ@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ܿ@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ܿ@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@޿@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@޿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ݿ@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ڿ @޿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@߿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @޿@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ڿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ڿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ۿ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@RP@@@@@@@@@@WYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY@@@@@YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY@@@@@WYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYT@@@@@YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY@@@@@Y@@@@@T@@@@@8@@@@@@@@@@:@@@@@UƯ@@@=@@@@@ů@@@@@@@@=ů@@@U@@@@@ǯ@@@T@@@@@U@@@@@YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY@@@@@TYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY@@@@@YYYYYYYYYYYYYYYYYYYY@@@@@YYYYYYYYYYYYYYYYYYYYW@@@@@VWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWR@@@@@WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWVWWWWWWWVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +  G +G 7 7G D DG Q QG ] ]G j jG v vG  G++GG77GDDGQQG]]GjjGvvGG  $$* ,*$   $ , / , $ $*,*$$ P QT T X YXTQ P Q T X YXTQT     ! "#!! "     !  !#!#"#" "       $%&'$&('&)(&*)&+*&,+&%,&-.%$-%/-$'/$0/'(0'10()1(21)*2)32*+3*43+,4+.4,%.,56.-5.75-/7-87/08/980190:912:1;:23;2<;34<36<4.6465=57=78=89=9:=:;=;<=<6=>?@?A@AB@BC@CD@DE@EF@F>@GH>H?>HI?IA?IJAJBAJKBKCBKLCLDCLMDMEDMNENFENGFG>FHGOIHOJIOKJOLKOMLONMOGNO=L>>>??433?frame1&@+<~ y m+=@3Bٝ@ST59oooS?oooooooo>ooooooooooooo=oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo5oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooS::SS9:::85135S542112338?>==<::8S5S9::999UU8S5S:<===<:9U:<==<:855SS:<==:999U8S55STS9<>???????????>=:S15>?=;><5311124S>=<<>o>5ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=?oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooSSooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo5ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooS5oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo98oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo;8ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>:oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>8oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>>ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>9oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo:ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?Tooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo:oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo:9ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo:ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<=oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=5ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<5ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo8=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo5oooooooooooo9oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooS5;?>S358999S425oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>S9:<:TS<>=:::?ooooooo>=:T5555555135U>=<<<<<<<<<<::9TSSS9:;;<;::9TTSSSSSSSS5S;??=955ooooooo>=<<=>oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo9oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooS8ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo:ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?Toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<;ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo5=oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo5>oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<=oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>1?ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo8?ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo1ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo2ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo4oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooSSooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo99ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=:oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?=ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo?oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo9oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooTooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooTooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo>8oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooS9oooooooooooooooooooooooooooooooooooooooooooooo??>>>>>>>>>>?=S9=????>=<;98TSSSSSSSSSSSSSSSSSSSSSSSSSSS5S8:<<<<<<<<==>>=<:9UTTSSSSS55SSSSSSSSSSSSSSSSSSSSS5STU9:9:9998S555/CCZ#CCT/T[[00  00  V//cbZ`Y__Y_ ` Z b e\_ecf`^h\lemghnhp p j s {lxousvyqqs{uvv| uZ{Z{{fZZo{%Z,Z,v?q>u=k=x;h;z8p8g8n5m5f3l0f/l,f,l8{8t5{5v2v0{/v%{WgMgYaKa[ZbZV{RsN{IZAZ{{ZdZ~{yst{sZodjZi{b{;;@@DD**1133557799>>@@BBEEIINNQQVVXX[[^^``ccggjjnnttxx||iii^^YYVVTTQQNNJJ**11UU\\JJWW33AA||eee\\DDzzaaZZdd^^EE11**JJ))   srqtuvxyy{|}xy{|~XcZfNU[^bho)(!-137<>AFGN     !#"!%$!$&#!&&'#(*))*+*,++,--,.,/../00/1/211233242545647468:9:;99;<;=<<=>=*>*(>(?>>?@?A@AB@@BCBDCCDEEDFDGFFGHHGIGJIIJKJLKKLMNMLOQPQRPRSPPSTSUTUVTVWTTWXWYXXYIHIYZ\[][\^`_`a_ab_[_bc^_dfegihhijikjjkllkmknmmnoonpnqppqrqsrrstsutvtulmwmxwwxyxzyz{yy{|{}|}f||f~d~f                !  !"!#""#$#%$$%&%&&')(()*)+**+,+-,,-.-/../01200234655676877898;::;<;=<<=>=?>>?@?'@@'(ACBBCDCEDDEFEGFFGHGIHHIJKMLLMNMONNOPOQPPQRQARRABSUTTUVWYXXYZYSZZST[]\\]^]_^^_`acbbcdceddefghffhihjiijklnmmnonpoopqpsrrstsuttuvuwvvwxwyxxyzy{zz{|}~~}}~Frame 1AV4V44V4V44A4TTVYVYVVAVAVAVhAVhAhAhAA V V VVVVVSVSVAVVVA"4!4"444444444 4 4 444+4+4*4)4)4&4$4!4444444444 4 44444(4$4)44444444444֣4444444444>4>4Z4Y4X4W4U4T4P4O4O4L4K4I4D4C4>4>4P4O4L4K4H4D4C444}4o44k444|4v4q4h4]444ģ44444444444k   !  !j!j"k"h!Z![]]YYYYYYY]] ] [Zghkkkj  $ $ $$((!)!)!)T)T][ZZ[]]]TTO   $ $ ))+!+!+ + **))&G&O"O"OSTTTY] ] [Zg4]4Z4j4h4DDLLPPT T WWY!Y!Z!Z!ZZXXUGUOOSOSKTKTDTDT>O>>>O>O>>> CCIIԄLքL։L։OډOډOkOkPhPhOZOgO]KYKTHTHTCTCTO]ZZ]kOkhhhThT]]]hqq| |}Ɖ}kvgvgvvo!o ggk!!jk !!kkj ģģO]ZZOTT֣]֣Zj kj TTY]]O"!"  *+ď+))ʏ&$ԏ!؏ƏȏڏʏޏΏ ԏ܏)$(֣࣏ď܏>>4XҏYZWUʏTPOƏOڏL֏KďIԏDďCԏ>ď>ԏPOLKHDC4oƏ}Ək|vqh]ģQMEXskin0root???????object1?????ji@???object2  ????@???object3 ????RA???object4????L,yx'A???object5????jiKA???object6????L,Ayx'A???object7????RAA???object8!"#$%&'????ji@??? object92()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY?????%A??? object10 Z[\]^_`abc?????AA??? object11defghijklmnopqrstuvwxyz{|}~?????4A??? object12 ?????.-ݿA??? object13 ?????RAA???object14R????%A???object15????[CA???object16????vZڴA???object17#      !"#$%&????4A???object18'()*+,-./0123456789:;<=>?@????4-A???object19ABCDEFGHIJKLMNOPQR????.-ݿA???object20STUVWXYZ????ҿA???object21[\]^_`????b@A???object22 abcdefghijk????MK@aA???object23lmnopqrstuvwxyz{|????jAA???object24}~????AA???object25????=|AA???object262????%A???object27 ????򿈇AA???object28????4A???object29 ????.-ݿA???object30 ????RAA????L,A4@?@A4@?2->4@?@AA4@?L,AA4@?L,AjiKA4@?L,jiKA4@2->T@?2->T@@AY@?@AY@@A@?@A@L,A@?L,A@L,Ah@?L,Ah@L,jiKAh@?L,jiKAh@L,jiKA@?L,jiKA@L,AjiKA@?L,AjiKA@L,AjiKA @?L,AjiKA @L,AA @?L,AA @L,AA@?L,AA@@AA@?@AA@@AAS@?@AAS@2->@@A@L,A@L,AA@@AA@L,AjiKA@L,jiKA@?@ÏA4@?㡂A4@?@[Z|A4@?eA4@?j)=<@KKA4@?@LKyA4@?zx@yxA4@?\Z @yxA4@=|ҒAk@?=|ҒA@j[ZA@?j[ZA@G<<@KKA@?><@KKAj@@yxAk@?@yxA@@yxA@.AyxA @?.AyxA@/AKKA!@?/AKKA!@/AKKAk@?/AKKAk@.EAyxAj@?.EAyxA@^AyxA @?^AyxA@?^AyxA@a=ALKyA@?a=ALKyAO@4ALKyA]@?4ALKyAZ@AAZ@?AA@@LKyA@?@LKyAO@򿉇@LKyAT@?@LKyAT@%oALKyA]@?%oALKyAZ@%oAyxAj@?%oAyxA@eAyxA@?eAyxA @jAA @?jAAk@jAyxAj@?jAyxA@=|AyxA@?=|AyxA@=|AyxA @?=|AyxA @=|ALKyA @?=|ALKyA @=|ALKyAT@?=|ALKyAT@GALKyAY@?GALKyA]@eA<<@KKA@򿉇@LKyA@zx@yxA@\Z @yxA@QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/star.mdl000066400000000000000000001117641475442401000251440ustar00rootroot00000000000000IDPOs=p=p=PA>x+@MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM      MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"޺LMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"޺LMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"r#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"r#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$#1##!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$#1##!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##ލ#$LJMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##ލ#$LJMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"#MMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"#MMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!MMMMMMMMMMMMMNMMMMMMMOM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!MMMMMMMMMMMMMNMMMMMMMOM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##"#GMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##"#MMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#޺!#NHMFMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#޺!#MFMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"###!MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"###!MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"#!""KMMO  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"#!""KMMO  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"1 ޽"!## !  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#"1 ޽"!## !  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOM#!ݽ#! " 4#!#! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOM#!ݽ#! " 4#!#! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""! "p p! `!"#"! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""! "p p! `!"#"! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#!  ! # MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#!  ! # MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#1 ! "" #!#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#1 ! "" #!#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! !ݽ!"#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! !ݽ!"#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMݽ !!!""$s#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMݽ !!!""$s#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO!" "3"""#!!!!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO!" "3"""#!!!!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO" !"!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO" !"!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMME"""ݻMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMME"""ݻMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMD "!#!޼!#!JMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMD "!#!޼!#!JMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOH "!NLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOH "!NLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMD#   #"!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMD#   #"!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO  ! #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO  ! #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMݫ! "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNMMMMMMMMݫ! "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOMMMMMMM!1  ޼MNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOMMMMMMM!1  ޼MNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$ !" #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$ !" #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#" 3" MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#" 3" MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs""1  ! ޫOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs""1  ! ޫO MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO# ! $MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO# ! $MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMFN#  !MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMFN#  !MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO" ! #IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO" ! #IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMML#""#" $MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMML#""#" $MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!"!    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!"!    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM# !  " MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM# !  " MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"#1!!!!p "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"#1!!!!p "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM݉#""! p " MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM݉#""! p " MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!##"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!##"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##3!! "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##3!! "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMr"#"!#! "!#!"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMr"#"!#! "!#!"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!"s"#"!$!  "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!"s"#"!$!  "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"##! 1!!  p`3MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"##! 1!!  p`3MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#p##"!!#"!!#""OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#p##"!!#"!!#""OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM !$޸$!p p ލ   1#ݹMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM !$޸$!p p ލ   1#ݹMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM "!3!"3"! #"!"#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM "!3!"3"! #"!"#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  "!###!###!##" ! #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  "!###!###!##" ! #MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMIIDE"!#p! `!#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMIIDE"!#p! `!#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   #MMMMMNLMMM1$! $LMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   #MMMMMNLMMM1$! $LMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM !CFOMMMMMMMMOF#GMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM !CFOMMMMMMMMOF#GMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MKGMMMMMMMMMMMMM#JOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MKGMMMMMMMMMMMMM#JOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMLMMMMMMMMMMMMMMM"#FMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMLMMMMMMMMMMMMMMM"#FMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM OMMMMMMMMMMMMMMMMMMMMMM"!##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM OMMMMMMMMMMMMMMMMMMMMMM"!##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMM""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMM""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMOM"##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMOM"##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMED#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMNMMMMMMMMMMMMMMMMMED#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLMMMMMMMMG##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMLMMMMMMMMG##MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM#MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!#pMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!#pMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM    MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM97B<AGJLJGB<9 J20 }A QJ d}S 9Q dB 29  L0 B- S7 VA SL LS BV 7S 0L -B 07 70J2 B0 } SAQJ d} BS9Q d 0B29 G9B7J<LAJGGJBL<J9G7B9<<9BA                      ! !"!"#"#$#$$%&%'%'('()()*)*+*+,+ ,-, !- .-!".!/."#/"0/#$0#&0$&$12&%1&31%'3%43'(4'54()5(65)*6)76*+7*87+,8+98,-9,:9-.:-;:./;.<;/0</2<0&20;<=:;=9:=89=78=67=56=45=34=13=21=<2=star&@[[[[[m[jP[um[mut[jw[mv[ujj+jjm+jZjm_W+6tjZxj_z+6'jZOT`jZYZjZTmZzj  0(m,=Z_m_@6DZn_p68220+u(mLjfumfmuDjomnu4QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/start.mdl000066400000000000000000003531641475442401000253320ustar00rootroot00000000000000IDPOr=$WmAQB`o]@oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooRQQRQQOO!!  !!OOQQQQRRQQQQQQPPOO!!!!  !!!!OOPPQQQQ8PP8PCCPC..C. . """"########$$%%%%&&&&&&''''''((((((((((((((((((((((((''''&&&&%%%%$$$$$$$$$$$$#####$$#$$$$$$$$$$$$$$%%%%%%%%%%%%&&&&&((&((((((''''&&&&%%%%$$$$##############""""""""""""########$$$$%%%%%%%%&&&&&&&&&&&&&&&&&&%%%%%%%%%%$$$$$$$$$$#!!#*--*-//-/33/3**3:==:9669366369968778AAAAAAAABBBBBBBBBBBBBBCGGCEEEEEEEEDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEFFEEEEEEEEEEDDDDDDDDCCCCBBBB===AA=ABBABBBBBBBBBBBBCCCCCCCCBBBBBBBBBBBBBBBBBBBBBBBBAAGJJGJLLJLPPLPGGP""   ""   ____QQ.*,<><*,(,&$,$"*""*!*!*(!(!((!((!((!(<@B<B>D>E>EG@I@I@IBIBBKBKBBKBBKBIB!((!(IBIB!(IBI@G@G(!*"G@E@ED@DB>B@>@>>><<>::9<9775<553<33<11:1:/:/::/:/9.99..9..7.7.5.,5,5,31,1//,.,,,*,*((*&&&*$$*""*"*!,!,,,II:I:!,!IDIDI9111111919119I>I9<>><<<<::::::9999999999::<!II*!****!*<:!*<!*:!*:!*",""","$$$,&&((,**,.,...//.111.335.55/57/777/77/7//1111:!,!,,,IIr"rx"xxrxrwqwququqtptpq oo nl lqoonll   ""    &_ _=n_S_SQ&Q.,*< < >*,(,&$,$"*""*!*!*(!(!((!((!((!(< @ B< B> D> E>EG@I@I@IBIBBKBKBBKBBKBIB!((!(IBIB!(IBI@G@G(!*"G@E@ED@DB>B@>@>>><<>::9<9775<553<33<11:1:/:/::/:/9.99..9..7.7.5.,5,5, 3 1, 1 / /, . ,, , *, * ( (* & & &*$$*""*"*1!!,$,*,1,*I$I=:9:FI?!<,8!1I?D@I8D8IN9R1Q1Q1Q1Q1Q1O9Q1O9Q1N1O9TI[IX>O9Q<X>X>X<X<W<W<W:W:W:W:W:W:W9W9W9V9V9V9V9U9U9P9P:P:Q<H!HININ*R!Q*Q*Q*R*S!R*Q<P:S!R*Q<T!R*Q:U!S*Q:V!S*V"S,W"W"W"S,W"W$X$X$S,Y&Y&Y(Y(S,Y*Y*Z,S.Z,Z.S.Z.Y/Y/S.Y1Y1Y1S.Y3X3X5S.X5W5S/W5W7S/W7W7W7S/V7V7S/U7S/S/S1R1R1R1Q:n!\!\,a,g,n,gIaI       ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*0/.10.32/03/542352764574986796;:89;8=<:;=:@?>A@>CB?@C?EDBCEBGFDEGDFGFJIHKJHMLIJMIONLMOLRQPSRPUTQRUQWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^dcbedbgfcdgcihfgifkjhikhmljkmjonlmolqpnoqnsrpqsputrsurxwvyxv{zwx{w}|z{}z~|}|~~KHK             ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*/.,-/,210320541251764574986796;:89;8=<:;=:?><=?<A@>?A>CB@AC@EDBCEBGFDEGDIHFGIFLKJMLJONKLOKQPNOQNSRPQSPUTRSURWVTUWTYXVWYV[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebgfdegdihfgifkjhikhnmlonlqpmnqmsrpqsputrsurwvtuwtyxvwyv|{z}|z~~               ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*/.,-/,210320541251764574986796;:89;8=<:;=:?><=?<A@>?A>DCBEDBFGFJIHKJHNMLONLRQPSRPVUTWVTZYX[ZX^]\_^\ba`cb`fedgfdjihkjhnmlonlrqpsrpvutwvtzyx{zx~}|~|             ! !#" !# %$"#%"'&$%'$)(&')&+*()+(-,*+-*/.,-/,210320541251764574986796;:89;8=<:;=:?><=?<A@>?A>CB@AC@EDBCEBGFDEGDIHFGIFKJHIKHNMLONLRQPSRPVUTWVTYXUVYU[ZXY[X]\Z[]Z_^\]_\a`^_a^cb`ac`edbcebgfdegdjihkjhmlijmionlmolqpnoqnsrpqsputrsurwvtuwtyxvwyv{zxy{x}|z{}z~|}|~~             ! "!!"#"$##$%%$&$'&&'(')(()**)+),++,--,.,/../00/1/211234545644676877898:99:;:<;;<=<>=>?==?@?A@@ABACBBCDCEDDEFEGFFGHHGIGJIIJKJLKKLMMLNLONNOPPOQORQQRSRTSSTU2V33VWWVXVYXXYZT[UU[\[]\\]^Y_ZZ_`]a^^abacbbcdceddefegf`_h_ihhijikjglfflmlnmmnonpopqooqrqsrstrrtutvuvwuuwxwyxyzxz{xx{|{}|}~||~~kkj              ! " #""#$#%$$%&&%''%(%)(()**)++),,)-).--.//.00.11.2.322344355363766788797:99:;;:<<:=:>==>??>@@>A>BAABCCBDDBEBFEEFGGFHFIHHIJJIKILKKLMMLNNLOLPOOPQQPRPSRRSTSUTTUUVV!VW!WX!XY!YZ!Z!![[^]\]_\a\`\_``_b_cbfedefgeghiehjfdjdkihlmilnjknkopnopoqmlrsmrsrtustvpqvqwxvwxwyzxyzy{|z{|{}ut~u~~|}|                ! "!#"#$%#$&%$'&$'$()'(*)(*(+,*+-,+-+./-./.01/0102312324345635657867879:89:9;:;<=:<>=<><?@>?A@?A?BCABCBDECDEDFGEFHGFHFIJHIJIKLJKLKMLMNOLNONPOPQOQRSORSRTSTUVSUVUWVWXYVXYXZYZ[Y[\]Y\]\^]^_]_`a]`a`babcdacdcedefgdfgfhighihilkjmljjonmjnmnpqmptsrutrurvwuvxwvxvstzystysy{xs{|x{~}}}}}}~}~}}~~~~~}}~~~~~Frame1r !! !  j kjkkhh-h-h"g"gZg[Z [ [ ]]] ]YYTTTTSSOO O O GG G""- - -h'k'k-h#j#kjj    #!# '! '! - -  GGGOOOOSSTTTTYY]]]][Z[[gZgghh%TlOlO%Tlllll l OOOhOlhOlhOhOlllOll]l]ggggggZZZZ[Z[[]]]]]] Y Y"Y"Y$T$T'T'T*T*T+T+T-T-T.T.T0V0S1V1V2S2V3O3O5O5O6O6O7O7O7G7O8G8G8G998G::::;;;;;;<<< < < < < < fKAK<GEGEKIGHKMGKK GK KGGKGKGKGKKGEBs x xusu| |u u u u6666vv\nlssnrr999{{9oo9cc9WWOv[}OC}CO[9UUEE9aaE9aUaa9a99        !  $#"#%"$$"('&(&)()*(*+(+,(,-(-.(./(/0(01(12(23(34(45(56(6'&'7'87)&9&79*):)9:+*;*:;,+<+;<-,=,<=.->-=>/.?.>?0/@/?@10A0@A21B1AB32C2BC43D3CD54E4DE65F5EF'686F8IHGHJGLIKIGKONMNPMROQOMQTRSRQSVTUTSUYXWXZW\Y[YW[^\]\[]`^_^]_cbabdafcecaehfgfegjhihgimlklnkHmJmkJGJJKGGMPPQM M SQ Q USS WZZ[WoWo][[o_]]addeaageeig!g!kn$n#$Jkk$rqpsrputqruqwvtuwtyxvwyv{zxy{x~}|}|}}"frame1ړ ړ ~ړ~!ړd d KK66'O6O'H6O%6]O']%6]O'] KZ%6Z Kg%6Zdhdh ~k ~k%j%jO%O%|5~6C]9C@CE,SE%d6,v8@8]: 2 Ӑ 2|%-v%Ӑ#d,d,M(S(9ICI,JCK9J9H'U6@R,_]9f,9^@CfMb@Cc,Sb,9a dp%dp|n,vn,@R@],"U!ˠːːoo_g_koZoZT^hTT^hT ^ ^ >ch>h>k>c>>cc ! XXXŧ XjXkŧ!X˚˵!ᵮᚖ˚ eƉeƄJgJkeZeZJeeƏ˚Ə˵˚5ͯ TͯOO5T5&2]Y5la4O5ll 5#OX~frame2~~~q q ~\q\!~q~B B ~))~&~OOH~O~%]O`%]~O]~ )Z%Z )g~%Z~BhBh~ \k \k~%qj%qj~O%qO~%qZ5\C]C@!D,0E%B6,T8@c8]n:{ q n2 n c2Z%c-T%n#B,B,+(0(I!I J!KJHU@R _]f,^@!f+b@!c,0b,a Bp%BpZn,Tn,n@cR{@c]n,nU}!ɠɐ}ɐoo_g_ko}Zo}ZTAh>vh>}k>}A>>A}A !v XXXç XjXkç!Xɚtɵ!ߵߚtɚߚ eeJgJketZetZJeteɚɵɚt͍ zT͍OްOzT&2]ހzYla4Oހll߰ #O[0frame3n noڜ ڶ oڶ!oڜom pTn&p>Y&p0OYOKHp>Op%>]OK`%Y^pO0]p TZ%YZ nap%>Zomhho k ko%j%jnO%Oʼno%<<40.)={?v?tFmvF]{FR7O6R8]|h>h>k>|>>|| ! XƛXƛXƉ XjXk!Xт!ϵϚΚeeJgJkeZeZJݏeŏݏeݏŏ$  ͇ tT ͇OO%U$& 2]oT$la 4O$ll $#O]0frame4k kkڜ ڶ kڶ!kڜlm lTn&l>Y&m0OYOKHl>Ol%>]OK`%Y^mO0]l TZ%YZ nal%>Zlmhhk k kk%j%jkO%Oʼnk%0<4..3={=v=tCmvE]{ER7O7R8]:m<1;0Ӟ/ڌ)z=k=a>]C]aD@kE,zE%6,8@]: 2 ӵ 2%-Ӟ%ӵ#,ڌ,r(z(_(kLQJkKaA_HM@]BRQ_]af,_f@kfrb@ke,zb,_a p%pl,,@R‡@],FUmm!lloƂom_g_kmoZoZTwhmTnThhTǂ mw nh >|h>h>k>|>>|| ! XƏXƏXƉ XjXk!Xт!˵̚˚eeJgJkeZeZJݏeŏݏe􏶚􏶵ݏŏ   ͇ tT ͇OO!U!& 2]oT!la 4O!ll !O],frame5m mmژ ڨ nڨ!mژni y nP`&n;K&n,OKOMC]QD@[D,jE%|6,8@8]: 2 Ӧ 2#-ӎ%Ӧ#{,|,c(j(O([LBJ[KQAOH>@MBRB_]Qf,Of@[fcb@[b,jb,Oa {p%|pl,n,@R@],7Uoo!oooÂoلo_g_kooZoZTmhoTpTdhT om pd >rh>h>k>r>>rr ! XXX XjXk!X!εΚΚee脹JgJkeZeZJʏeʏe⏹⏹ʏ#  ͗ T ͖OO#U#& 2]T#la 4O#ll ##O] +frame6vvvڗ ڡ vڡ!vڗvh r vNYv9Cw+OCO5Hv9Ov%9]O5`%C^wO+]v NZ%CZ Ygv%9Zvhhrhv k kv%j%jvO%Ov%0EC]IC@SE,bE%t6,o@]: 2 Ӟ 2#-ӆ%Ӟ#s,t,\(b(H(S(;JSKIJHH6UE@R;_]If,H^@Sf\b@Sb,bd,Ha sp%tpn,n,@R@],0Uxx! xxooτx_g_kxoZoZThhxTxTbhT xh xb >mh>h>k>m>>mm ! XXX XjXk!Xšµ!׵ךךeقe݄JgJkeZeZJeeٔٔµš,͟ T͟O O,U,&2] Y,la4 O ,ll ,# O])frame7}}}ڕ ښ }ښ!}ڕ}f k }MR}7=&})O=O.H}7O}%7]O.`%=]}O)]} MZ%=Z Ra}%7Z}fhkh} k k}%j%j}O%O}%5=>]AD@KD,ZE%l6,~8@8]: 2 ӗ 2%-~%ӗ#l,l,T(Z(AIKI3JKKAJAH/U=@R3_]Af,A^@KfTb@Kc,Zb,Aa lp%lpn,~n,@R@],)U!ȠȐ~Ȑ~ooƄ_g_koZoZTchTT`hT c ` >hh>h>k>h>>hh ! XXX§ XjXk§!XȚȵ!޵ޚȚݚ eωe҄JgJkeZeZJeeϏȚϏȵȚ2ͧ TͧOO2U2&2]Y2la4O2ll 2#O[QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/v_star.mdl000066400000000000000000001572441475442401000254740ustar00rootroot00000000000000IDPO >T{>`:=1tA"B@@8%q@0  fg\g0  0  f[h0  0  hZg[0  0  begg0  0  fgZ0  0  ffZg0  0  ffff0  0  fe]e0  0  ]g0   xdh !#$'*,))$#gfh[!#$'*,))$#!#&(+-+(&#[ghf!#&(+-+(&#00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!$&)*-+)&#ded00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!$&)*-+)&#00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!#%(+-+(&$uuc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!#%(+-+(&$00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!#%(+-+(%#de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!#%(+-+(%#00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!#&(+-+(&#fff0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(%#ef0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(%#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#duae0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+)&$0000MMMMMMMMMMMMMMMMMMMMMMhMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+)&$0000000MMMMMMMMMMMMMMMMMMMMMMhMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#uuc0000MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)%#vux0000MMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)%#0000000MMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(&#uvr0000MMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(&$ff0000MMMMMMMMMMMMMMMMMMMMMf MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(&$0000000MMMMMMMMMMMMMMMMMMMMMf MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#f0000MMMMMMMMMMMMMMMMMMMMMM fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMM fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(&#fffd0000MMMMMMMMMMMMMMMMMMMMMMz MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(&#0000000MMMMMMMMMMMMMMMMMMMMMMz MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#fee0000MMMMMMMMMMMMMMMMMMMMMMM fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMM fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-*(%#ffYf0000MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-*(%#0000000MMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#Yffc0000MMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)&#fffW0000MMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)&#0000000MMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#g[ee0000MMMMMMMMMMMMMMMMMMMMMMMM wMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMM wMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(%#ggf0000MMMMMMMMMMMMMMMMMMMMMMMMg gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-+(%#0000000MMMMMMMMMMMMMMMMMMMMMMMMg gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#hig0000MMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(%#hh[f0000MMMMMMMMMMMMMMMMMMMMMMMMM   gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)+-*(%#0000000MMMMMMMMMMMMMMMMMMMMMMMMM   gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&$gff0000MMMMMMMMMMMMMMMMMMMMMMMMMM  fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMM  fMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%)*-*(&$jdf0000MMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%)*-*(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#hgg0000MMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)&#hYh0000MMMMMMMMMMMMMMMMMMMMMMMMMMeMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&)*-+)&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMeMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(&$gghj0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMM00!#%(*-+(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMM00!#&)+-+(&$[gii0000MMMMMMMMMMMMMMMMMMMMMMMMMMMxcMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMfh MMMMM00!#&)+-+(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMxcMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMfh MMMMM00!$&(+-+(&#[ihg0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMM00!$&)+-*(&$gfd\0000MMMMMMMMMMMMMMMMMMMMMMMMMMMM##"KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMe MMMMMMM00!$&)+-*(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMM##"KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMe MMMMMMM00!#%(*-+(&#dgg0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMf&"$MMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMM00!#%(*-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMf&"$MMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMM00!#&)*-*(%#de[g0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM#!##MMMMMMMMMMMMMMMMMMMMMe  MMMMMMMMM00!#&)*-*(%#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM#!##MMMMMMMMMMMMMMMMMMMMMe  MMMMMMMMM00!$&(+-+(&#fdg[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM!#$MMMMMMMMMMMMMMMMMMe   MMMMMMMMMM00!$&(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM!#$MMMMMMMMMMMMMMMMMMe   MMMMMMMMMM00!$&)*-+)&$dehg0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMe"MMKMMMMMMMMMM  gMMMMMMMMMMM00!$&)*-+)&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMe"MMKMMMMMMMMMM  gMMMMMMMMMMM00!#%(*-+(&#ef[g0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMe""bJMMMMMM  MMMMMMMMMMMM00!#%(*-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMe""bJMMMMMM  MMMMMMMMMMMM00!#&)+-+(%#[fh[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##"##"cMMcc# MMMMMMMMMMMMMM00!#&)+-+(%#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM##"##"cMMcc# MMMMMMMMMMMMMM00!$%(+-+(&#[ggg0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$"!""#޼"!"  MMMMMMMMMMMMMM00!$%(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$"!""#޼"!"  MMMMMMMMMMMMMM00!$&(+-*(&#h[hh0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!޼!!"!#%MMMMMMMMMMMMMMMM00!$&(+-*(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!޼!!"!#%MMMMMMMMMMMMMMMM00!#%(*-+(%$[hgf0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!!߾߾!߾#gMMMMMMMMMMMMMMMM00!#%(*-+(%$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!!߾߾!߾#gMMMMMMMMMMMMMMMM00!#&)*-*(&$hf0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMI""!"""#gMMMMMMMMMMMMMMMMMM00!#&)*-*(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMI""!"""#gMMMMMMMMMMMMMMMMMM00!$%(+-+(&#h[gf0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""!#""!#gMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""!#""!#gMMMMMMMMMMMMMMMMMMM00!$&(*-+)&#g\g[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMe޾!"#"߮""!"MMMMMMMMMMMMMMMMMMMM00!$&(*-+)&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMe޾!"#"߮""!"MMMMMMMMMMMMMMMMMMMM00!#%(*-+(%$\hgh0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!߮߮"MMMMMMMMMMMMMMMMMMMMMM00!#%(*-+(%$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!߮߮"MMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&$fgg[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!#!!"#MMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM!!#!!"#MMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#f[g0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMG!MMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMG!MMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$ch]h0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK"#  """MMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$ 0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK"#  """MMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-*(&#f\hd 0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! MMMMMMMMMMMMMMMMMMMMMMMMMMM00!#%(+-*(&# 0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! MMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&#gid 0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM߻ MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&# 0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM߻ MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&$[ifg 0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! !""MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&$  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM! !""MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(*-+)&$gghg      0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM# P"JMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(*-+)&$     0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMM# P"JMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(&#chZZ  0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMc  !!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(&#  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMc  !!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&#Yegg  0000MMMMMMMMMMMMMMMMMMMMMMMMMMJ"" ߾"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&#  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMJ"" ߾"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&$ihjf  0000MMMMMMMMMMMMMMMMMMMMMMMMMMMbݼ! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&$  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMbݼ! MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#jgf  0000MMMMMMMMMMMMMMMMMMMMMMMMMM! !cMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#  0000000MMMMMMMMMMMMMMMMMMMMMMMMMM! !cMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*(%$gd  0000MMMMMMMMMMMMMMMMMMMMMMMM"!! #"dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*(%$ 0 0000000MMMMMMMMMMMMMMMMMMMMMMMM"!! #"dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&$hdg 00 0000MMMMMMMMMMMMMMMMMMMMMMMMu##!## ޾JMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&$ 0 0000000MMMMMMMMMMMMMMMMMMMMMMMMu##!## ޾JMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#[h]f  0000MMMMMMMMMMMMMMMMMMMMMMM$"!!!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#  0000000MMMMMMMMMMMMMMMMMMMMMMM$"!!!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#iigg  0000MMMMMMMMMMMMMMMMMMMMMe"#߮#!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#  0000000MMMMMMMMMMMMMMMMMMMMMe"#߮#!MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(%$]jh  0000MMMMMMMMMMMMMMMMMMMMg!$"!""߼MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(%$  0000000MMMMMMMMMMMMMMMMMMMMg!$"!""߼MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&$iii  0000MMMMMMMMMMMMMMMMMMMf"""!#߾"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&$  0000000MMMMMMMMMMMMMMMMMMMf"""!#߾"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#iih  0000MMMMMMMMMMMMMMMMMMf#""!1!"ݭ!!dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#  0000000MMMMMMMMMMMMMMMMMMf#""!1!"ݭ!!dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$i^fj      0000MMMMMMMMMMMMMMMMM """"!߮"!ݹMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$      0000000MMMMMMMMMMMMMMMMM """"!߮"!ݹMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*(&#f\ 0000MMMMMMMMMMMMMMM ޻""߼!1#""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*(&# 0000000MMMMMMMMMMMMMMM ޻""߼!1#""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&#ih 0000MMMMMMMMMMMMMMx  #GF!߮!"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&# 0000000MMMMMMMMMMMMMMx  #GF!߮!"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(%$^h 0000MMMMMMMMMMMMM aMMMKMM$""߼#$MMMKMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(%$ 0000000MMMMMMMMMMMMM aMMMKMM$""߼#$MMMKMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$hi0000MMMMMMMMMMM FaMMMMMMMMMI!MMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$0000000MMMMMMMMMMM FaMMMMMMMMMI!MMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(&#gig0000MMMMMMMMMMM MMMMMMMMMMMMMu$KMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(&#0000000MMMMMMMMMMM MMMMMMMMMMMMMu$KMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&#fgjf0000MMMMMMMMMM MMMMMMMMMMMMMMMMM$MMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)+-+)&#0000000MMMMMMMMMM MMMMMMMMMMMMMMMMM$MMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(%$gig0000MMMMMMMM  eMMMMMMMMMMMMMMMMMMMc##eMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(%$0000000MMMMMMMM  eMMMMMMMMMMMMMMMMMMMc##eMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#hY[0000MMMMMMM  MeMMMMMMMMMMMMMMMMMMMMMIa$MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#0000000MMMMMMM  MeMMMMMMMMMMMMMMMMMMMMMIa$MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*)%$fe[]0000MMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMH$MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*)%$0000000MMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMH$MMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&$ff]0000MMMMM ggMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$#MMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&)*-*(&$0000000MMMMM ggMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM$#MMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(*-+(&#i\h0000MMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMF"MMMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(*-+(&#0000000MMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMF"MMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#ijii0000MMMx gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&#0000000MMMx gMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(%$iii0000MMMh ggMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(*-+(%$0000000MMMh ggMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-+)&$ji0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-+)&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#hhf0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMM00!$%(+-+(&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  MMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$hM0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  eMMMMMMMMMMMMMMMMMMMMMMMMM00!$&(+-*(&$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM  eMMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*)&#vfi0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMMMMMM00!#&(+-*)&#0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMMMMMM00$')+-+)$hfyf0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMM00$')+-+)$0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMM00  hff0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMM00  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMM000  ddfe0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMx MMMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMx MMMMMMMMMMMMMMMMMMMMMMMM000  fdX0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMMMMMMMMMMMMMMMMMMMM000 "fdg[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMMMMMMMMMMMMMMMMMMMM000 "0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM gMMMMMMMMMMMMMMMMMMMMMMM000  df\0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMM000  fi\0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMz MMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMz MMMMMMMMMMMMMMMMMMMMMMM000  heZ0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  geZ0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  iMf[0000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMM000  h[i000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMg MMMMMMMMMMMMMMMMMMMMM000  Zgg000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMM000  ]h000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMfMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMfMMMMMMMMMMMMMMMMMMMM000  h^000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  ii000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  0000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  hh00000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  00000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  ge\i00000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  00000000000000000000000000000000000000000000000MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM000  ]ii0000000000000000000000ux0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  000000000000000000000uwx00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  i00000000000000000000vxxzzzz000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  0000000000000uwxyzzx000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  v00000000000ϯuvvvxxxxzzzzzzz0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  0000000rwwwwyxwx0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  gg0000000uwwxxyxyyzzzzzyyyx000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  000vvsruuwwxyyx00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  fhg000wuvvwyzzzyyyzzzzzzzyxxxwxyw0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  000uxwxwvusuvvwxxyyzy00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  [g]f000wzzzywxyzzzzyxzzyyyxyxwwvvwzzyy00000000000000000000000000000000000000000000000000000000000000000000000000000000000000  000vyyxxwwwwvsssruuuwwxxyzzyw000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  gh[000zzzzxxxxzzzyyxxyxxxxwvvvwxxxyz000000000000000000000000000000000000000000000000000000000000000000000000000000000000  000vyxxxxxxwwxvvvvvvvuuuwwwxyyxxxy0000000000000000000000000000000000000000000000000000000000000000000000000000000000000  [hYi000wzzyywwwxzzyyyxwwxvvvwvvvvwxxxzzz0000000000000000000000000000000000000000000000000000000000000000000000000000000000  000vxxyxxxyzyzxxwvvwvvwvwwwwxxzxwwxy00000000000000000000000000000000000000000000000000000000000000000000000000000000000  h]hh000yyxwxwwxyxxwwwvvuvuuvvvwwxyzzzz000000000000000000000000000000000000000000000000000000000000000000000000000000000  000wwwxyzyyzzzxxwwwwwxwxwwxxyyxwwwwxx0000000000000000000000000000000000000000000000000000000000000000000000000000000000  ]gh000vxxvxxxxxxxxvssssuuvxxxyzzzzy000000000000000000000000000000000000000000000000000000000000000000000000000x0  000uwwwwwzzzzyxxxxxxxxxxxxxyyzzxwwwwwwx0000000000000000000000000000000000000000000000000000000000000000000000000000y0000  hh\h000uwvwyyyyyxxvruuwxxyxyyzzzz00000000000000000000000000000000000000000000wzxyyzyxyzzyyzyyz0  000uwwwwwwyzzzzzzyyyyyyxyyzyzzzzxwwwwwwy00000000000000000000000000000000000000000000zzxzyzxyzzzyzzxzzz0  \gg]000suwxzzyzyxusvvwwxxxxzzzzz0000000000000000000000000000yzzyyzzyyzyyyzyzyxyzyyzzzyzyyzzz0  000vvwuvvwyzzzzzzyxyyyzyzzzzzzzxxxxxwxwxw00000000000000000000000000szzyyzzxzyzxyyzzyxyyzzzyzzzzxzzzzy0  [hf]000uxzzyzyxvbsrssuvwxxyzzzzzy000000000000000Ϫvuuuuuuuvzyyyzzzyzyyyyyzyyxyxyyyyyyxyyyxyyyyzyyzyxzyyxzz0  000uuuwwxxxyyyyxxxxzyzzzzzzzyzxxyxxxxxuu0000000000uuuuvvvxzzzzzyzzzyzzzyzzyxxyzyzzyzzxzzzyzzyyzyzzzyyzzyyz0  h[g00wzzzzyxusuuusuuvwxxyzzzzzzwywxwxwyyyyyxxxyyyxxxyyxxyxyyxzxyzxxyxxxxxxxxyyyyyyyxxxxyzyxyyyzxxyyyxxzy0  000ruusuuvwwxyxxwwwwxxxxxxyyyyyyyyxxxxxyyyxwxwxwxwxxxxyyyyyyyyyyzzyyzyyxyzzzyzyzyyyxyzyyzxzzxxyzzyzyxzyzzzyxzzxyzz0  gxh00xwyzxxuusuvvwvwusuvvwxxxyzzzzyxzyyyyyzzzzzzzyyyxyxxyxyxxxyyxwyyxxxyxxxxxxxyyyxxyxyyxxxxyyyxxyxyyyxyxyyzyy0  00wuuvvuuuuvvvwxxyyxwwwwwwwxwxxxxyyyyyyyxxyyyyyzzzzzzzyyyyyyyyxyyyyyyyyyxyzyzxzyyxxzxyzxyzyyzxxzzyzzxxzzyyzxxxzyzzyy0  ]gYf00uyywwvsrvwvvvstsuuvvwxxxyyzzxyxxxxzzzzzzyzxyxxxxxxxxwwxxxwxxxxxxxxxxxxxxxxxyxxxxxyxyyxyxxyyyyxyyxxyyyyy0  00xwvwwwvuuvvvvvvuwwxyxwwwwvwwwwwwwwxxyyyyyyyyyzzzzzzzyxyyxyxxyxyxyyxxyyxxxyyyyyxzxzzyyyxzzyxxyzyzxyyxyyyyxzzyzyzzzzz0  iffg00zzxvssuvursuuvwwxyxyyyxxxwxxzzzyyzxxxxxxxwxwwxwxwxwwxwwwxwxxxxxxxxxxxxwxxxyxxxxxxxxyyyyxyyxyyyyyyx0  00uzzxxwxwwxwwvvuuuuvwwyxwwvvwwvwwwvwwwxxxxxyyyyzzzzyxyxwxxxxxxxxxyyxyxxyyxyxxxxxyxxyxxxxzxyxxwzxzxxzxyzyzzxyxywzyzyzz0  hhd00zzzxvssuuuwwwwxxyxxxvwwxyyyxxxxwxwxwwwwwwwwwxwyyxxxwxwwxwwxwxxxxwxxxxxxxxxxxxxxxxxxyxyxyxyxxxy0  00zzzyyxzzxxwwvuuuuvwxxyzxyxwwwvwvwvwwxyyyxxxxxwwyxwwxxwxwwxxxxxwxyyxxyxwxyyyxyxxxyxyyxyxywwyxxyzxxxxxxyzzxzxzyxzzz0  fffs00uzzzxuvvvursuvvvvwxxxwyxwxwxxxxwxwwwwwwwwwwwwwxwxxyyxxxwwwwxwxwwxwxxxxwwxxxxxxxwxxxyxyxxxxxxxyxyxxy0  00xzxyyyyyxxwwvvuuuvwwxyyzzzzzyxxwvvvvvvwxxwwwwwwwwwwwwwwxwwxwwwxwxyxxwwxwxxywxyxwxxxxxxyxyxxxwxwxwwxxwxxxzxzyzyxzyzz0  eXhs00yzywuvwyyxwwwvusuuvvwwwwwwwwwxwwxvvvvvvwwwwwwxwwxwxwwwwxwwwwwwwwwwxwxwwxxwxwxxxxwxwxxxxxxxxyxxxxxxxxyx0  00xwxyzzzzyyxxwxwwwwwwvwvuvwwxxxxxxxwvwuvvvvuvuvvvvwvwvwwwwwvwvwwwwwxwwwxwwxxxwxxwxwxxxxxxwxwwwwxxwwxxwxvxyxxxyxxxyyxx0  fd00xxxwvuvvxzzxwvvvuuusrsuuvuvvvvwvvwwwwwvvuuuuvuvvvvvwvvwwwwwwwwwwwwwwwwwwwxwwwwxwxwwxwxxxwxwxxwxxxxxxyxxxxxxxx0  00wwwwxyzzzzzzyxxxwxwwvvuuuvvuuvuvvvvvuvussuvuuuvvvvvvvvvvwvwwwwwwwxwwwwwxwxxxwxxxxwwwwwwxxwwxwwwxxxwxxwxxxxxx0  gfff00wxxxvuvvxyxwvvvuvvuusrruvvvvuuwwvvvvvuuvuuuuuuuvvvvvvvvwvvvwvvwvwwxwwwwwwwwwwxwxvwxwwxwwxwwxwxxxxxxxxxxx0  00vwwwvvxyzzzzzzxxxwwwwwwvwvvuvuuuusssvuvuuvuuvvuwwwwwwwwwwwwwwwwwwwxxwvwwwwwxwwvwwwwxwxwxvxxxwxyy0  f[f[00uwwvvvxyxwvvwwxwvvvvuuuuvuuuvvuvwwuutuuvuuuuuuuuuuuusuuuuvvwwwwwvvvvwvwwwwxwwxwxxwxxwxwwxwxxxxwwxwxx0  00uvvwxwwwvwwxxxxxxxwwwwwwwwwvvvvuuursuuuuuuvvvvvvvwvwwwwwwvwwvwwwvwwxwwwwwwwxwwvwwwxwwxwwxyy0  gZh00suvvvwyzxvvwwxwvvvvuuuuwvuuvwuuuxxwwvvuuuvuuuuuuwvvuuuuuuuvvvvvwwwwwwwwwxwwxwxwxxwxxwwxwxwx0  00ssvvuuuuuvvwwwxxxxxxxxyxyxwwwvvvurssuuuuuuuuuutuvvvvvvuuwvvwvvwwvwwvvwwvwwvvwwwvvvwxvwxxwwwwyx0  g[f00uvvxwwvuvvwvssruvuvvuuwvuvvwvwwxyzyxwwwwwwvwvvvuvwwwxwvuuuuuuvuvvvvvwvwwwwwxvwxvxwwxwxwwxwxxwxx0  00suusvuuuvvwwxwxxyzzzzyxxwwwvuvuvuvuvvvvvvvuuvuuusuuuuuuuuvuvvuuvvvvuvvvvwvvvvwvvwvvvvwwvwwwwvvwwwwx0  \jh00xvusrsvvwuuu`uvvuvuvxxxxzyyyzzzxxxxxxwwxwxyyzzxwwvvvuuuuuuuuuvvvvvwvvwwwwwwwwwwwwwxwxwwxwxw0  00wuuuvwvvuwvvusvvvwwwwxxyyxxwwwwwwwxwxwwwwwvwwvvvuuuuuuuuuuuuuuuvuvuuvvvvvwvuvvvwuvvwwvvvvwwwwwuww0  g[h00xyxvuussrssuuuuuuvvxxxxyyxyyzzzyxxxxxxxyzzzzxxxxxxwvvuuuuuuuvvvvvvvvvwvwvwwwwwwwwwxvxwwxwx0  00xwwwxxwwwwwwvvuuuuwxxyyyxxxwwwwwwwwxxyyyxxwwvwwvvvuvvvuvuutuuuusuuuvuuvuuwvvvwuvvuvvwvvwwvwuwvwvv0  \ig00yzzyyxvvuvuvs`ruuuuuevvwvvwvwxxxvvuvvuvwxxxwwvwvvvvuuuduuuuuuuuvuuvuvvvvvwvwwwwwwwwwwwwwwxv0  00xyyxxxyyyzwwwwwvvvvwvvwxyzzyxxxwwwwwwwwwwwxxwxwwvvvvvvvuvvvuvuvuuuuuusuusuuuuuuuvuvuvvvvvwvuuuuuuu0  ^^h000yzzzzyxxxyxvwssruuusssusrsuusuuuuuuuuuvuvvvvvvvwvwwwwwwwwwwww`0  000uxzyyyyyzyxwwwwxwxwwxxzzzxwwwwwwwvwvvvvuvvvvwvwvwvvvvvvwvwvvuvvuuvuuuuusustrssuuuuvuvwuuwuv0  j]000uxyzzzzyyzyxwvuuuus4sruussussrssuuduuuuuuvuvuvvvvwwwwwwwwwwwwwww0  000vvxxyyzzzyxxxxxxxwxwyyxwvvvvvvvvuvuvuuuvvvvvvvvuwvwwwwvvvvuvvuvuvuuuuvussrssuuvuuvvuuvvuvu0  ]f000svxyxyxyyyywvvuvvvuusrrsuvvvuuuuuvwwwvvvvuuuvvuuuuusuuuuuuuuvuvvuuuvuvvvvvwvwwwwwwwwwww0  000uwwwwyzzzyxwwwwvvvuwxwvutssrsvuuuuuuuuuwwwvwwwwvwwvuuuuvuwuvvvuusssrsssuvvuuuvuu0  i]h000uvwxxxxwwxwvvwwwvusruvvvvuuwwvvxxzzxxwwwvvvssuuuuuuuuuuuuuuvvuvvuuvuuuvvvvvvwwvvwwwwwwww0  000uuvvwxwwwwuuuvussrtuuuwxwwxwwwwvuuvvuuvvwvvvuuuvuussssrsusuuu0  \][000uuvvwvwwwvuuvvwusvvvwwwwvuvwwwvwwwxxxxvusuuuuuuuuvuvuvvuuvuvvvvvvvvuuvvvvvvvvwwvwvwwwwwwww0  0000rsuuvvstussrssuuuwwxyzxwwvvuuuvuuuuvuuvuuuuuvuuuuuussrssssrs0  h]i000uuuuwvuusb`uvvwwxxxwvuvxvwtuuvwwvuuuuuuuuuuuvvvvvvvvvvwvwwwwvwwwvvvwvvvvwvwwwvwwvwwwwwwww0  0000assrssuuusuuusrsuvwwyzyxwwuuuuuuuuvuuuvuuuuuuuuuusssrssssr0  ]\0000ussssrssuuvvxxxyxvvvuusuuvvvvvwwvwvvuvwwwwvvvvwvwwwwwwwwwwwwwwwwwwwwvwwwvvwvwwwwwwwxwx0  0000suuvurssuuuuuuuuuuuuuvvuuutssrsuvwwywwwuuuuduuuuuusssrssssr0  ]]h0000vvvvuuuusssuvwwxyxxxvvuuuvvvvwwuuvwxxxwxwwxwwxwwwwwwwwwwwwxwwxwwwwwwwwwwwwwvwwwxwwwwxwwxw0  0000uuuuuvvuuuvvvuuuuuuuuuuvvvvvvvuuvvvuusrssuvwwwwuuussrtssssrs0  fg[0000vxxwxwwvvuuvuur4suvwwvwxxxwvussruuuvuvwwvvvwwwwxxxxxxxxxxwxwwwwwwwwwwwxwwwwxwwwwxwwwwwwxwwwwwxwxwxw0  0000vvwvvvvwvwwvvvvvuvuvvwvvwwwwwvvvvvuuussssrssssrscsssrssssr0  ]e0000wxxyzyxxxwxxvvtsssuvvvvvwwxwvvsrsuuuvvvwvwwwwxwxwxwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxwxwwxwxwxwwxwx0  0000wwwwwwwxwxwwwwvwvwvwwwwwwwwwvvvuvuusssrssssrssssrssssrs0  fcZ0000yyzzzyzyxxwsssruvwwuuvvwwvvssssruuuuvvvvvwwwwwwwwvwwwvvvvvwvvvvvvvwwwwwwwwwwxwwwwxwwxwwxwww0  0000uvwwwxxyyyxxwwvwwwwwwwwwvvvuuuuuussssrssssrssssrss  ^fff00000wwxyzzzxywvtussuuvvvuuuvwvvursussuuuduuuuvvvvvvvvvvvuvvvvvvuvuuuuvvvwwwwwwwwwxwwxwwwwwwwwww  00000suvwvwxxwwwvvvwwwwwwvvvvuuurssssrssssrssssrcsss0  fdYf0000000wwxwxxwwvsruuvvuuuvvvsusssrssssrsuduuuuuuduuuvuvvvvwwwvwvwwvwwvwwvwvv`0  0000000uvvwwwwvuuvuvvuvuvvsssaraas7sssrssraa00  ddc00000000uvuvvussuvuuuvrsbsbssrssssruusuuuuvuuvuvuvuvuvuvuvevu0  00000000uvvvvvuuussaaarsarassssrsa0  yjxd000000000ϟsssrtussssrssssrssuuuuuuuduuuduuuduuu0  0000000000uvssrsssaaarsr00  d0000000000000ssss000arrsbsssrssu0  0000000000000ssrsscssaars6r10  xde00000000000000`24300000000000000000000000000000000000000`sssrssss0  0000000000000000000000000000000000000000000000000000RRara10  fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000``rbss0  000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000PPa00  ide00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  ex>100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000  1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 65= 9= @ CDC@=96 r20 $= wC hI eH @V= a6 S s0 l. x5 z= xD sI lK dI _D ]= _5 d0r2 l0 $ x=wC h lIeH @V _=a6 So6l5r9s=r@oClDhCe@d=e9h6l= K ,9 9 ,K         !w v{ <y;} : < :;ww n )l p (ow)w)) ,w prw                        ! !"!"#"#$#$$%&%'%'('()()*)*+*+,+ ,-, !- .-!".!/."#/"0/#$0#&0$&$12&%1&31%'3%43'(4'54()5(65)*6)76*+7*87+,8+98,-9,:9-.:-;:./;.<;/0</2<0&20;<=:;=9:=89=78=67=56=45=34=13=21=<2=>?@?A@@A>?>ABCDCEDFGBGCBHIFIGFJKHKIHLMJMKJDELEMLDNBBNFFNHHNJJNLLNDCOEGOCIOGKOIMOKEOMPQRQSTSUVUWXWYZYP[\QP\SQ\US\WU\YW\PYTRQTSV]UX]VU^XW^WZZY[_PR_[P`abc`bd`cedcfdegfehfgihgjhikjiljkmlknlmonmpnoqporpqsrqarsbastua`tavt`dv`wvdfwdxwfhxfyxhjyhzyjlzj{zln{l|{np|n}|pr}pu}raur|}~{|~z{~yz~xy~wx~vw~tv~ut~}u~ecRRTeTgeigTTViV]kmk]Xm]omXX^oo^ZZqosqZZ[sRcbRb_[_bkiVbs[w2|v_star1&@`ca]\y\];_:b;d f#fe_dJĉXjXyFą^r=3X7Asw@EG??4S8Kz9Y5Ml5My9Y@] @]GX GXKL$KL"K=&K=F1HF1N?-U?-R82^82[4>i4>s?6C;9D9Ad@E4WLv_star2&@lNlOm}mNoNyqOysPtQtRsS rSoR mQiEiGWVnDkrFzfxK;xL:ysMoK[ii:ipz@4zB9xC*tC pA!l?k0k2]Rp0Zt1[`y6?z7F'Au8q6&aOn*o+o)Pq*\t+\v,^w-Cw.?v/>t.r.p,MvVl݆lلyk~nۀCnӇqkmigp։sq؃ m5p{MeCnyc^oՁkdL^OFtz~R.jR.`ZQOFEZ_L^jozOFgZTfez|ynjaM][HXT^AZ_iFebw8tn2{r j'g(iLo3x50v*f-^v_star3&@ЦyѫxnСiў\ҞaԠ6դ4֩7֮ձ ԲӯyѢvӫwiҕcԔ\{8ٟ5ۨ4܋ڶض j՞vרԔ֎Y؍^ےAޚ+3-ߴܵٱ~ڛۤfۍT݌R^N+(}ߙߔߑSSO','c(R}S R)RoISeS] Rhh;~fBhl?jls4jYjOu-ac^o1y^ham8ufT_Zdl efmq#qr'rnInMh@hTafa]\b\q[m[z__j1f;m/m*k=gCcD`d_obf9[v_star4&@wywx*gnvi w\"xa$z6%{4%|7#|"| zyyxvyw\ixc"{\;s{8&5&47܋ ~ mj{v}{|Y ^$A%+%3"-~}fTR*^N"+"(&SSO',',e,dc)f,h(K L F;C7zECqII WH) tWU`aii!!jdg&#%aX[S KXPrR`]}"+Vǀ vτ 0 %4+CK^V [W r Âz ɉLJ: 8 Ebasn ^v_star5&@wywx*gnvi w\"xa$z6%{4%|7#|"| zyyxvyw\ixc"{\;s{8&5&47܋ ~ mj{v}{|Y ^$A%+%3"-~}fTR*^N"+"(&SSO',',e,dc)f,h({FXeZzWmxL\bY$_g^o} Zr|~0[j ycnRxDS;~VzYlXYyUo]wWX~St^ek>caU\gf_qFhx)a~5j/c1jchae^bt\ztagZma`RZf[kjIieOms(n{$n!m~kxiphhhdNmpA>mv_star6&@HH6tFDWBX@s@h@hADFGMMMeG]CY&~w?k@m-}F~ITʏQQNNJUF`BcAoBnEIMPS Sek(M@IJ>>E8F7F5L O m-RSQ'OAMAK>K9K:LIC>@_7E^7Oe@V49\8Cc0=i;Fj @p ~Hi|BnyH_wBewFRu@XyCEwR|9DXEHKECHGQ=IY*K]%L\!}LV"|JN}HFGBOKN&QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/vwplayer.mdl000066400000000000000000004532241475442401000260440ustar00rootroot00000000000000IDPO ԓ>VY>Gz>C94(}B(&61AFGFGFGFEDFFFrrruuurrrrFGFEDFFFrrrrrrrFGGFEEGFBB``````CCEGGEFGFrrrFGGFEEGFBB```````CCEGGEFGFrrrrrrrrDGFFFEDBBBCCCabbbC`CC``aa`CCECFFFEarraDGFFFEDBBBCCCabbbC`CC``aa`CCECFFFErrrrrrrrDGEEBC`````aa``C`bbba````FErrruurrDGEEBC`````aa``C`bbba````FErrrrrrrrrrrrrrGGDEDDDCCDEFEEEDDBBabaaGGaabccba`CEEErrrGGDEDDDCCDEFEEEDDBBabaaGGaabccba`CEEErrrrrrrrrrrrGGDDDDDCDDCCEGFEDBEba`GG`ba`CEEFFCrrGGDDDDDCDDCCEGFEDBEba`GG`ba`CEEFFCrrrrrrrrrrrrrrrGGEEEDDDD`FGDDDbbaDDE`aGaCCCaAACECErrrrrrrrrrrrrrrGGEEEDDDD`FGDDDbbaDDE`aGaCCCaAACECErrrrrrrrGGGGFDDD`FFb`EEbbbbbaCCCCCEEEGrruwxyyxwwxyyxwurrrGGGGFDDD`FFb`EEbbbbbaCCCCCEEEGrrrrrrrrrrrrDGECCCCCCCCEECAAaEEaaaa`EEEFrrsttuy{}zz}{yuttsrDGECCCCCCCCEECAAaEEaaaa`EEEFrrrrrrrrrrrrGGGEBAADDEEDCCAbcb`bbbaaabaEFrqvtrrstxvxwtsrrtvqrrGGGEBAADDEEDCCAbcb`bbbaaabaEFrrrrrrrrEGDBBBDCCDDCCbbb``bcbba```CEFrrrussrvtrssurEGDBBBDCCDDCCbbb``bcbba```CEFrrrrrrrrrrrBCAADFEFF`CC`abbaccaFFDBBBDEEErtxwvuutvzzvtuuvwxrrBCAADFEFF`CC`abbaccaFFDBBBDEEErrrrrrrrrrrrBAAAECCCEF`abbaDDaBBFDDEEtwyzyxxz}|zxxyzywtrrBAAAECCCEF`abbaDDaBBFDDEErrrrrrrrrCCDCC``DD```abb`abb``FFa`aabbaaCFFrrsvy{zwvz~zvwz{ywsCCDCC``DD```abb`abb``FFa`aabbaaCFFrrrrrrrrrrGGEEFE`a`BB`B`ba`aabaab`abbaaa`FFrrstvywtsuwwustwyvtsGGEEFE`a`BB`B`ba`aabaab`abbaaa`FFrrrrrrrrrrGGGDBBBBBBAABB`aa``abbbaDDFFrrssvvtsstvvsssrrGGGDBBBBBBAABB`aa``abbbaDDFFrrrrrrrrEGGEDBBBCDC``DDFaEEEEEEFCrsrttrrrEGGEDBBBCDC``DDFaEEEEEEFCrFGGFFCBCDEFFDbcbabbbaabbaaEEEEEFrrssuvvvvussrrFGGFFCBCDEFFDbcbabbbaabbaaEEEEEFFGGFCBBBBBBBBEaDDbaababa`abbaFFFrus`uxzzxu`surFGGFCBBBBBBBBEaDDbaababa`abbaFFFvxxxvFFGEBBBDDDCCECC``bcb`bEGDBFFFrxtsstxrFFGEBBBDDDCCECC``bcb`bEGDBFFFsstttututsFEGEDEEEDDBAAAAAbaaa`CDFFFFxsrr`vuvxyyxvuvruFEGEDEEEDDBAAAAAbaaa`CDFFFFuuuuwwwuuFFFGECCCBBCBAAAABBDDBDC``CC`FCFFxsrqquvwwwwwwvrFFFGECCCBBCBAAAABBDDBDC``CC`FCFFxuuuFFCGEBBBCABBDDBDBDCCCCEEFFvqqqxxqqxFFCGEBBBCABBDDBDBDCCCCEEFFxuuxyBBDDCDCFzvqquttuqqqqvyzBBDDCDCFBDFFCFCFyzvtrqqqqqqqqqqqqqqqqvzBDFFCFCFzzBDFIaIa`vttvBDFIaIa`yBDGIbIb`vvttvvvBDGIbIb`wBDbabdb`BDbabdb`BDbabdb`uuBDbabdb`yDbabdb`Dbabdb`xyxDbabdb`xDbabdb`uxababcb`vwxwxxxxwwababcb`wacbbcb`uuvuuuuuuvuwacbbcb`yxacbccb`ssssssssacbccb`xacbccb`uacbccb`wyvacabcb`yacabcb`wvyacbbcb`uwvacbbcb`xwuacbccb`wxwwxxxxwxwwxvuacbccb`xwwacbccb`vvxuvuuuuuuvuacbccb`xwtytvacbcbb`ywssssssssxacbcbb`wwxtacabcb`yysuwacabcb`xxvxacbbcb`xysxyxxvwacbbcb`xwwxvxxwuacbccb`wwvxywtuacbccb`wxwvtwvxxwacbccb`tuvuvwrtuacbccb`utrrrrrwvtxrrrrrtuacbcbb`wwussvvuwtuwvvwacbcbb`xuttutrrrvxwvtwtwvwxwtsrrswyxwvuacbcbb`wxvtvwvusvvuuvxyyxvvwacbcbb`xuvwxyxwurrvvvssvwrrrwyzzzyxwv`cacac`xywvxyzzyxwussuwyz{{{zywvww`cacac`xvwxyzzzywvusrvsttssuvuwxxyzz{{{zywwx`bacac`wyyvwy{|||{zxvusrqrsuvxz{|||{ywvyy`bacac`xxwwyz{{{zzyxxwusvsruutuwyz{{zzz{||{zxwy`bbdab`xyzwxz{|||{zywvtrqqqqqqrqqrtvwyz{|||{zxwzy`bbdab`xywxz{||{zzz{{zywusvustusvxy{||{zyz{||{zxxy`bbdab`xyzxyz{|||{zywvtrqrrqqqrrrrqrtvwyz{|||{zyxzy`bbdab`xyxxz{||{zyz{||{yxvssuwxz{||{zyyz{{{zxwy`bbcab`xyzxyzz||{zzxwutsrssrqqqrrssrstuwxzz{|{{zyyzy`bbcab`xywxz{{|{yxz{||{zxwurqrrsuwyzz{|zyxxyz{zyxwy`cacab`yzzxxyz{{zzywvtsrstsrqqqrstssstvwyzz{{zyxxzz`cacab`xyvwyz{{zxwyz|{zzyxvsqrrstvxyz{{zxwvxyyyywwy`b`aa``yzywxxyzzzyxwutssstsrqqqrsutsstuwxyzzzyxwxyzy`b`aa``xyuvxyyyxvvxz{{zyywurrrrrsuwxyzzywvuvwxxxvvyx`a`````wyzywwxyyyyxwvtsssttsrqqrsttssstvwxyyyxwwwyzy`a`````vxyuvwxxwvtuwxzzyyxwtrrrrstvwxyyxvuutvwwwuvyx`a`````wyzywvwxyyxwvussrtutrqqqqrtutrssuvwxxxxwvwyzyw`a`````vxyuuvwvutttuwxxxxwtsrrrrrstvwxxwuuuuuuvvuwyyvwyzywuvwxxwvutsrsuusrqqrsuusrstuvwwwwvvwyzywvyyvuvvuttuutuvwwvtsrrrrsstuvvutvwvuuvvvwyywwyxywuuwwwvutsrrtttsqqqstttrrstuvwwvuvwyxywwwyyvvvvutvvvtuvvutsrrqrtsstuuttwxwvvvwwxyyxxwxyxxwutuvvutsrruutsrrstuurrstuvvutvxxyyxwxxyywwwwvvwxwuuuttsssrruustuuuvxxxwwxxxxyzzzyzyywwvttuuttssuvutsqqqstuvussttuuttvwyyyzyzzzywwxxwwxxxvuuttttsruvuuuvvwxyyxwxyxxyz{{yz{{zywvttuuttuvwttvuqqquvttwvuttuuttwwyz{{zy{{zywxyxwxyyxwvwvuvvuqvxwvwxxxxzzyxxzzxz{{{z{{{{zywuuvvuuvxuwxvurruvxwuxvuuvvuuwxz{{{{zz{{{zxzzxxyzzyxxxwvwxvvyxwwxyxyz{yxx{zyz{{{zz{{||{zwvvwvuuwvxyxvurruvxyxvwuuvwvvwz{||{{zz{{{zyz{xxyzyyxyywwxxvwyyxwxzxyz{zywzzyz{{zyzz{||{zywxxwvvvz{zwusrqrsuwz{zvvvwxxwxz{||{zzyz{{zyzzxyzzzyxzywxyywswyzywz{xyz{{ywvvxzzzyyz{{{{zywyyxwwy{{yutrqqqrtuy{{ywwxyywxz{{{{zyyzzzxvvxy{{zyx{zwyzywrwxzywzzwxz{{xwvvxzzyyzzz{{{zywzzxxyzyywtsrqqrstwyyzyxxzywyz{{{zzzyyzzxvvwx{{zxwzzwyzywwwyywvvwvxxxwwwwxyyyyz{zz{{yyxzyxxyxxwvvtsrrstvvwxxyyxzzxyy{{zz{zyyyyxwwwwxxxvwvvwxywwuwxxwvvwvuttuwxwxzyyzz{zzz{yyxyxwwxxzzywutrtuwyzzxxwwyzxyy{zzz{{zyyzxwxwtttuvwvvwxxwuvwxwwwxwuttuwwwxyyzzz{{zz{yyxxwvxz{{zywussuwyz{{zxwxyxyy{zz{{{zzyyxwxwtttuwxwwwxwvvwxwwwxxvutuwxwxyxzzzz{zzzyxwxwxzz{{zywussuwyz{{zzxwyxxyzzz{z{zzxyxwxwutuvxxwwwxwvvwxxxyyxwuuuxwxyxyzzxz{{zzyxwwwxz{{zzxvtrtvxzz{{zxwxxxyzzz{z{zzyxyxwxuuuwxyyxxxwvwwxwxwxwvuvuxwxwxyxzz{{yzyxwwxyz{zzyxvssvxyzz{zyxwwxyzyz{zzxyxwxwxuuuvxxwxwxwwvwwxwwwxwuuvvvwwwwyxzz{yzyxwwxzz{zyywuruwyyz{zzxwwxyyyzzzzywwwwvvvuuwxxwxxwwvwwxwxvwvvtuwuvuvxxyzz{yzywvwxzzzyyxvuruvxyyzzzxwvwyyyzzzyxxvuvuwuvvwwwxwxwwvvwvvwwvwvtwuwuwuwyxzzzxyxwuwxzzzyxwutbbbbbbdddddefdbdddiijjjjjhijjjjiidddddefedddbbbbbtuwxyzzzxwuwxyxzzzyywuwuwuwuvuvxwvvwvbbbbbbbbbbbbbbbbdddddddddddddddddddddbbbbbbbbbbbbvwvuvvvvuutvuuuuwyxzzzxyxvuwxzzyxwvtrgggdhhhhhhgfhhhhhhgdgggetvwxyzzxwuvxyxzzzyywuuuutuvuwvvvuvwvgigffiigewuuvwuuvusuvuvvvwwzzzxyxvuwxzzywvusrffdgeeggeeegggffehfefsuvwyzzxwuvwyxzzzxwvvtutututvuuvuuwufffhhfuvuuvuvutstuvuuwyxzzzxyxvuwxzyxvusrefdgefggeggggffefgdefsuvxyzxwuuwyxzzzxywuututusttuvuuvueedggeuutuuuvtssttutvwwyzyxxwuuvxyywutrrefcgfefgegggfeffegceertuwyyxwuuvxxyzyxwvtuvtutttututuuueedgfevtstuvutsstuttvxyzxwxwuuvxyxvtsrdecfefefdddgffeeefcddrstvxyxwutvxwxwuxvttustusttutstvdedfeduvstuuttssyyxwxwuuvxywusrraaaaaaaaaacccaaaaabbbbdddbdbbbbbbaaaaaccbaaaaaaaarsuwyxwustuutttwutstuststuttsvubbbbbbaaaacccbbccccbbbbbabbabbbbbbbbbbcccbbbbbbbbttutsutuvvwvtrrrdeeeddbbbbbbbddddb```````````````bdbbbbbbddbbddbbrsttwuststssrtttsttueefffgcaaabbbeefgfeeeddcbccbcegggeeeedbbbegggeecctuussrrgghggfeffffeeiigffecaaaabbbaabbceggfedefgghgfgfffssuutststrrstsssscghhhddddfdddeefghhheghbdggdghjehhhgfeedddgggefcbrgghggfeffffeeiigffecaaabcccaaccceggfedefgghgfgfffutstsrrssssssccdccehigccciiihiijfahcbdggfghiafjidcccgjjjiigebbghhhfefgfggfhjigfcccbbbceghbdcccefhgfefgfhhihhgggsssscccccfhgdddhfgiiiigaacbbeghfhieaaddddccfhjjiihfbbhggfefgedccikihgcedcccceijidegeeefihgghhghijjihggdcccccgifeeidadhiiigaabbbeghgfgebaddddedadiiiiigbbbhggefgeccdijihggdeeeccdijjjifehifgfihhfeeeefiiffeedcccdcdegghecdgfgecabbcffghegddbbcegfgdcehggedcbbbggefeedddijfeeeebbehheeggghhfehijfehiiiihcceefffggidddgeecceefgeecccebbbcheghedbbebeccceegfeecbeebbbdefdcbbcihfedddecbchjiigggggcehhieeeffhihfcbbeeggghhhhfehgfccddcabdefbbchhdghdbbbdbgedbacddcbbcdebbdeedddfghhccefddeedbgijiijjiccefgdccdffeghebbbbbbccggghedffedffecbfccdbcfhhdffdbbcdbhfffabcffecccddegefcbbcggfaacdijiheeehihhiiibdggfcbbffeeeeebbbbbbaafffcbdfdceghhcacccdbceggceedbbgcbhffeabccgeccccgggedbaabcdcaaadijjigfffghhhhhddghfbbfeecceeeffgedaaafcbbbdccceghhcabcccbceffcddcceecbhffeabcccdfddcfggbaabaabccccbadggiihedeeffggfffeeddiigcbcegffffgebaaecaacecbbcdhhhcabcfgcccdeccdcdefccgffdbbccccffedeffaaabbceffddccfddfghfecccdeeeedcbehifcbbcefefeffgcbaadaabefaabfbggecbceefccdcbbbbbcbdccfeecbceccbfedcefeeaaabceeebcdcdcbbbcfheccbbbceeddddefcbabaacccaacecefdcbccddccdbbabbaabcccddcc`cdfccedbdfgfdaaabdbbcbbbabdfdcecbaabbaaaaaabceddbbcccbccbbaaaaaabcbcccb`ddebbcbabdgfdaabbaabaaabedfaaaaaabaaaaccccbabbaabcba`````aabaabba`cccbcbaaacdbbabdbaaaaabddaaaadcabbbabbbaaaa```abaa``````acbaaa``bbbbabaacdbbbcddbbaaccdaccccdaabdcccccbbba``aabb``abcbcbaa``aaabcbbdddbddddebbaabbdccccdcaacefggffeedcbabeca``aceebcbbbbcbbecchifdbddeeddbbbbbdcdcccaabdiiihhfbcddbbeca`aa`adggdbccdbcgcehjjifbbceddddbb``eeeecaaabcgghihgbcdhhfedbccaabcadhgcddeiheegijjiebaafbddbcb```ffecaaaabfeeefffbcghhhgcdeab`aeecdhfbcghgeghiiiiecaabuxyyxu```ddbabfgedgcbegffgggffghecbbttvvttuxyyxussssssttvvttbbaaa`ssssssceecbabcbbcdcbabceecaaaaaaedadbb`aabbffdcbbdfhffcaabdeggfbaadcbaaaaabbdebbcbbbbddccbbbbbeb``bbbbbbeeeeedcbcfghjfcbccdddhgbbbbdbbdhidaacidccfdbedggfddfghb```bba`bbefedddccdghijiccddcccgiigdbaccfddcaacehccebedcbcdcfghh``aabba``befeddeccefccghhhecbabfhihfcaacedddccbegcbgedcbbabcfgggaaabaaab``eeeeefddedcbggghfcabbeghhgfaacebceffhggbhjhgbbabccdhhguwxxwtaa``bbeacdbbhjihgfhjhffeaccccchhg sstussuwxxwuc rrsrrrssuutt bbba`rrrrrraa`````aaaaaaaaaa```aaaaa ddebb`abbbbbaaaaacccecefebaaccddbbbb`````dbbbabbdeedbbbbbb defbdbbfebccccaaccccceggfcbbcebbcabccaabggfebdfedhiifdghhg fggbdbbeebcccdbdcccadfghhfccedc`abcdbbbbgecbdfedgiihdeffhh gggbdbbefabddeggfcabefghiiihdc`abcdcdbbbcbbdefdfhhheeedfhh ggfbdbbfgaadeggfeabdefhiigfea`abcdceaaba`bcefeeffeedbbehhh efebbedbbgcaabfgfebbceghijhedcbaaabbdcaa``bbcefeffecbaaaeggg effba```abeefcbgbaaacfedbccgijjihhhgggccbccc``bcccchhhhggeedcccegffgebb````bbbba``````bbfefda```adcadcccfeecccdefijjjiihhgdcdedeffdddddikkjjjiheeddffgifeda``addeca``a````dffda`````abdddbaaaabbcbaefccgfhiifffffiihgfeeecbceeeggbbbdhhhggfdcbbbcfghhdedaaabeecbbbcdbaaacfeebaaaadegghgedccddeaaafgefgjjjiedcbdgffeeeca`````abaaacfffeccbaaaaabcgddddcbcdffgcbghhhfddddcedcbabccccehgeddefcbaaagihhkjihggdbbcfeedcbaaab```bbcceggggfeccbbbaabcdbcdecddhfgebbfgijjhgcccccdabddccccffcbccbbaaaagheefjjjkkjheeeeihhgffedbbbbeeeghhhgdbbbbcdeffeKMbbceccdfggfccdefijifbaaaccdbbhiecbbeebccdccbaabffcccehhiiifbbbbfeeeeeedddddihijkkheddddhjhghgfbcefccccfedddddeghhgcaaacdecchgdcbbeeabccehebbaccaabcdeffdaaaabccccccccdcbdihghhhhcbbbbbdgfgfdceefccbaaedccddefffggfecdeeccceaaabccaabbhhfeccbaaabbbccaaaaaabbbbbbccaabfffeeddcc`````addcbbbcddbaaacccccccdeedcbbbdeffaacaaabdcba`aegfecb```aaaaaa```aaaaa``````aaddddaabaaabdbbaaaccdeddrrrrrrraaa``````aabbbbrrrrrrttrrrrrrrrrrrr rrrrrrrrrr FrrrtuuurrrrrrrrrrrrrrrrrttrrrrttrrrHrrrrtuutrrrrrrtruurrrrrrruurrtvvutrrrFFFFFGHIIrrrsturrrrrtuuutrrrrrtwvutrrrrruvvurrrJFJIIrrrsuvwuuurrrrrrrtuvvtrrrrvwwvtrtttuvttuttFFFFuuuvuuuuurrrruuuvuurrrtutrrrrrrrtrrrrrIJrsuuuutttuuurrrrrsrrrrrrrrrstutrrrrrrrrrrrruuutrrrrrrtrLIFFrrrrtttrrrruutsrrrrrrrrrrrrFFrrrsrttrrrttrrrrrrrrrrrJGFFrrrstrrrrrrrrrsrstusrrrrrrJFFFrssrsrsrrrrrrrstur rr JFFrrrsrsrsrrrrrrusrrJIKNrrrrsrrsrrrrurrrLrrrssrrrrsrrrrrLNrrsssrrrrrrrrrrLLIrssrtsrrrrrrrssrrrrrrsrrrrsrrrrrrrrsrstrrrrrrrsrrrtrrrrrrrrrsrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrtrrrrrrrrrrttrrrrrrrrrtrrtrrrrrrsrrrrrrrrrrrrtrrrrrrsrrrrrrrrrrsrrrtrrtrrrrsrrrsvsrrrturruurrrurrsvurrrrruvtsrruuutrrrtuusrvwurrrrrtvwwurruvvrrsuurrrrrrrtrrtrrrrrrrrrrrrrrrrruvvusrrrrrrururrrrrrrrrrrrssrrssssrrrrrrrrrrrrsrrssrrrrrrttrrrrsttrrrrrsrtsrrrrrttrrrrrutrrrrtttsrrrrrrtrrtttrsrrrrrsttsrrrrturrrsuutrrrturrrrrtsrrrsuuvurrrsvvusrrrrrurusrrrsrtsrrrrrrsssrrrrtssssrrrusrrrsrurrrrrrsrrrrrrrrrrrrrrrtsrrrtuurrruurrrrrrrrrrrrrrrrrrrrrrrrrrtrttrrrttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr o r nB/50 *$ [ _/2 ;9 >HIX`c^ Zh nJaUiD ;G]! b i mS K E !x0i. p7 /. @ ; > 8D/AWTKUDE \fe Zxwf S T@]] Vh p s PW/WHB B <@eww UxM M aan Z S-F*Y %X 8H ?T =u c]Ix $DGPQQ 1[Z qsQQ!]i_ a_ ~Z@?O K W}@D vG b wBDWX V &> >J K_ / oAB i j =B ] gJ] o 1d = #b )jc(c'j .j $i   !"#$%%$&'()*+,-./0123425 #67(8%+9:;<=27>=5?@A=<= B)0ACDEF('GHI;&JKLMM5NOLGP>QRSTQ*6IUVWHXYZ W[\B],^*Q[_`:aQTb\cbSc\d<e!76T)B103O^fg_9h !">7ZWV;IZijk+X@ lkmn%o30dpqrsturvwwxrCtsgf("!"7$#yCz{j{m-{zuIHU1Fewv]l|}~B E$yY}C{`V]vut|prDs}{jo _:9I6 W U W-@%oqvr_an%no  1e<k^4de/F13+3d4^ #FeLh4K>P_haF3`V:ha9;\TB*~4hU!6uzE.Vkjm;Zl}2=5:H;iki@/h9 #%6 @-/}jQS[4e)T*DCsXxw@? ZV_noy#$ED:VHu|mI Z%|tCxr_ofp lCEz/Flm|inMN+an%_`5.V - w],OLffYWUH'&KRbO^G'P'KPNyuEysuMLfY&8J]+X,.-/.[S\AxXkl  qpim{uqvRbc,XwRSR0Ad? c QbRSc~|C} 1<2"(Gg?02KJ>~[B~ (cD$D7"G>  ?J>gXYys`  ~*[) %+-T\bU !dA<g?; jiJ8 ) ;A= pf-M55N8&(@<axrun1*"O֜&)lF^?LNh+z'aL[Y{c?it5Cyw,Jr>|SuNԊ'bӊ,Ԝ, [G5P W LnUsoM~]h]Yg(rNC}ґ|ktI>Jc }f}Ex{pRy~s:z}yor߈ 49}h|䃚gs}9$8l]sts.|}k{wFs\[g~'sKn{9 J|c 6mwЖg |kt>3yJb weuEy~}AM|r݌nj nu䃐rÖMl-5k]sns/|ho~\Zs23n~<ʅ;x[ '~k-r].y15.wD5rO(wa?-ضaxrun4P;!E2UGZEGeApBhQ<9<1hM$rS^z^eg Lnx 3zDt̗?Ak{B';pS~a reqd|~ІD˓JˆËn׌ijz r߀OĜHƜ26z]sis.}h˂g]s̖2Ј9n ŅBx'XŅ-{h5pY8v6~53vet`?wQ<<<}EFxL8yc\6axrun6m@!c8pGf7SFFlj?hm?mhLd|PZTaGkoB4q:F{C~5q]*L^)xqGgrR}}hdta]sfzPG<ԍ4oodeEm=40@^g\t7BG!= hy~yh~qMF%@ s!4CQ Fʞ!Ƨ!{c4eqyn]^ z0zIp[uDu=c7utMG1G1>mR }qK^h]`h"(o]46kB|ӑ\F|itOBNc }f|7x|mQ}xyg|9h{yیrj 44gz惐gy}4ʆ$8k]srs.|iqCn\[g|'pGn~9 P` ;mD{`B~PG0GFM}&?e5<&rockrun16"'OӖ++n4`=O׆[h7k6]{IrX`maXhsoLBorE@A={]L(d`ShIw?@)"|}tmk {.*aqhKtV@{w5r(X9hJ{GkHhOR-ڍ?rEhEbzl;eOag{y茗t툗 i|pRQÞ?]grh/ft;dZgĞ#*lF dd`4iH^Rf o%lk=Q6rockrun2 !N+dFU?FLJEh z"`|ItUYaFbq;Ft2T~C5v[*(}`ChdrNT3$ !z{nmf̅4)oX;erf UQi8Td[{afYmJI/ӕ4q6feMzQ9J9ch^"<J(F Wi7cywhvMN!F dX$4CF8# l9Xtkwobc Xz7JS|7c:2XYM R J6LqU]k]egIlbF8n8XwԖi{SJXMh wew7x>Ì]yX}t⌜o戜:qw怐il 6n]sns/heZg 0l7 ^] WFcIXP[d*fa=d0 ̽rockrun3s "pN L[6LFAljBht!kh%yc}LRTZklhn l`4|B~?s[++X^hiA43# w|kka̅85if~iHU`'eZ3^BkGB2ԍFoeceJkEF=Fah|b|"4yl#|a `-yuitsGG$? uC!z9}FwJ62$^4k:n`R|s$q-.r'G c:/qzq}6D DY|Ne rfr6{̗FƤ(X}Wnijz r耈qM&y0l]sis/ |iċkƎ\[qž ȓ;l7RXF6SKJSLS/X"P3;0&ضrockrun4MU AW;6W6IEDωmRhOUmQbwlÎuSUT^fknm;qh 5nIo^]y[qg }Li 0j8uڏEglD8Yoa~}n lcnpy֔FС(ȓXĐ}œWi銔h킘yjXt|qǧ&—yƟ3k]rhs0'|kΈkЋc`r˛Ґ;l;چLZՆ;dIABSBI5O DFU3rockrun5d^!X[_:M`7PFDLJBhe\mck cLSY]LhkN9nH9|B}3r[+L[@hr!<3$ "z{nlfʅ93nBrUida]fkGF2ҍFqddeCb6C/T^s{biST|M!C ix~ui|rOB(A "9CU16- \4qnY}a |0|I_7d8fd;LYXwMII AoInJ^z[bhIkh935XyҖUii{LAXRc weu6{ʧ?°I[X}to创 y倎gNGj 3l]sns. hěƛc[s Ǥ1l7 W[ JEXHOSRZ.]U?U8 rockrun6=!0!Lh4X?Iȇ[h9r]((yZ?hmq$43# |{qmhʅ3)llLYn'U}h ec^Xec$kJJ-ғ4rEieclh;Y4mh]R;7zH${}A hx~xirOc#Y d|$!5?a8ħ#äUlsnb|]z.z G!]&6'0/aOSL8MslN^k[chLiYF;8[zҖ6}h{UJXaSm yez7wt>G[[|}uߌq䈛[_io%lMi.W5 Ƕstand2ddN +]7S?F0gekYoixLUTSMz]Q;]H9nDr5e[y)=OBzX :4$ ~!Ònˆf2e7f@^TF bJXOzIIȍ}y4nyoad8h54*CQgwRmFoK$q@'GurskkfO<#5 h$y8|Fw?~6 /S4] kMwY'X0X K c2e [k ML]W:LfF}^}zX[sIci;99]tȖW xxl}]Sc|AY yeqourǂEĐL|xyt׌lڈ}ytڃIL 5n}]rlh/y'tlzy|[w`r lw:f]^;f?[_io%lMi0X5 Ǹstand3edM +]7S?F0ggk[~oixLUTSMy^Q;]H9nCq5e]y)=OBzX :7' ~!nlf2e7f@^TF bIXOyIIȍ}y4nyoad7h54*CPgxQo ?oK$q@'GurskieO;#5 h$z8|Fy?6 /S4]kLPwY'X0X K c:2e [k ML]W:LfF}^|zX[sIci;99]tǖXxxl|]S\}@X yerotqǂEđK|xytՌlو}x}tڃIL 5n}]rlh/y'tl|y|Zw`r Ālw:f]^;f>[_io%lMi5X5 Ƕstand4edN +]7S?F0ggk[~oixLUTSMy^Q;]H9nCr5f]y)=OBzX :4$ ~!}Ònˆf2e7f@^TF bIXOyIGȍ}y9nyoad8h54*CQgxRo ?qK$q@'GurskkfO<#5 h$y8|Fx@6 /S4] kMwY'X0X K c:2e [k ML]U:LfF}^}zX[sIci;99]tȖXxxl}]S\|AY weqotrǀDĐLW|xyrՌlڈ}xtڃIL 5n}]rls/y'tlzy|[w`r‹ lw:f]^;f?[_in%lMh0W5 ǵstand5e!dN +]7R?F1gehYmkwLUTSLz^P;]H9pCr5f]{)=OBzX :7' !}Ēnjf†2e7f@^TG bJXOzIG ɓ|{9l{ab:h64+CQgwSo FqK$q@'GussklfO=#6 h$y8zFw@~6 /S4] kMw['X0X K c82e [k ML]U:LfF}^~zX\sIci<99]tɖWxxl}]R\|B[ ueqpuseĎK|Pxyr،lj|xtۃII 5n|^rls/y'slyyyqw`rŠ |lx: f[];d>Zfin%kMh.W% axstnd1! O+adRDGqÚqqug:W`xiWwP]0] Kc:2[goMI*9*0IycE`zW[z(cQF88uyʖ |kt9N.uFa yez7xn{iRtswp{0~p{w،q݈//ez݀fot}Ƀ.x̂;l]soh/|{itn>kf]syxlMls75wNZ'%xa%}6+.{F.tV'}dW% axstnd2" O+adRDGsÚssug:W^ xiVwP]0] Kc:2[gn MI*9*0IycE`zW[z(dQF88uyʖ }kt9N.uFa yez7wn{hRusvpy.}p|w׌q݈ /.ey݀fpu}ɂ.x̂;l]soh/{{im>kf]s{wlMns95wNZ'%wa%}5*.yF.sV'|oW$ axstnd3" O+adRDGtÚttug:W^ xiVwP]0] Kc:2[gn MI*9*0JycE`zW[z(dRF89uyʖ }kt9N.uFa yez7wnygRurtpx.}p|uՌqۈ /.dy݀equ}ǁ.x́";l]soh.||il>if^s{vkMns95wZ'$wa%|5+.yF.sV'|6X$ axstnd4" O+adRDGic^s{v}iMns95wNZ'$wa%|5+.yF-sV'|oW% axstnd5" O+adRBGsÚstwg:W^ xhVwP]0] Kc:2[gn MI*9*0JycE`zW[zIdRF88uyʖ }kt9N.uFa yez7wnyhWtsvpx.}p|uՌqۈ /.dyހequ}ǁ.x́;l]sos.||ilLif^syw}kMns95wNZ'%wa%}5*.yF.sV'|dW% axstnd6" O+adRDGtqqqug:W^ xiWwP]0] Kc:2[gn MI*9*1IycE`zW[zIdQF88uyʖ }kt9N.uFa yez7wnyhRtsvpy.}p{w،q݈//dz݀fot}ǂ.ŵ;l]soh/{{imLkf]syx}lMns75wN['%xa'}6*.{F.tV'}oW% axstnd7" O+adRDGppqug:W^xiWwP]0] Kc:2[gnMJ*9*1IycE`zW[z(dQF88uyʖ |kt;N.uFa yez7wnyiRtswp{0}~p{w،r݈//dz݀}eot}ǃ.ŵ;l]soh/{{inLkf]syx}lMns76wN[(%xa'}6*0{F.tV(}oW% axstnd8" O+adRBGsÚssug:W^ xhVwP]0] Kc:2[gn MI*9*0JycE`zW[z(dQF88uyɖ }it9N.uFa yez7wn{hRusvpy.}p{wٌq݈/.ey}fpu}ǂ.x̂;l]soh/|im>kc^s{wlMns95w['%wa%}6+.yF.sV'|dX$ axstnd9" O+adRDGif^s}wkMns95wZ'$wa%|5).yF.sV'|oX$ axstnd10" O+adRDGif^s|wkMns95wZ'$wa%|5*.yF.sV'|oW% axstnd11" O+adRDGsÚssug:W^ xiVwP]0] Kc:2[gn MI*9*0JycE`zW[z(dQF88uyɖ }kt9N.uFa yez7wn{hRusvpy0}p|w،q݈/.ey݀fpu}ɂ.ŷ;l]soh/{{imLkf]s{wlMns95wNZ'%wa%}5*.yF.sV'|dW% axstnd12! O+adRDGqÚqqug:W`xiWwP]0] Kc:2[goMI*9*0IycE`zW[z(cQF88uyʖ |kt9N.uFa yez7xn{iRtswp{0~p{w،q݈//ez݀fot}Ƀ.x̂;l]soh/|{itn>kf]syxlMls75wNZ'%xa%}6+.{F.tV'}ds3 axpain1" N+a6OFB0*1"DIcG^zXahxHkge(Fa!uw̌uyywxG|}\шɁ\tucwՂXuvX͐}\SU\yaqƈԂ̌:Ս_?}]qgrgeitiڂ4yBw[q݋%n{7os|Ke^g}k{g|Ps:smq{BlzU axpain4p"pN +[yGdeJ6gqhedlc^tX_UKjcHi(Ga!ww͌xy{wvO{{c҆:\uwduׂ[tvYΐ:|aUW_{aqÈҁ̋:Ռc>}]qirgglwi3wBy[q߈~$n{7pw |Kh^l}pyk{Px<0<*yJ'dG^zXbh|*if9x3yqAp|Wci8(1Kf!yoy:y|sN{y\ɂ:Zwy}upq߃p::Zg|thqaxʂĉ:΋w8y]s{qg swix?r_]qՆy'n~7}3}&{ZȄ y$x[*|(<$d+xK~ic9 pain1q""pN(d7[?Gʋ}Bgs kg%{`{FuURXPkhM5iH5C3v])LSEha!<3$ !|{olfЅ-D3fE`!SyW dO[U kISד4oodeKhJ?C4agwg{$9uL!wB WxxitMN!|G n"9?mK|9i2^?^i^zai0i I ^8/q[qMXihLWhL^kZgh(kg4M?6yזc|ktdT`6sQi"yew7yǥ>&XyWy}u茒ojxxWy}&&yF]sos/}yiĖpě^Zg ǟ&XyWy}u茒ojxxWy}&&yF]sos/}yiĖpě^Zg ǟ0*1"DIcG^zXahxHkgc; OIckY|`|zXskT'a)oU1Y3WG {|}k}}}kCaWFb"]uo[wyn}I|Q΁cэɂakNlRMuAu}Csuub;=Hqbl{NN̍ՋT9|{]ZMrsQ\uliYڌ<؂Fm[a݌#o:Wo>O`` |gsc Xk1loEgy= axdeth4!Mܻ)k]hIQI|6ZsThnUUpPgRvBWexhphqg4k0U^wmt//RbzZY] T!U|f"LPowQf~Tl0p aMPUJWi|KXvQUsRY8FGcLRzh>m>g;{1LHwcSY{`azX[hT'c=nn[0{~\3gWE} wayibybmqCdn:R!`te[uyNw#q|ڝ?wѦlx՗CghQhlPTrGqHmnomsC=}@Lo|Be~pݗs̝lkԞY6{}x]mgOosX YsqvhhhY{خ}.l[mamاuom:T~qp>P]e y|krsg nXp~1q|srDky/Ԗaxdeth5I".\]bYJ\DIU{'aΪsĸLh8PMRaAUw`5sX=zGc'Ug)lQO0MT.;X8}Vʽs6Psi6Wt8cLC[HW%Q7!QredMu`|&Qcғ`ԇiLJ4cmh~?a:Saa Us^sXhDG'SJ=l2K08P+&X5}<NmPoiWp_:CW7 SPqGeKuCxQ] \w ev4_vidl?\N\RCoY4qSx5X]Si]VaeR?,}L/N;WcL?YS"[m"]lhUmI66|k[!g=oBrG] M%Qe-']iY_d<`[!aTwY~l+CF{c =C?];U F[BzX;[_J2`LcBE[J'kaxdeth7ξ(1 U]P=muX(??% !)} ij4}dHaU/_OLeiDmJ+kX[+y4ipddCk?43DYg|Yw&Ft@ t7M:x{xh{mMB$:'kc("9|FGJv,K]4\R |hXzW`)^O^8/l[gfZ+D*?;S66U0˾deatha4d*"aN(nFf>X;~A;|Q5eL5deatha5]*!Xq Iq9i=XÆ1h_(kT1yl{Rua`X8nh-3f!AgAi?aXt=LR1muS%C3% {!2y î5d@dO1_O}I ei<pF*lX[*|wFlydfd6h,F!_MgxPg'Du3 t+J9yqxhn`M3,,k]'"<F{@It$>M4\I%|}fKzK[ +|ZOq \t6t.Xc^Z+G,>Wf=^yhXSh'=nQ4IDuL%~k{yF9w}?U e8ypɊ9\]}j}O^͒^99L^sx1}|o{haholED~o988{^5rI,F}>AyQ<~EC1deatha6U+!K!]GnMlc=v)RphP@0#f!u}| }r<|c0\L3CIthDc[8rdB'nUOU*u|I}e4nfdd{o}$hC} _;st@\$_t yrlGF|cyhaM ,x_Z&";x9u1D#=7FPD,~wd;z8hXLcU\Xa Ea )K uSZS*B%9RMd,^fhX@i,.o8?AArwC-~gkh{eByN5}ww0B yo{b<\^|x|y{yypvs~GN_lpyf<;F]ss|}u tv{l{}g^~g~oRDApi8w88k^1rqGv$Fm>?iQoADc>\w;HPiQL8A86Q5;D50 sdeatha8LG$@L7+n=Cc?KPR:X!hKGmPSY,X01$c y]3o]5!zc(u* wQcQDB Hֹ޸nйJKuil|qʊr ʵ;γ7nµ+rs~™qϗm/¶0,׹"n$-J;6]:zz^x׈f4Y<kK|E޽ ]]Bs/=q`V1>f]19<5 f0sGD K< P<F'.[deatha980#-*9 Gl2Da_a'1@F75S@S5OY5;$uAA&bO;U:&[ ̗R}Un\d$c]h_ UWYp!hl2=&`\u!St;PB<f='_'W ?X//C @[, ?Cx:/@3xU3A7kd/mz""8a I3` 8X= D? =,%u0Z/U3&D%'>*9J5`d"^-huZ gʗA…6wq VG=<;?z΋Y'68i75<$3(k_(u& w?uFE? Oиڸn̹FG~u=bzLo߈EF˵=γ8n-rދV;ܗN%ۖ?L3X/Ը!n$/GBd]6zzQֈ3UU7kG߹Eػ ]]?h/=q`êL<;fR0891c.sFAK9P9C'5Adeatha107-$+0' n BcUO(8T%h7+i9: c6L-x]`[bYkVSk SS$v%"ONYSb?L!VːJ̗*,Ȣ,.$$Dž7y-ho,9ʽ, ̥Eę @[a1 =F8 N!51B]35'v?<(pJUǐ7 ϗ2}Tn[d[[$m\`U`o$zo58"UXu !Or"7DB3f6%] 'U! ;S-! @ TY6 A! qT0?:md2mz$"4U I-S ' , _, K),v-U-S GIMJ-A]d+^"hsZ gח$ԆOqq SR> ˊ7,?0i-, <[<_1u& y[!^7 KN Z q33t(py85<϶Ҹ!εZڈAܖ<-)ʸX N OPp]'zy/y!C7k5: e]h#*qY˪(<9 d+0F-;78lJ MFL;^D 356deatha115!$,*n _cUO&6T"h4i=(c3L+x]`[bYl VSk S S"v""O NYSb5MOʐH˗(,Ȣ*5!$ȅ6y+o+9ʽ* ̥Fę @Y`/CD%N 2G 15 x;>cJUǐ6 Ԗ-} Tn[d [[!h]TW`o!ho21UXu!Or  J T1f3"]'W ;S"# @ TW3 Ay q T;<1md0mz"" ZMX t Y G+&y1S/S GI MJ-A ]d*^!hsZgӗʈqq SR->Ԉ3 45 -i,* < [<]0u$ yu^5 KN Z q21uby&o F϶Ҹ ε Z0+/LʸX N OPd]%zy(jފ U5k3: e]h/q Y˪'<9d*0F-; 78lJMFL;^D 3q0 deathb1! N LfFZ>M…:hkt[DwOX]NkkQP Mi'h |[DwPXWgzcr dq y41k^t%(R`h^P =# s"wtnpf; F=fQ`?S{tPRoM;^RGzDPO'̕5t~phfUh`1XG6zʵ Ƹ ̨s1^1PiXRzk'cW aR=Ğ2dž77 coiMc|DyFkkƘ>ʗM[lu}rڌijy㆚nlXox}YΣʜMɧD;{]glg/{||ypf{cXgɧ Ģ0l PS` IL4BcW"X%SHP1_61deathb3E@L`#k?^>S emFh8Wo[FwPXRww``x4|whfgw}-{(MwhU{=! ey{y}oph; 7?`cQWcT|SqgFBleJpwFRRxx̍y|5yt{cifhmwv iiXTP ox ow$GckPek]xhIhc"aq 4>V8zǵ ø̨~ S]Tf`Uwr$XW.ʯa8Ĭb¾bŸAedmLU"R"L FPchVe^wxWms"&hG 6i{rȖ1R`di`LRBi[Y}gBzFd`>ĚG[X_h}u8klz lkXoڃ|} R̤ĝéG;m]gng/l||lcf{nctZg F9zħ ̗kWMTfMUy^$[Z~.˭]8Ƭ`þ^Ɵ'W<{y|G]$Rh+@y;$^U^Q.ϨGʧHǹGț&el3LWpXsU| Dk]d8Ud^:vX5h"(yiKR<|l{rìT`MdiK`MOn`Ixn,`}0~DzyFe 5'~^w|`]ch}fw8ll| |hhsU}q{sV|Â'zPl]Pgog/l|x|kaaf^{letZ[g wlEXm`a Z[y0Pyoctfv$^qAa|_>ʌdeathb6ǻLι7kN?^S=Zm &mh Yq[cFaxMN]U2waAaC(5y0wfgAu,${@(P0h]+f=q!q e'}ws}omphl;t YFS?d^R}ROschiM7LcR sFW]U\{v{xy*5yt*^i;f'h68!mU%r3"t2$O:cPgi xI&%k""M45>W>fywsg3^ Rh_y'$`;`7*Ч8˥:ȸ8˙enLX[Z^Xg FV]f$Ve^&vX!hx"k&{i7Sl>gl}rwtĪT`:di7`:PY`LenThBzeFe x5s'l^vwi`_Pi}R|w8ll| ghlh^Uo}`Vh p'szyRlm];gnrg/o|e|lMddK{{lteuZFg~~ xl1sZX`an [k^e0Seod`ia!a\Adg`AÁdeathb7+6lJCaLISc;mh Tu[bDYzSHXSwa,a0(5{/wfgBt+#{?(MzW&b*nn1e(wroh1hg`'^n5t1%q'Mn05`>ndeathb8+6l;Aa` RW TNawiG;BeJwL-Z1lynt&.tw%\k1_h+/p T o q$I1mlfyȳTa}=di7{`@LDi T}LzR3d U"r+'reUpzQL@oVe|^4CpCn:kfpung/?8%/,%P:5o]7gqUqX(|y`qP"icK}"6\yZ?q'*={l0h;SP`[2R1SCJc^`,XVZ.a;edeathb9+6q(Jc(OU84mh TZPF@kS1Swa,a0(5{/wfiH"l,#y;MzW&H(UW5e(tVrF>iC4U5?_w*H YD(:%@*?0S Th Tw$[<Z;/ί78Ȭ8ƾ7̢dfLSOGJ%BcTe^'xWhUGh1W"%B(oQkȲTc|Aeh7{aE;q< T}=AAd VswkW~wyM5Uu;^C?:d7o3uoJpzS;M.:6"8!%W%3o]3gtAA(wWtPmaHE \{[6q,L{l0Y9< cC0J-B?<nL L I? ^J+Gdeathc1WK#KJP'c7OFP̆sCqSGhTWc|OMXRRl]J4[tXLLMJk{X0D3$ !|{omf̅ ?3dVq`ENtGZhL5tuP:j5Y9?ՍCoedeyHgCC};JaqskY@@oL$oCyGd|wktN|S-uR!wh5'9?p[9ÎЇ͆ď]Cd`@f^wb{ZAuXNL$Q%fU(>GEvkl-3?? -YdU^kWkh (hm59 3ĒyՑGWk|XΎsY|n!yeyE{ԒNFStߌnj ľFFѹSw胖ɹSȎЎ?Շ? ]sos.i*[sڅ l}D X[ ՃӒFҌq؇?<deathc2Se,HcGAO[DGDIЅk`sLehPr^~J|ItMkm{W[DtXR_TKILiJfzPcW_?% !r|fm]Ӌ >?iawMdnAZ=[?Wa{LXbk-1B}}Bqcccqeg|[BuS@yysqQY_uie,ona'GZ?e}lxk%qi$Poa,w7}Ciw6ΐlۇڒqB@hppi}tvIk=ADl?e{Dy^*DD2'àm`s`k|Wk }I`sD5/1nDtkԟmt~$n^nECMdo`loCCҞiy-NߐCl;1]wdsz3|͐h.!ZrlfڅڠRӅ2艦搳 fos;( \deathc3L|,A}8]NWfBfD͋cyzEkL[~G~F`Pk`W^YZ`SJ"IITPz=r`yC},Ĉ<$lۀ^hW:ʗ;ǡAčC]h1Cu(o~-n;kz*ġ+fwu@q\a\i|ssn_khUuwqHt^ck(\q&-l}anq},k}'C+rF|@e5̤mʤ؊ސB7}onqt3|yU-{4b8a\=\@8|8"%ff )$ɖad`kwXj}!uIy]^5*3h|Alu"i$f]hf߻ָ B}[dWlf;ϰ@ӲCaou2ƹ³Ӷ޵Cڬh80]u]wq3y h|4%Xu߬mk_Ɛ׋ uL;.c o y<' vdeathc4E&<ģ(W_B^F8YzDlM1[ÄGDaRmXWXP[QSt"GHYSjEuWy@}+Ј9$k^hU8Ԕ9˟JNjAhi5Uy<+rtCqKnk*v+]uuUq\a]ahdw`YvRqwp@Y_lGYr-o[og(`'MIrB|Ue;9؛s֞mϭ|UP1tqmt0R,'}++Ty h~F.Xwhnk`Ӑ: ԃL:0L+21 a 7"؉*39*rdeathc5US9Ww`A}]G7Yh[pc3[IDtlSi]ZX`{{Q{!xMvOlUlmuݑyU}+ӈF$k^hWEד4ǡtV‹sUwkAuCơcr}lxkm-x-[w u wRq{[axX\zWRLoxtPdndu`quq}`&[ urr_|tTi9> ږwיpרs|T|?t or]`?̂?r9™\̋y$*c8aAH-si*ak]|$uxMoX>OAhd. l 9Fh{'fyh]*T,}[~cWmd7ڨ}Vߤ|Uఌ,`n2u)ڲ ۤ쓖U苌u?=]v]xo|Ay hf4Xvrhi{X֐7;L7GHI%J8b[I Bw}{Uhl[toc~qp}v!h`NWmt~y^T}e(̈cF}'ks^hhWkeБ`FSSSTk`rUhơw Ð r퇦k9ih.y-l[ws2ur hPqmaf_xTOqx{hootwo}r;}a_ rV`|aPo?A| ГatЗah֤nm{Py@u2tr#dۊaw[ُ|8,-lcAncIkS0}k*a~m]n}b$uSsW?hND{htL l BxMvl |'fWh`X tch\=ST]+ }[S\Wcpd`FҥUS֡RTܬa+`qon0u^=֯a ؟n g VTޅ^tAiK]~x]hyoPJy s huU^y[FX~x|]vr\siqАbEIyLlERkNWs,WvDlbLmCMw;SlI_+2deathc7"/WJWAQGQDlhZA[p;Il;BfUh}[{d|m}lg!`RWmuwCR}GIÆFBq'kV^MhUPfđBC=N@RiYqTR\2f2tҋiEih.a-SquU0uU aqfaYiy__wy |owrӁr:lo rBY|UyBAbđC{ĖCgΤNmuTu/}r%nx6(+Q\ALcIJQ0ai*asm^o|E't8{Wu?NDahXKw1lyr2BWOVw 'c0i-HMKC%꾜deathc11d|"o0a[TLTI"7OXger[ilAX@A3F!cUihT[ptXf}~m!m Qk6{,!}MMhWrmu~yU}"("F0$l1^&iW'E7 T Tih]`og`, ; ufvEhwh*w5Pw1 y3{RxqaMQvGPC^[EviQ _}Xne_wmt}ErBy; * h? f ?X2xۍynmi"7*yL&7>&559 0 ]. B*n6>3* 羌deathc12Ib"Qn2?]UPUI&8?8gMY\SU?W=?-GMUQh?[P?f`kk Sc"t%"{MOPW[mdupy!@,++4{$$l8`-iW-7%9 `_XhG`knX_-= puwfm8ihhh-r;Qy8 z;y Twq[aX@1w9-Q3:P+w[;DaEnHIwRktp7ur6 c}$G6'E@!gcr_| TQ8F1& j!& QQxqY_auE Sr5io%Cxl?tu<|Xa6se(9 R? TI *gUhJ {a(md]@0 rHSW0F!3' l<]`L{/xl-}+ 6i?O7`-$c \h!^q5<ޢ ܥIڗ XԨ7}5]3p[AlkC;X XiJwJ |@/ª' Ԥ қ]ҖyD 5}](v^2wr2?y;& h8 c>X*wؑknkiX(91hM+9G'<5> > `< A5pA)* wdeathc13+K)Y X]UPUI&8;+h0Mp8Ky;& h7 f>X(wؑknmh]'91sM+9G'<5>> T< A5pB+*=deathc14&  ]UPUI&8<z$l'(W=?-GDUkE[ ^=cYkmSd"{%"{MO9UzwTy!U+(+4{&$l8`-mW-7%9 `_Ci, )r0 -= yk-| k%h-r;Qy: z: y Twq[aXAzE `? `P!wT0^Io(Aw' w ]p7oq<d"H,A'%%,r_| TA/ 1& j!& X Tw;Su-[rM O }ZU/-9 R? TI *gGi& y^-nX]/( t_W^F!3' k<12{/xl- }+ 6i?G*`!,dh"^o7<ޢ ܥIڗ XԨ7}5^c]/nl,4X XhX*wؑknqf](91hM+9G'<5> > `< A5pA)*=deathc15G]UPUI&8<z' W=?,GDUkG[ ^?aYkmSd"{%"{MO9Uzw`y!J*,*4{%$l8`,mW,7$9 `_Ci, (t, ,< w l(|k!h-;Qy8 y6 y Twq[aXAzG `A `P wT0^Io&Cu' u]p6oq;d!H,A'%!,rB| T@-1& j!& X Ty7 Su,[rMV } qT*(9 R? TI *gGk%y^,nX]/& u_W^F!3& k:(-{/xl-}+ 6i?E*` ,dh"^o7<ޢ ܥIڗ XԨ6}3^\['pk"FY Yf3u1/|!Lª& Ԥ қXҖyD.}]'x^,ktVy;& h7 f>X(wؑknqf]'91hM*9G'<5>> T< A5pA)\3 deathd1q-i%'c<[0wG/Zt$ik0a]qIZJMMyXN;WC7iCp3`]y}+*IBzS 9s0i!iyx"`uiizk`q8<`BZ|Jl_?pBXJyJHM_]}4o{dco8i;9,>Ma|H{&>kH$k='Amllkc^GB=a z;5B9[ĩ\1yvu}kna:2JL[C|U!<p?G!y;WG}i5qipdyc0b/4!KFatGh&>dE$d:'>mhll`\O8#3!^ FrA{=0y 2ΚP5yRcEPrP(O5M Kp `t Fp/\` MJJG 8W[Eu`sxSWzac;B-louO%|qsk}{s?|Y;l};}U"}BuDmf~>'|RwPu||9oŠ u}Éqǂі$'s A;{]sni*}~uh{iy`[s8ln 1BxYSID9!<{iukpa:1D>ZBP$N9p9A$y9vWG|}]5q]pdmc!b?H8Zq=`'HfB$d7;m\llQPO,#{(!Z |FfAx30y ɈA3{J`pVy6Zk?S+Vd+,f"A:p^klVKOt'%m&!m^! kC\@m31yjrwƵP,JNwQ~wDld}5ksgwco%hl$W,Vw\D|9]pslh(}yh|žEZ¨AS[wwƤUȢHdlY1 |56׋:2З0,LÜA|Ù;I(9]&zq-iǖ!M@+"i7x ],wĎ;€ni`¡69D\W58SM5IR NU &JfW%T8 deathe1`3X(lt4`?UDžFbh/p]:}^}MwXYaKntF.u<=wK+v]''[@p]!3,yxwόn w,,cG~|S {Ssy{] EJ]MmDYRҒ|Ԙ=|FtFMbN)C=casgl-=zG"z=]:}uavt{VuPd .LpU8zsíqwXk)ySd\}\n/o&q`u?o%a!qkUZXDWfKt`p^cpzb)L8prqT/}w{fxRYO6uWtyr?3t{&Vڳ9ۺϯ6|yt{zP>߷;רC|t}ҋ4y8ƃ <:AqlzȀTէԳ;Ҳ~IlBwd/h:sR mS=&F(=hNkhb{0{ {J+/xow&ws2@*;l6wf"h/sE lE< :'2hAk߃ eW/]-]==-xmyws*?*8<5A6'?F A'W0!З֯ۯ ֔Pczt`y `ԃRЛP }'ޑ Cwl+wis(~q6i3<" 0'+h2y|@*H%G2)+zl|ws%</7=QC'w Zw†1 p GuX `Woc tzHuivtd`v*w>`YdpGkhRXs ww`}SrGf%l]uhwM\]SZZc|dkuo}w冪uous|2zMiNah3hIzsiut̖r:w,oLLvmn[4Mda{pZVinSOoLgc$]0WBUUG ªnailatt2$GŠ ?w[mlUdYZ?rw_UoghTucFxc@dd7eqxf|}6nX,|44qc`[dcGk\RWmypwu]qOrGf%n]yuhxL\ZSXXc}udksn}y冣uoup~x2zNhSaf3\Izmipttt8p,hJJvhnZ7Lda|pSVdn|OGn{Gq],U0OBO\G ªlight1% H† ?}[mtW6`X?rve\lmhTucFxc@dc7eqxf|}7nX(|44qcw Zw†1 p GuX `Woc tzHuivtd`v*w>`YdpGkhRXs ww`}SrGf%l]uhwM\]SZZc|dkuo}w冪uous|2zMiNah3hIzsiut̖r:w,oLLvmn[4Mda{pZVinSOoLgc$]0WBUUG ªlight2$GŠ ?w[mlUdYZ?rw_UoghTucFxc@dd7eqxf|}6nX,|44qc`[dcGk\RWmypwu]qOrGf%n]yuhxL\ZSXXc}udksn}y冣uoup~x2zNhSaf3\Izmipttt8p,hJJvhnZ7Lda|pSVdn|OGn{Gq],U0OBOQ0 άrockatt1$O=PpJdwD|1sxpukX{ZVwD8A-oA!cuaDh7WX|'}k?~CoD/vdfcndy5q#zh}awhshpt`8 Uz}T(!kGhS`Wf}xJ}L!okdfkiZ~g|;s=:-DKsAQ EX/)[%LkIwepyb}VH=%5$dw,ankxe=p18' rockatt2!O=WPpQJp=I|=sz=z8`I[VqA@yD<:F-D{ueE}m:o[Xo,u}t9y4m?3w`^!FdkpduAi|os#QyOh}Hc|qscqpcmhX@LdyyU+h!sMbUR XUUzELxMKLX_ pqrogfnmaXi|FsPE8}Qs{FQ 9|Z<*y^2,sM\hTwbl}[HL#C$Yn !k`mmidA;B|Zai.fKfadCtlJLu`0w`L c2 \tMO ]D,Y>IFvVlW?[fswcUSwiuKi^@yX[:EAA8}sUz[xQwse{\^fn.e:Ql lkNnLI{Z<{Z > a0dtGdM uD'q>aDVq]Bpf}tqW\x|w+aCWX8]>Y5seyogw}ytxcfgft}d:e*_y+r-^\i9+dr:}}5UYXy6+x+sA+950f5 T- rockatt4! O=xPpsId`D|:sz\uXZiXVxFCF;oF/eumDt8cX,}|94qB8wg^!dlow)}†|#pypf}iauÆfrhmp^AUl|U+!uFiYSX[ZxgIVlIwxqyofwm}Xi}BzE:7EUsL!7];+^2(uFuqoyn}bHE#<$dn$ankdB]<`hq)c:Tk pkNlLI|U<|S>a2gq GoM"F'}?lDSu]Buf|wuW\xy+cCUW6h>d3spyumu}ykfqftd:o+gw-w.\di;.dr}6`dW8.n-sB(;53f6 S. èrockatt5$O=Pp}JdkD|5sxeuaXqZVwD=D36B(cugDn9]X,}s4FpD3vea enoy. v#}y|fvuawfrhmq`< Tr}T+!oFgUZX^}pINuJqr6fqmXg|?zA:2EPsF 7Z5)],(pFukoyh}\HA%8$dr,anke@go3s{z{|quy|?U6zAV$Zgci{c36B3?Typd|ff:y+lw.w1\li>0dlo9`pX<10hF(?.6f; Q0 άrockatt6$O=PpJdwD|1sxpukX{ZVwD8A-oA!cuaDh7WX|'}k?~CoD/vdfcndy5q#zh}awhshpt`8 Uz}T(!kGhS`Wf}xJ}L!okdfkiZ~g|;s=:-DKsAQ EX/)[%LkIwepyb}VH=%5$dw,ankxe=p1\G ªshotatt1% H† ?}[mtW6`X?rve\lmhTucFxc@dc7eqxf|}7nX(|44qcw Zw†1 p GuX `Woc"tzHuivtd`v*w>`YdpGkhRXs ww`SqGf%l]uhwL\ZSXXc|dkuo}w冪uous|2zNhSaf4hIzsiut̖r:w,oJJvmnZ4Lda{pZVinSOoLgc$]0WCU;YI shotatt2% O ?|`mqZd]]?rxcYrikTyfEzk?6l6Etwf}7mX(44ud:wmw68/%tt}ʑowȄ2l}o}C]M {^ i`q WatvgdIkZy Zy1o Go[ |^#yUhd t|Gqlvsh]w*zCf\6gJk`UXq |s|y]GwPrGf*q]zmvLqZT[[dxikur|冧zu|s|2NhScd4`Mzolty͖u8t,kMMvkrX7Lpf|pSUhqRJnIg^,X0PBPHJ óshotatt3% HÆ ?hil]coHk|w ZwlÆ< o G_a p`!lW\hwzFmlusf[rt*xAf\oXOyUWX] ulyp]HlRqEc%m|[hk|sJZW`[[dulmwkaـl݆}w|_ht2VdUcc9PSxhk`ty8d,aQOMt_uX:Lnfyp {S@QqUyJsJsy`,}X1PEyS OJ òshotatt5% HÊ ?mdld^oOd=rxXPuan_{dBzh=6i3Ervf|7lX,49wc8woz 6xu%|%dd{_ jp}C]XO} |a i`q Xcuxad(c]1i"k"qohh|amEwMFoYrV}B%8,|cwyk}xlHK%C%l%yt@W[55Mf[ pWY,qy ZynÈ1 o Gg^ w`!tWcf uzFpkusf\uy,}Ad\6`Lj\UXc ypyw]GtPqFe%ty]oktJZW`[[dyqqtkgڀp߆}w|cݐlx2OdVcd9XOzlket:i+gMMtdrX9Lnd{pU@XzySL{Jg`,Z1RDSUI įshotatt6$ Oċ ?uall[6W^=rx_Uqhk`xcCxf?6h5erwf}|7mX(}44tc:woz6:|-%kkte| jp}C]XO|a iaq Xcuxhc(kZ1pp"qofm`hFwMEoYrW|B*8,|cx{m}ymHL%C%l$uqo@]W55M}fo[ p}XY,rz ZzË1 o Gm[ ^!|UicuzGqkvtd]w}%>c[diIkdRXg }ty}^G{PqFe%{t]u}kvLZZT[[dwwokky}t↢|uzgސo|2OhVdf5aLzpkk|Ȗ}:o,kMMtioZ9Moc{pWJ`tSLnJga$[0SCS@ ʶaxatt1! OǓ +P8<BAhzs]uGA]yf=pw3Cyz+JrAy3h[ ++qc7gWt2At9|%Ɇ!kÒ]kU65mqNMqGH{Pn]Ec2Qh:m(f1/wy4q}daeJzQ¨&y{}z^ۊ^ނnlj|k|y}Xk u0[q]st0{u {dƎpē]W[Ğ1ʗ9nqF̈́7Ps%ԍx݁wz|.%{*݋u%L6 axatt2!O +dFZ)FÆBhz[|BrST`Cpn7Cq/U{C~3q]++{]?haqBU=# w{nid;?){nU YrXNWi%[OdF[fKkLOO#}4idaeKkM9E4ah[ 9}E,}@ \h'ex|yiqOH!@'_K$4}CC9qdz Ĵh9LuVwla^ _z'>Yz% c2y [SFR!J!AIO}oP^s]ah (oYF?6guϗ|htFV9gJc ueuEx{ԔI՗Ô]lØX}}oیijz农[r}]ɢќnΧ >Zskq0}|}f{Ĝ6Ǔ_WgϦ Ν.n}F DV[ <9o6aL$I0BA?;gZ axatt3t"u O +>z'f;@hukicZskY^MmnG5o8A{B}>q["(L[Cho7AL$-"|a}0HInRtlHW}h^q^1{akY?p<{<ʢ#Ʃ!b4ew yo\] 0 Ip[uDu=c6ut MG8-.GG}rJ]h^]g Iq\456zӑ\E|kt8H+Mb tcu6x{qQ||g8s{r݌o㈛ 77gz倏gdž7̉#8j]sns.{isCq]Zq$s&nxF 3HZɆ%$b$[5/-:-A%nCZ axattb1" NΙ +*!=hknnbB{]Bmk5C{l-UpAtLfZ{((qZ=hXn6B,|xnj ̴4+plQPqLUyÙqQd[Ea8Sc?kT~}Ė~>|EFCkLSwM΅ c΅:Ι2| [I8}~ tlN`k[\hlNC;—Ks l}A=X?.{m2κ,evcyt1݇kzĘfڂ{ؒƖ^ؙ(β(xʷ fmp#tMnvǂoooɿqrF2ɽ'H~ļLX axattb2" N ()!ŏ@hkhaaw`[Fhi7Ck3UwA~=q[++}XBhalC_+! }p n3xlVYqYVĩtWa'[O`H[cMkQ̐ҏ4q6wEHkK9B4`hXe["v+La@hu1|?%"o|amZ:aFqz}sFkwe`cqBm{8Cw0B}Uhq`|U+CJ"A n{v{iteMpB$k= "tF|{CcN6|˙ƞ í JCq oLY ΀0 I] \`7`.E"r M9>%rLxo?rC]vh^Xi uLqg<*0|o;,k{(s{|iN~}\ fekE|wCߓ,֋~QԀwБQ}ana͂q zwnπ|Pˬ,ؖ,Іw׋.n[rasw5y hzgނ{`Ur܅olrE"iP;rokrs{hKc^ehaE axattb5W[$K\E;]EJEBqChW[mYh hSWRdGhrH9t@4xFwʢ#Ʃ!b4ew yo\] 0 Ip[uDu=c6ut MG8-.GG}rJ]h^]g Iq\456zӑ\E|kt8H+Mb tcu6x{qQ||g8s{r݌o㈛ 77gz倏gdž7̉#8j]sns.{isCq]]s$s&n|9 3HZɆ%$b$[5/-:-A%n@1 Ǩaxattc1! OǓ +S7L<] AhztaxODgyf=pw3Cyz+Jr>y3h[++qc7gWt2A|4$ȇ!tŒdz`Ëԉ95mqNMqG'{Pn]Ec2Qh:m9dI(4o}6aeJzQ7qrK~]~h^WgwKtMCxFԛ3ہtΏitZ5{S胖E^ fbkdwpswxwqb {|iڊizEd w~#*zbRyFZqfw}.|z {fyihxnSq{yWuo㘜nqFgc5i'tcxhx]|kI{qk2ulL? axattc2!O +aF`'UBhz]|?hMc`Cpn7Cq/U{C5q[*I{]?haqBU3#ȅ!w{nif1҄i?{nU YrXI"Wi%[OdF[fKkXA`ʞГ}4ndacKkM9E4ah[ 9}E,}@ \h'ey~yhqMH!@'_K$|4}CCInَ$h5LuVwla^ _z'>Yz% c2y [SFd̞rߞk䒿]>}oP^h]ah (oYFWגM؊uϖh{o=f芋Jc ufu7x{-DXC}oیijz冬ʟ͟Dr}C--ߟ莬R~Zskq0}f{tswoSgzn}7ly?f#qwn}M*|gM axattc3t"u N +lAn#U?huki]MZaY^MmnG5o8A{Bx>q[LL[Cho6C>$1"{tpl< mFnStlGRh^q^1{a,0~wSo0 n>q|tUcNWsZȪ}.ï*tJCq oLY ΀0 I] \`7`.E"r Mr|}g|k2iprC]{z^Xi”'ȅKqgkY?p<{<ʢ#Ʃ!b4ew yo\] 0 Ip[uDu=c6ut MG8-.GG}rJ]h^]g Iq\456zӑ\E|kt8H+Mb tcu6x{qQ||g8s{r݌o㈛ 77gz倏gdž7̉#8j]sns.{isCq]]s$s&n|9 3HZɆ%$b$[5/-:-A%nA ˢaxattd1 OƐ LM68d}1}AhzsZuIIVyd0iu%CwyUe>n)\["w+*pc,gUt,Jl9r%|t"cUhMyiw8oqB OqBHKn]Dc0tQh3m<{L.nnos4rn6`~eJyP;F9VhGPBB̩ ǪÚhYz c2} [S?I3830nO}oH^h]Xh(oRF8>tzȖ ||ft|<{M1{G] DFwq݉I݌ʋ\ʖɎ[|}|Ԍtو \zڃ]ʘבə՜ tFhsuwux\4hk@~l^}cu=uM c:2t| [q5׃$u$nuTlVak[ehGnmuV;P̧ƭuS?z oV^ 0 IE;K:^K:KK]x M^ o i6ctH]k^^gIqf5MpUW{Mm|f}}tkXwR~bfFu~vN}~Z΄8ćg}}{o|ڈ 44g#Zu}ωʍ4Տ#Gp`gyz)|dv{Cv^^iۈ#{(rv4 f o6|{Jr{Rz ǀ)z?\$ axattd6m=$c6pG`7P4B‰=hm=mhJ|dOWTcEhrA4t8?yC}5p]*La:h|w 4?$ !||nkdȅ C3xtF~hwSn dth ]skzJGF24oodeCm<4/B\gYt6BG!= ny|yh|pMC%= s!9CP >ʢ#Ʃ!b4ew yo\] 0 Ip[uDu=c6ut MG8-.GG}rJ]h^]g Iq\456zӑ\E|kt8H+Mb tcu6x{qQ||g8s{r݌o㈛ 77gz倏gdž7̉#8j]sns.{isCq]]s$s&n|9 3HZɆ%$b$[5/-:-A%nQW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_axe.mdl000066400000000000000000002132141475442401000252670ustar00rootroot00000000000000IDPO\>(>f>S]~«B(ڽLAFGFGFGFEDFFFrrruuurrrrFGFEDFFFrrrrrrrFGGFEEGFBB``````CCEGGEFGFrrrFGGFEEGFBB```````CCEGGEFGFrrrrrrrrDGFFFEDBBBCCCabbbC`CC``aa`CCECFFFEarraDGFFFEDBBBCCCabbbC`CC``aa`CCECFFFErrrrrrrrDGEEBC`````aa``C`bbba````FErrruurrDGEEBC`````aa``C`bbba````FErrrrrrrrrrrrrrGGDEDDDCCDEFEEEDDBBabaaGGaabccba`CEEErrrGGDEDDDCCDEFEEEDDBBabaaGGaabccba`CEEErrrrrrrrrrrrGGDDDDDCDDCCEGFEDBEba`GG`ba`CEEFFCrrGGDDDDDCDDCCEGFEDBEba`GG`ba`CEEFFCrrrrrrrrrrrrrrrGGEEEDDDD`FGDDDbbaDDE`aGaCCCaAACECErrrrrrrrrrrrrrrGGEEEDDDD`FGDDDbbaDDE`aGaCCCaAACECErrrrrrrrGGGGFDDD`FFb`EEbbbbbaCCCCCEEEGrruwxyyxwwxyyxwurrrGGGGFDDD`FFb`EEbbbbbaCCCCCEEEGrrrrrrrrrrrrDGECCCCCCCCEECAAaEEaaaa`EEEFrrsttuy{}zz}{yuttsrDGECCCCCCCCEECAAaEEaaaa`EEEFrrrrrrrrrrrrGGGEBAADDEEDCCAbcb`bbbaaabaEFrqvtrrstxvxwtsrrtvqrrGGGEBAADDEEDCCAbcb`bbbaaabaEFrrrrrrrrEGDBBBDCCDDCCbbb``bcbba```CEFrrrussrvtrssurEGDBBBDCCDDCCbbb``bcbba```CEFrrrrrrrrrrrBCAADFEFF`CC`abbaccaFFDBBBDEEErtxwvuutvzzvtuuvwxrrBCAADFEFF`CC`abbaccaFFDBBBDEEErrrrrrrrrrrrBAAAECCCEF`abbaDDaBBFDDEEtwyzyxxz}|zxxyzywtrrBAAAECCCEF`abbaDDaBBFDDEErrrrrrrrrCCDCC``DD```abb`abb``FFa`aabbaaCFFrrsvy{zwvz~zvwz{ywsCCDCC``DD```abb`abb``FFa`aabbaaCFFrrrrrrrrrrGGEEFE`a`BB`B`ba`aabaab`abbaaa`FFrrstvywtsuwwustwyvtsGGEEFE`a`BB`B`ba`aabaab`abbaaa`FFrrrrrrrrrrGGGDBBBBBBAABB`aa``abbbaDDFFrrssvvtsstvvsssrrGGGDBBBBBBAABB`aa``abbbaDDFFrrrrrrrrEGGEDBBBCDC``DDFaEEEEEEFCrsrttrrrEGGEDBBBCDC``DDFaEEEEEEFCrFGGFFCBCDEFFDbcbabbbaabbaaEEEEEFrrssuvvvvussrrFGGFFCBCDEFFDbcbabbbaabbaaEEEEEFFGGFCBBBBBBBBEaDDbaababa`abbaFFFrus`uxzzxu`surFGGFCBBBBBBBBEaDDbaababa`abbaFFFvxxxvFFGEBBBDDDCCECC``bcb`bEGDBFFFrxtsstxrFFGEBBBDDDCCECC``bcb`bEGDBFFFsstttututsFEGEDEEEDDBAAAAAbaaa`CDFFFFxsrr`vuvxyyxvuvruFEGEDEEEDDBAAAAAbaaa`CDFFFFuuuuwwwuuFFFGECCCBBCBAAAABBDDBDC``CC`FCFFxsrqquvwwwwwwvrFFFGECCCBBCBAAAABBDDBDC``CC`FCFFxuuuFFCGEBBBCABBDDBDBDCCCCEEFFvqqqxxqqxFFCGEBBBCABBDDBDBDCCCCEEFFxuuxyBBDDCDCFzvqquttuqqqqvyzBBDDCDCFBDFFCFCFyzvtrqqqqqqqqqqqqqqqqvzBDFFCFCFzzBDFIaIa`vttvBDFIaIa`yBDGIbIb`vvttvvvBDGIbIb`wBDbabdb`BDbabdb`BDbabdb`uuBDbabdb`yDbabdb`Dbabdb`xyxDbabdb`xDbabdb`uxababcb`vwxwxxxxwwababcb`wacbbcb`uuvuuuuuuvuwacbbcb`yxacbccb`ssssssssacbccb`xacbccb`uacbccb`wyvacabcb`yacabcb`wvyacbbcb`uwvacbbcb`xwuacbccb`wxwwxxxxwxwwxvuacbccb`xwwacbccb`vvxuvuuuuuuvuacbccb`xwtytvacbcbb`ywssssssssxacbcbb`wwxtacabcb`yysuwacabcb`xxvxacbbcb`xysxyxxvwacbbcb`xwwxvxxwuacbccb`wwvxywtuacbccb`wxwvtwvxxwacbccb`tuvuvwrtuacbccb`utrrrrrwvtxrrrrrtuacbcbb`wwussvvuwtuwvvwacbcbb`xuttutrrrvxwvtwtwvwxwtsrrswyxwvuacbcbb`wxvtvwvusvvuuvxyyxvvwacbcbb`xuvwxyxwurrvvvssvwrrrwyzzzyxwv`cacac`xywvxyzzyxwussuwyz{{{zywvww`cacac`xvwxyzzzywvusrvsttssuvuwxxyzz{{{zywwx`bacac`wyyvwy{|||{zxvusrqrsuvxz{|||{ywvyy`bacac`xxwwyz{{{zzyxxwusvsruutuwyz{{zzz{||{zxwy`bbdab`xyzwxz{|||{zywvtrqqqqqqrqqrtvwyz{|||{zxwzy`bbdab`xywxz{||{zzz{{zywusvustusvxy{||{zyz{||{zxxy`bbdab`xyzxyz{|||{zywvtrqrrqqqrrrrqrtvwyz{|||{zyxzy`bbdab`xyxxz{||{zyz{||{yxvssuwxz{||{zyyz{{{zxwy`bbcab`xyzxyzz||{zzxwutsrssrqqqrrssrstuwxzz{|{{zyyzy`bbcab`xywxz{{|{yxz{||{zxwurqrrsuwyzz{|zyxxyz{zyxwy`cacab`yzzxxyz{{zzywvtsrstsrqqqrstssstvwyzz{{zyxxzz`cacab`xyvwyz{{zxwyz|{zzyxvsqrrstvxyz{{zxwvxyyyywwy`b`aa``yzywxxyzzzyxwutssstsrqqqrsutsstuwxyzzzyxwxyzy`b`aa``xyuvxyyyxvvxz{{zyywurrrrrsuwxyzzywvuvwxxxvvyx`a`````wyzywwxyyyyxwvtsssttsrqqrsttssstvwxyyyxwwwyzy`a`````vxyuvwxxwvtuwxzzyyxwtrrrrstvwxyyxvuutvwwwuvyx`a`````wyzywvwxyyxwvussrtutrqqqqrtutrssuvwxxxxwvwyzyw`a`````vxyuuvwvutttuwxxxxwtsrrrrrstvwxxwuuuuuuvvuwyyvwyzywuvwxxwvutsrsuusrqqrsuusrstuvwwwwvvwyzywvyyvuvvuttuutuvwwvtsrrrrsstuvvutvwvuuvvvwyywwyxywuuwwwvutsrrtttsqqqstttrrstuvwwvuvwyxywwwyyvvvvutvvvtuvvutsrrqrtsstuuttwxwvvvwwxyyxxwxyxxwutuvvutsrruutsrrstuurrstuvvutvxxyyxwxxyywwwwvvwxwuuuttsssrruustuuuvxxxwwxxxxyzzzyzyywwvttuuttssuvutsqqqstuvussttuuttvwyyyzyzzzywwxxwwxxxvuuttttsruvuuuvvwxyyxwxyxxyz{{yz{{zywvttuuttuvwttvuqqquvttwvuttuuttwwyz{{zy{{zywxyxwxyyxwvwvuvvuqvxwvwxxxxzzyxxzzxz{{{z{{{{zywuuvvuuvxuwxvurruvxwuxvuuvvuuwxz{{{{zz{{{zxzzxxyzzyxxxwvwxvvyxwwxyxyz{yxx{zyz{{{zz{{||{zwvvwvuuwvxyxvurruvxyxvwuuvwvvwz{||{{zz{{{zyz{xxyzyyxyywwxxvwyyxwxzxyz{zywzzyz{{zyzz{||{zywxxwvvvz{zwusrqrsuwz{zvvvwxxwxz{||{zzyz{{zyzzxyzzzyxzywxyywswyzywz{xyz{{ywvvxzzzyyz{{{{zywyyxwwy{{yutrqqqrtuy{{ywwxyywxz{{{{zyyzzzxvvxy{{zyx{zwyzywrwxzywzzwxz{{xwvvxzzyyzzz{{{zywzzxxyzyywtsrqqrstwyyzyxxzywyz{{{zzzyyzzxvvwx{{zxwzzwyzywwwyywvvwvxxxwwwwxyyyyz{zz{{yyxzyxxyxxwvvtsrrstvvwxxyyxzzxyy{{zz{zyyyyxwwwwxxxvwvvwxywwuwxxwvvwvuttuwxwxzyyzz{zzz{yyxyxwwxxzzywutrtuwyzzxxwwyzxyy{zzz{{zyyzxwxwtttuvwvvwxxwuvwxwwwxwuttuwwwxyyzzz{{zz{yyxxwvxz{{zywussuwyz{{zxwxyxyy{zz{{{zzyyxwxwtttuwxwwwxwvvwxwwwxxvutuwxwxyxzzzz{zzzyxwxwxzz{{zywussuwyz{{zzxwyxxyzzz{z{zzxyxwxwutuvxxwwwxwvvwxxxyyxwuuuxwxyxyzzxz{{zzyxwwwxz{{zzxvtrtvxzz{{zxwxxxyzzz{z{zzyxyxwxuuuwxyyxxxwvwwxwxwxwvuvuxwxwxyxzz{{yzyxwwxyz{zzyxvssvxyzz{zyxwwxyzyz{zzxyxwxwxuuuvxxwxwxwwvwwxwwwxwuuvvvwwwwyxzz{yzyxwwxzz{zyywuruwyyz{zzxwwxyyyzzzzywwwwvvvuuwxxwxxwwvwwxwxvwvvtuwuvuvxxyzz{yzywvwxzzzyyxvuruvxyyzzzxwvwyyyzzzyxxvuvuwuvvwwwxwxwwvvwvvwwvwvtwuwuwuwyxzzzxyxwuwxzzzyxwutbbbbbbdddddefdbdddiijjjjjhijjjjiidddddefedddbbbbbtuwxyzzzxwuwxyxzzzyywuwuwuwuvuvxwvvwvbbbbbbbbbbbbbbbbdddddddddddddddddddddbbbbbbbbbbbbvwvuvvvvuutvuuuuwyxzzzxyxvuwxzzyxwvtrgggdhhhhhhgfhhhhhhgdgggetvwxyzzxwuvxyxzzzyywuuuutuvuwvvvuvwvgigffiigewuuvwuuvusuvuvvvwwzzzxyxvuwxzzywvusrffdgeeggeeegggffehfefsuvwyzzxwuvwyxzzzxwvvtutututvuuvuuwufffhhfuvuuvuvutstuvuuwyxzzzxyxvuwxzyxvusrefdgefggeggggffefgdefsuvxyzxwuuwyxzzzxywuututusttuvuuvueedggeuutuuuvtssttutvwwyzyxxwuuvxyywutrrefcgfefgegggfeffegceertuwyyxwuuvxxyzyxwvtuvtutttututuuueedgfevtstuvutsstuttvxyzxwxwuuvxyxvtsrdecfefefdddgffeeefcddrstvxyxwutvxwxwuxvttustusttutstvdedfeduvstuuttssyyxwxwuuvxywusrraaaaaaaaaacccaaaaabbbbdddbdbbbbbbaaaaaccbaaaaaaaarsuwyxwustuutttwutstuststuttsvubbbbbbaaaacccbbccccbbbbbabbabbbbbbbbbbcccbbbbbbbbttutsutuvvwvtrrrdeeeddbbbbbbbddddb```````````````bdbbbbbbddbbddbbrsttwuststssrtttsttueefffgcaaabbbeefgfeeeddcbccbcegggeeeedbbbegggeecctuussrrgghggfeffffeeiigffecaaaabbbaabbceggfedefgghgfgfffssuutststrrstsssscghhhddddfdddeefghhheghbdggdghjehhhgfeedddgggefcbrgghggfeffffeeiigffecaaabcccaaccceggfedefgghgfgfffutstsrrssssssccdccehigccciiihiijfahcbdggfghiafjidcccgjjjiigebbghhhfefgfggfhjigfcccbbbceghbdcccefhgfefgfhhihhgggsssscccccfhgdddhfgiiiigaacbbeghfhieaaddddccfhjjiihfbbhggfefgedccikihgcedcccceijidegeeefihgghhghijjihggdcccccgifeeidadhiiigaabbbeghgfgebaddddedadiiiiigbbbhggefgeccdijihggdeeeccdijjjifehifgfihhfeeeefiiffeedcccdcdegghecdgfgecabbcffghegddbbcegfgdcehggedcbbbggefeedddijfeeeebbehheeggghhfehijfehiiiihcceefffggidddgeecceefgeecccebbbcheghedbbebeccceegfeecbeebbbdefdcbbcihfedddecbchjiigggggcehhieeeffhihfcbbeeggghhhhfehgfccddcabdefbbchhdghdbbbdbgedbacddcbbcdebbdeedddfghhccefddeedbgijiijjiccefgdccdffeghebbbbbbccggghedffedffecbfccdbcfhhdffdbbcdbhfffabcffecccddegefcbbcggfaacdijiheeehihhiiibdggfcbbffeeeeebbbbbbaafffcbdfdceghhcacccdbceggceedbbgcbhffeabccgeccccgggedbaabcdcaaadijjigfffghhhhhddghfbbfeecceeeffgedaaafcbbbdccceghhcabcccbceffcddcceecbhffeabcccdfddcfggbaabaabccccbadggiihedeeffggfffeeddiigcbcegffffgebaaecaacecbbcdhhhcabcfgcccdeccdcdefccgffdbbccccffedeffaaabbceffddccfddfghfecccdeeeedcbehifcbbcefefeffgcbaadaabefaabfbggecbceefccdcbbbbbcbdccfeecbceccbfedcefeeaaabceeebcdcdcbbbcfheccbbbceeddddefcbabaacccaacecefdcbccddccdbbabbaabcccddcc`cdfccedbdfgfdaaabdbbcbbbabdfdcecbaabbaaaaaabceddbbcccbccbbaaaaaabcbcccb`ddebbcbabdgfdaabbaabaaabedfaaaaaabaaaaccccbabbaabcba`````aabaabba`cccbcbaaacdbbabdbaaaaabddaaaadcabbbabbbaaaa```abaa``````acbaaa``bbbbabaacdbbbcddbbaaccdaccccdaabdcccccbbba``aabb``abcbcbaa``aaabcbbdddbddddebbaabbdccccdcaacefggffeedcbabeca``aceebcbbbbcbbecchifdbddeeddbbbbbdcdcccaabdiiihhfbcddbbeca`aa`adggdbccdbcgcehjjifbbceddddbb``eeeecaaabcgghihgbcdhhfedbccaabcadhgcddeiheegijjiebaafbddbcb```ffecaaaabfeeefffbcghhhgcdeab`aeecdhfbcghgeghiiiiecaabuxyyxu```ddbabfgedgcbegffgggffghecbbttvvttuxyyxussssssttvvttbbaaa`ssssssceecbabcbbcdcbabceecaaaaaaedadbb`aabbffdcbbdfhffcaabdeggfbaadcbaaaaabbdebbcbbbbddccbbbbbeb``bbbbbbeeeeedcbcfghjfcbccdddhgbbbbdbbdhidaacidccfdbedggfddfghb```bba`bbefedddccdghijiccddcccgiigdbaccfddcaacehccebedcbcdcfghh``aabba``befeddeccefccghhhecbabfhihfcaacedddccbegcbgedcbbabcfgggaaabaaab``eeeeefddedcbggghfcabbeghhgfaacebceffhggbhjhgbbabccdhhguwxxwtaa``bbeacdbbhjihgfhjhffeaccccchhg sstussuwxxwuc rrsrrrssuutt bbba`rrrrrraa`````aaaaaaaaaa```aaaaa ddebb`abbbbbaaaaacccecefebaaccddbbbb`````dbbbabbdeedbbbbbb defbdbbfebccccaaccccceggfcbbcebbcabccaabggfebdfedhiifdghhg fggbdbbeebcccdbdcccadfghhfccedc`abcdbbbbgecbdfedgiihdeffhh gggbdbbefabddeggfcabefghiiihdc`abcdcdbbbcbbdefdfhhheeedfhh ggfbdbbfgaadeggfeabdefhiigfea`abcdceaaba`bcefeeffeedbbehhh efebbedbbgcaabfgfebbceghijhedcbaaabbdcaa``bbcefeffecbaaaeggg effba```abeefcbgbaaacfedbccgijjihhhgggccbccc``bcccchhhhggeedcccegffgebb````bbbba``````bbfefda```adcadcccfeecccdefijjjiihhgdcdedeffdddddikkjjjiheeddffgifeda``addeca``a````dffda`````abdddbaaaabbcbaefccgfhiifffffiihgfeeecbceeeggbbbdhhhggfdcbbbcfghhdedaaabeecbbbcdbaaacfeebaaaadegghgedccddeaaafgefgjjjiedcbdgffeeeca`````abaaacfffeccbaaaaabcgddddcbcdffgcbghhhfddddcedcbabccccehgeddefcbaaagihhkjihggdbbcfeedcbaaab```bbcceggggfeccbbbaabcdbcdecddhfgebbfgijjhgcccccdabddccccffcbccbbaaaagheefjjjkkjheeeeihhgffedbbbbeeeghhhgdbbbbcdeffeKMbbceccdfggfccdefijifbaaaccdbbhiecbbeebccdccbaabffcccehhiiifbbbbfeeeeeedddddihijkkheddddhjhghgfbcefccccfedddddeghhgcaaacdecchgdcbbeeabccehebbaccaabcdeffdaaaabccccccccdcbdihghhhhcbbbbbdgfgfdceefccbaaedccddefffggfecdeeccceaaabccaabbhhfeccbaaabbbccaaaaaabbbbbbccaabfffeeddcc`````addcbbbcddbaaacccccccdeedcbbbdeffaacaaabdcba`aegfecb```aaaaaa```aaaaa``````aaddddaabaaabdbbaaaccdeddrrrrrrraaa``````aabbbbrrrrrrttrrrrrrrrrrrr rrrrrrrrrr FrrrtuuurrrrrrrrrrrrrrrrrttrrrrttrrrHrrrrtuutrrrrrrtruurrrrrrruurrtvvutrrrFFFFFGHIIrrrsturrrrrtuuutrrrrrtwvutrrrrruvvurrrJFJIIrrrsuvwuuurrrrrrrtuvvtrrrrvwwvtrtttuvttuttFFFFuuuvuuuuurrrruuuvuurrrtutrrrrrrrtrrrrrIJrsuuuutttuuurrrrrsrrrrrrrrrstutrrrrrrrrrrrruuutrrrrrrtrLIFFrrrrtttrrrruutsrrrrrrrrrrrrFFrrrsrttrrrttrrrrrrrrrrrJGFFrrrstrrrrrrrrrsrstusrrrrrrJFFFrssrsrsrrrrrrrstur rr JFFrrrsrsrsrrrrrrusrrJIKNrrrrsrrsrrrrurrrLrrrssrrrrsrrrrrLNrrsssrrrrrrrrrrLLIrssrtsrrrrrrrssrrrrrrsrrrrsrrrrrrrrsrstrrrrrrrsrrrtrrrrrrrrrsrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrtrrrrrrrrrrttrrrrrrrrrtrrtrrrrrrsrrrrrrrrrrrrtrrrrrrsrrrrrrrrrrsrrrtrrtrrrrsrrrsvsrrrturruurrrurrsvurrrrruvtsrruuutrrrtuusrvwurrrrrtvwwurruvvrrsuurrrrrrrtrrtrrrrrrrrrrrrrrrrruvvusrrrrrrururrrrrrrrrrrrssrrssssrrrrrrrrrrrrsrrssrrrrrrttrrrrsttrrrrrsrtsrrrrrttrrrrrutrrrrtttsrrrrrrtrrtttrsrrrrrsttsrrrrturrrsuutrrrturrrrrtsrrrsuuvurrrsvvusrrrrrurusrrrsrtsrrrrrrsssrrrrtssssrrrusrrrsrurrrrrrsrrrrrrrrrrrrrrrtsrrrtuurrruurrrrrrrrrrrrrrrrrrrrrrrrrrtrttrrrttrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr    >   > / / > >                   ^dțaxrun1ț1Í`n" beAAtp^hi| edW`hN`Œaxrun2Œn4{dW|o"~A$F}|rockrun2~|~|c}<~g~gF~(~~~>~A$F}|rockrun3~|~|c}<~g~gF~(~~~>~A$F}|rockrun4~|~|c}<~g~gF~(~~~>~A$F}|rockrun5~|~|c}<~g~gF~(~~~>~A$F}|rockrun6~|~|c}<~g~gF~(~~~>~A$Fxzstand1yy_xy}\aEaxpain395}C,>$'4_Ee~0}+|~).HaCaH}7\Af_?b&|`aEaxpain485~B,>#'9bEe/"+|).HeDaG7`Aeb@a%|hcHaxpain590B0L&,5jHg2-}.]1GmHdG|W4hBgkBc['{q&bOaxpain6>.E;(/j73rMh;5x7Y;tOd.qP&3qHgtJb]/v{pain1~}}9}|h}q~>}}{}~|@|I>W~apain2Z~}\~eYZ X{`[E[0[MZW`PZ&WaK`[5X}bpain3[}v]}eZ[ Y{ap\e\0\[W`R[XbCa\5_~gpain4b}c~8ab `|gdbpc.bbfWbK_gLfc3nrpain5p~pcop1o~qepep?pMopWoHnrUqq?{pain6~}}9}|h}q~>}}{}~|@|I>s/iUaxdeth1U*UEI@E3sBmD??[DOvBiO/04s}fpDaxdeth2?.D2L)/5gAu3.}.[2HjApOW4fT e^N#~ X0%Y\/(iD3k"RSdaxdeth7SU ,OCH+^O2G.;KG*8K.6Mi/:Q5R1#32"Rc$&dM.`P,!i$8OW1@yaxdeth8y#jF_ b e@7>Y>W YUh[ ?6;CpS>2 e=1z\Y1@yaxdeth9y#jF_ b e@7>Y>W YUh[ ?6;CpS>2 e=1z\Ypqdeatha1pp\pquuq~uws~Ur~wCgzmdeathb3mkkm5lhz\kqlCkkg{klhzUhz'mCfflwdeathb4kwjqZjulv5jvff\jqZkqCjqGirffjqkvgfJff'ltCgGlVdeathb5lVkR]jTlU5kVgG^kR`kRCkRJjSgGjQVlVhGJgG+lSCg5nFdeathb6nFlA\lDnE5lE~h5alAZmAClA&kBg6kAGmEi5`h5'nCCh5oDdeathb7oDm?mCoC4nDh5\m?rn?Km?mAh5m?oDi5Jh5 oAAi3sAdeathb8s?p;q>~s>?r?j4apu9k2Zs7[s6Hs7s8|j3vr8v: k1Xj2"u7Hdeathc1`4h\CHJVIC}deathc2}~W4rwBMS'B{deathc3{|PF@Q1NLU{deathc4{|B;wU 0T{uwdeathc5{w;|wwu_w;wvvuYvwwvv1vvuT{\cdeathc6{^o|__ \`^9bw^u]S^ _c^\5ab\PzITdeathc7zK:{NL1~I`K}==> H =9CGG;z.=deathc9z0D{42<~/W~0CssvDvt^t>uem~qnailatt2m~m~npnnooFoInnqIqo^o>pEr~vlight1r~r~qstssrsqtdt>ssvDvt^t>uem~qlight2m~m~npnnooFoInnqIqo^o>pE|}vrockatt1|}~|}[}~}}v7~H~?~H}}vG~vf~v>FV}y[rockatt2V}~W}fWXWZyXqYX*XQZyZDY[y^[y+X6e}jrockatt3e}f}ffgfjsgZh8h=gNii>hjCj=h6m}qrockatt4m}m}cnonqsoqo9o=npqApqCq=o6t}{xrockatt5t}u}Xvwvw{hvwdw>vw{xKxx{w{*wE|}vrockatt6|}~|}[}~}}v7~H~?~H}}vG~vf~v>Frvshotatt1rrWtuttwtupuLttvJvu^u>udosshotatt2oo]prqpqqEq(qpsHsq^q>rEbgshotatt3bcZdedfere9e=dQfQgBfgeg?e6agshotatt4ab[cdcfrdeoeLdffLfgfg=eofkshotatt5fg[hihkziqjoj>iQjkBkkDk?jokpshotatt6klmnmornohn(noNpHpp[p,ooG7z}axatt1GlՏU[ьNhNu#Ipw8VdXi/Wf@Sdqu7qZkDM}z;7w:JUq.3aaxatt26mBH7q; 3k]>AKD!A;XYXBœ6ya]B!tDzaxatt3DfߊK^i],[Eyq_c"fasttwz~q6|vxxa"~ӴWaxatt4U{a´ ĭ@S%(* #h~Sh̤5ӳ"BWW "RWoaxatt5jw8egRamn$e:VWVezTi~easR[sdi[ZV^o>rUaxatt6>̂>_CwL-DȁItFHDM,KEqFr[UNTʀNtHLtO(_ҳaxattb1aҤtϞ>kacIr(oYqmp10rd_BihY֬axattb2Ი<ϤϻĝI1\ȶZȼNƻɷ}ɨ֬ S;tdaxattb3;t?uLRKLWNTMTNWd`:]]U~MjHfaxattb4jn0*!s.|x!@s%rHbw 2{0=z5;v4~Cf?1,sFa%Ce:|'=t8 Mnaxattb58 c92<4dtEjB?H>DD ?BvCmMSLA6uKjwIn I6>rUaxattb6>̂>_CwL-DȁItFHDM,KEqFr[UNTʀNtHLtO(rUaxattc6>̂>_CwL-DȁItFHDM,KEqFr[UNTʀNtHLtO(MxLSaxattd1iRr&.] ]hZPxJO?d#%=c)`"*`$$tLO"U"8M'wES tISa#$Unaxattd2$g)99"+V0iRk+<-8,>/&>Nn0E-1pUi!Sl/)0[axattd3>쌢sUr sCz"wspwsRwP\t[DwswsOaxattd4^oC` W閙ZLgLcߔYeۙke1;`ɠpOףfz]Ywaaxattd50R6rUaxattd6>̂>_CwL-DȁItFHDM,KEqFr[UNTʀNtHLtO(QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_coil.mdl000066400000000000000000002227301475442401000254430ustar00rootroot00000000000000IDPO}{>J>0n>I?SGwBdm5V?@11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111111111111111!111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111!1111111111111111111111111111111111111111111111111!1111111111111111111111111111111!1111111111111111111111111111111111111111111!111111111111111111111111111111!1111111111111111111111111111111111111111111111!111111111111111111111111111111!!11111111111111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!11111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!1111霜1111111111111111111111111111!!1111蜜1111111111111111111111111111111111111111111111111!!1111蜜11111111111111111111111111111!1111霜1111111111111111111111111111111111111111111111111!1111蜜111111111111111111111111111111!!1111蜜11111111111111111111111111111111111111111111111!!1111眜1111111111111111111111111!1111眜11111111111111111111111111111111111111111!1111111111111111111111111111!!111111111111111111111111111111111111111!!1111111111111111111111111111!111111111111111111111111111111111111111!11111111111111111111111111111!!11111111111111111111111111111111111111!!11111111111111111111111111111!11111111111111111111111111111111111111!11111111111111111111111111111!!11111111111111111111111111111111111111!!11111111111111111111111111111!!11111111111111111111111111111111111111!!111111111111111111111111111111!11111111111111111111111111111111111111!111111111111111111111111111111!!1111111111111111111111111111111111111!!111111111111111111111111111111!1111111111111111111111111111111111111!111111111111111111111111111111!!1111111111111111111111111111111111111!!111111111111111111111111111111!1111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111!!111111111111111111111111111111111111!!1111111111111111111111111111111!!111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111111!!111111111111111111111111111111111111!!1111!1111111111111111111111111111!111111111111111111111111111111111111!1111!!11111111111111111111111111111!!111111111111111111111111111111111111!!1111!11111111111111111111111111111!111111111111111111111111111111111111!1111!111111111111111111111111111!!111111111111111111111111111111111111!!1111!#!11111111111111111111111111!!111111111111111111111111111111111111!!1111!""!1111111111111111111111111111!11111111111111111111111111111111111!1111!#"!!11111111111111111111111111!!11111111111111111111111111111111111!!1111!#11111111111111111111111111!11111111111111111111111111111111111!1111!#11111111111111111111111111!11111111111111111111111111111111111!1111!11111111111111111111111111!!11111111111111111111111111111111111!!1111!!11111111111111111111111111!11111111111111111111111111111111111!1111!1111111111111111111111111!!11111111111111111111111111111111111!!1111%!1111111111111111111111!11111111111111111111111111111111111!1111!#!1111111111111111111111!1111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111!!1111##!111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111!1111#!1111111111111111111111111111111111111111111111!!11111111111111111111111111111111!!1111!#!111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111!1111!#!1111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!11111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!1111111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!111111111111111111111111!111111111111111111111111111111111111111111!1111!!111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!!111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!11111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!!11111111111111111111111111111!1111111111111111111111111111111111111111111!1111!11111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!11111111111111111111111111111!11111111111111111111111111111111111111111!1111!1111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!!11111111111111111111111111111!111111111111111111111111111111111111111111!1111!!11111111111111111111111111111!!11111111111111111111111111111111111111111!!1111!!1111111111111111111111111111!11111111111111111111111111111111111!1111!!11111111111111111111111111111!!11111111111111111111111111111111111111111111!!1111!1111111111111111111111111111!1111111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111!1111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111!111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111!!111111111111!!11111111111111!1111111!!11111111!!1111!1111!!1111!!1111!1111!1111!1111!1111111111!!111!111111!1111!!1111111111111!!111111111111111!!111111!111111!!!111111 D #$ D D  $ D $ "  %  !  % . .C '= G ' @ @> GDY F_ -] 4cNI dJ GD[ Na da ]D\o ? ? o f fK6 6  h[l   h k            ! !"#$#"$ "!# !!#$" $ !""%&'(%)*)'(*+(,&,+'')%)*('+*+,(&%('&,-./0-121/02304.43//1-120/32340.-0/.4*Okcaxrun1UVk UVo UVoVVk>UVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NU.{ƛ ;|}ŐLwę{Ë{]~d ;}L{|򔙍]dU$trockrun2VXVX$UVVVCUVVVVUhVVsXV7Q.;E;KOQK>>[p.?F?pOpp>>J**c$y$o9H|8t9((b|'t]x8xx'x{ p:p}LpXpb pp}L璕pXpbU zrockrun3VXVX$UVVVCUVVVVUhVVsXV795$d'5O;"6~,)P<"6'VHSY,'@z{ax l%Kz(zI|("v{|asz]t*}o} RX|>!WWQgľ QS|ľ>SWQaUءrockrun4VXVX$UVVVCUVVVVUhVVsXV7*9b|(V.$,x!|X;9dDJ@-Jz!_r|v Zv}zk{KsIv"n|s gkXo#fz ?IyC#FW>g֞ >@؝?ӡ!ԡ@P20\5,E._O]b2/@}axn-H{.w.~}aww]w/|s| ]a>aW]aЙ ]^ЕKљѕ^W]aU)wrockrun6VXVX$UVVVCUVVVVUhVVsXV7U.?E?MSUMAA[u/DFDtOutAAJ..c)y)ooFf:k5kj0vgoAtOf5vou7'{Vm[hhČ ps7Ɖ'ÅVo[mzM0sʡstand2PRPU MRPRCNRRPRPQmPQaRR7U1vDlrG~MBX'{QNtGWwEZn1zJrRiCu$rrLxDEi;n6hf:{j5v@FtpFg9m4kk0vZpAsOg5u pv7'|Vn[ihǍ rsŊ4ʊ ƇVp]nzM0s̠stand3PRPU MRPRCNRRPRPQmPQaRR7V1vEsIOBY'{RtIPwEqo zJsRjCv$srLNzEeit>rFi:n5hm0uapBsOg5t rx4 }Vo]jkˎ rtNj4̋ ʈOp]okM/sǡstand4PRPU MRPRCNRRPRPQmPQaRR7S1tDlrG~MBW'{QMsGWwDqm1xIrQhCu$ppKNxDeg;m6he:{j5t@Ft;t>pEg9k4kk/vgoAsOf5uou7'|Vm[hhōprË4NJ'ćVo[mzM/tástand5PRPU MRPRCNRRPRPQmPQaRR7R;tBnpF|LD~V(zPMrFYvBgj1xGpPfCs$npJNwBef;k5hc:g4s?Fs:u>oDf9j3kj/vgn@tOe4vmt7'}Vj[dz noֽ7Ë'ԿVm]jz*Ocaxstnd1TVTX'RUUUCTUPTU TRhTUrUU4NU~OIzSvB{|@px?\wQNsA̫ {ɣ?Ф"̚N]i ?"N]i 5xXpain2:Xx:X~$:V~;VxC:Vx:V;U~m:Vxs;V~3Cc KOsQ@7K5hP9NP,RRIMN>rT@8XBDMOQR@3{.yr%Ķ%éN7B<6 3{0zr,  S4|@6~63xZpain3:Xx:X~$8V~;VxD:VxP:V:U~h:Vxs;V~9CaLM/C{;zr7ž%'0ıND@K6"C{@zr&%#NC|@E|6I~OIzSvB{|@px?\wQNsA̫ {ɣ?Ф"̚N]i ?"N]i*Oucaxdeth1KXuKX{ KV{tMVu>KVuKVMU{mKVusMV{.NUKVuKVMU{mKVusMV{.NUKVuKVMU{mKVusMV{.NUKVRKV\MUWmKVRsMVW.NUIV#IV+KU&pIV#sKV&.NUHV:GWGUyZGWyOFVyFV|GUHVu?HV9HWHVu\HWuOGVuGV|HVJUuNXdeatha2MX{MX,KVMV{CKV{WMVMUhMV{sNV7LVeLVlLV-KVLVOKVKVKVNUDNUpNW*LUNWHLWKWKUsLVLUMVMUKUJUXKVMKVKUJUJVJVMVy>MV:LWMUyZLWyOLVyLV|MUNVu?NV9MVMUu\MVuOMVuMV|MUOUvTXdeatha3RX{RX$PVRV{FRV{RVRUhRV{sTV7QVeQVlQV-PVQVOPVPVPVSUDSUpSW*QUSWHQWQWQUsQVQURVRUPUOUXPVMPVPUOUOVOVSVz>SV:RWRUzZRWzOQVzQV|RUSVv?SV9SVSUv\SVvORVvRV|SURUoVXdeatha4UXsUXw$TVwVVsDUVsPUV}UUwhUVssVVw7TV|eTV~lTV~-SV|TV|OSV|SV}SV}VUyDVU}pVW}*TUyVWyHTWyTW}TU}sTVTUUVUUSU~RU~XSV~MSVSURURV~RVVVs>VVy:UWyUUsZUWsOTVsTVy|UUyVVo?VVy9VVyVUo\VVoOVVoVVy|VUyRU_VXodeatha5UXdUXh$TVhVVdDUVdPUVnUUhhUVdsVVh7UVleUVmlUVm-TVlUVlOTVlTVmTVmVUiDVUmpVWm*TUiVWiHTWiTWmTUmsTVoTUoVVoVUoTUnRUnXTVnMTVoTUoRUoRVnRVoVVc>VVi:UWiUUcZUWcOTVcTVi|UUiVV_?VVi9VViVU_\VV_OVV_VVi|VUiRUPVXadeatha6UXTUXY$TVYVVTDUVTPUV^UUYhUVTsVVY9TV]eTV_lTV_-SV]TV]OSV]SV^SV^VUZDVU^pVW^*TUZVWZHTWZTW^TU^sTV`TU`UVaUUaSU_RU_XSV_MSV`SU`RU`RV_RV`VVT>VVZ:UWZUUTZUWTOTVTTVZ|UUZVVP?VVZ9VVZVUP\VVPOUVPUVZ|VUZWU(\X9deatha7ZX+ZX2$YV2ZV+FZV+ZV6ZU2hZV+u\V29YV5eYV7lYV7-XV5YV5OXV5XV6XV6[U2D[U6p[W6*YU2[W2HYW2YW6YU6sYV8YU8ZV9ZU9XU7WU7XXV7MXV8XU8WU8WV7WV8[V,>[V2:ZW2ZU,ZZW,OYV,YV2|ZU2[V(?[V29[V2[U(\[V(OZV(ZV2|[U2RUVX!deatha8UXUX,TVUVCTVUVUUhUVsVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTV TU UV!UU!SURUXSVMSV SU RU!RVRV!VV>VV:UWUUZUWOTVTV|UUVV?VV9VVVU\VVOUVUV|VURU VXdeatha9UXUX,TVUVFUVUVUUhUVuVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTVTUUVUUSURUXSVMSVSURURVRVVV>VV:UWUUZUWOTVTV|UUVV ?VV9VVVU \VV OUV UV|VURU VXdeatha10UX UX,TVUV FUV UVUUhUV uVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWSWSUsTVTUUVUUSURUXSVMSVSURURVRVUV >UV:TWUU ZTW OTV TV|UUVV ?VV9UVUU \UV OUV UV|UURUVXdeatha11UX UX,TVUV FUV UVUUhUV uVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTVTUUVUUSURUXSVMSVSURURVRVVV >VV:UWUU ZUW OTV TV|UUVV?VV9VVVU\VVOUVUV|VUTUpYXdeathb1VXsVXx UVxXVsCVVsPVVXUxhVVssYVx4VV|eVV~lVW~-UV}VW|OUW}UW~UV~XVzDXV~pXW~*VVzXWzHVWzUW~UV~sVWVVWWWVUV~TV~XUW~MUWUVTVTW~TWWVs>WVz:VWzWUsZVWsOVVsVVz|WUzXVp?XVz9WWzWVp\WWpOWVpWVz|WVz?UoEXdeathb2CXrMCXw$@VwDVrDCVrPCV~CUwhCVrsEVw7AV|eAV~lAW~-AV}AW|OAW}AW~AV~CVzDCV~pCW~*AVzCWzHAWzAW~AV~sAWAVCWCVAV~?V~XAW~MAWAV?V?W~?WCVs>CVz:BWzBUsZBWsOAVsAVz|BUzCVo?CVz9CWzCVo\CWoOCVoCVz|CVz1Un6X~deathb34Xo4Xu$3Vu4VoC3Vo4V|4Uuh4Vos6Vu73Vze3V|l3W|-2V{3WzO2W{2W|2V|5VxD5V|p5W|*3Vx5WxH3Wx3W|3V|s3W~3V~4W~4V~2V|1V|X2W|M2W~2V~1V~1W|1W~5Vq>5Vx:4Wx4UqZ4WqO3Vq3Vx|4Ux5Vn?5Vx95Wx5Vn\5WnO4Vn4Vx|5Vx/UM4X]deathb43XO3XV,0VV3VOC0VOW3V\:3UVm3VOh4VV71VYe1V[l1W[-0VZ1WYO0WZ0W[0V[3VWD3V[p3W[*1VW3WWH1WW1W[1V[s1W]1V]2W]2V]0V[/V[X0W[M0W]0V]/V]/W[/W]3VP>3VW:2WW2UPZ2WPO1VP1VW|2UW3VM?3VW93WW3VM\3WMO3VM3VW|3VW0U&4X7deathb53X(M3X.,0V.4V(D3V(P3V5:3U.h3V(s4V.72V3e2V5l2W5-1V32W3O1W31W41V44V0D4V4p4W4*2V04W0H2W02W42V4s2W62V63W73V71V50V5X1W5M1W61V60V60W50W64V*>4V0:3W03U*Z3W*O2V*2V0|3U04V&?4V094W04V&\4W&O3V&3V0|4V01U6Xdeathb64X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6Xdeathb74X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6Xdeathb84X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6X deathb94X4X$3V4VC3V4V4Uh4Vs6V74Ve4Vl4W-3V4WO3W3W3V5VD5Vp5W*3V5WH3W3W3Vs3W3V5W 5V 3V1VX3WM3W3V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO5V5V|5VWRs\Vdeathc1ZVtZV{ YU{ZUtCYUtWZUZR{hZUtw\U{3ZTeZTlZU-YTZUOYUYUYT\T}D\Tp\U*ZT}\U}HZU}YUYTsZUZT[U[TYTWTXYUMYUYTWTWUWU[Uw>[U}:ZV}[TwZZVwOZUwZU}|[T}\Us?\U}9[U}[Ts\[UsO[Us[U}|[T}WR\Vdeathc2ZVZV YUZUCYUWZUZRhZUw\U3YTeYTlYU-XTYUOXUXUXT[TD[Tp[U*YT[UHYUXUXTsYUYTZUZTXTWTXXUMXUXTWTWUWUZU>ZU:ZVZTZZVOYUYU|ZT[U?[U9ZUZT\ZUOZUZU|ZT`ReVdeathc3cVcV bUeUAcUcUcRhcUreU5bTebTlbU-aTbUOaUaUaTdTDdTpdU*bTdUHbUbUbTsbUbTcUcTaT`TXaUMaUaT`T`U`UdU>dU:cVcTZcVObUbU|cTdU?dU9dUdT\dUOcUcU|dTeRjVdeathc4iViV$gUjUCiUPiU-iRhiUrjU3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUgUgTshUhTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hViTZhVOhUhU|iTjU?jU9iUiT\iUOiUiU|iTfRpjVdeathc5iVriVw$gUwjUrCiUrPiU-iRwiiUrrjUw3hT}ehTlhU-gT}hU}OgU}gU~gT~jTzDjT~pjU~*hTzjUzHhUzhU~hT~shUhTiUiTgTfTXgUMgUgTfTfUfUjUt>jUz:iVziTtZiVtOhUthUz|iTzjUp?jUz9jUzjTp\jUpOiUpiUz|jTzeRZjVjdeathc6iV\iVd$gUdjU\CiU\PiUj-iRdhiU\rjUd3hTgehTilhUi-gTghUgOgUggUhgThjTdDjThpjUh*hTdjUdHhUdgUhgThshUjhTjiUjiTjgTieTiXgUiMgUjgTjeTjeUieUjiU^>iUd:hVdiT^ZhV^OhU^hUd|iTdjUZ?jUd9iUdiTZ\iUZOiUZiUd|iTdfRHjVXdeathc7iVJiVQ$gUQjUJCiUJPiUW-iRQhiUJrjUQ3hTTehTVlhUV-gTUhUTOgUUgUVgTVjTRDjTVpjUV*hTRjURHhURhUVhTVshUXhTXiUXiTXgTVfTVXgUVMgUXgTXfTXfUVfUXjUK>jUR:iVRiTKZiVKOhUKhUR|iTRjUH?jUR9jURjTH\jUHOiUHiUR|jTRfR4jVEdeathc8iV6iV=$gU=jU6CiU6PiUC-iR=hiU6rjU=3hTAehTClhUC-gTAhUAOgUAgUBgTBjT>DjTBpjUB*hT>jU>HhU>hUBhTBshUDhTDiUEiTEgTCfTCXgUCMgUDgTDfTDfUCfUDjU8>jU>:iV>iT8ZiV8OhU8hU>|iT>jU4?jU>9jU>jT4\jU4OiU4iU>|jT>fR"jV3deathc9iV#iV)$gU)jU#CiU#PiU1-iR)iiU#rjU)3hT/ehT1lhU1-gT/hU/OgU/gU0gT0jT,DjT0pjU0*hT,jU,HhU,hU0hT0shU2hT2iU3iT3gT1fT1XgU1MgU2gT2fT2fU1fU2jU&>jU,:iV,iT&ZiV&OhU&hU,|iT,jU"?jU,9jU,jT"\jU"OiU"iU,|jT,fRjV'deathc10iViV$gUjUCiUPiU&-iRiiUrjU3hT$ehT%lhU%-gT$hU$OgU$gU%gT%jT!DjT%pjU%*hT!jU!HhU!hU%hT%shU'hT'iU'iT'gT&fT&XgU&MgU'gT'fT'fU&fU'jU>jU!:iV!iTZiVOhUhU!|iT!jU?jU!9jU!jT\jUOiUiU!|jT!eR jVdeathc11iViV$gUjUCiUPiU-iRhiUrjU3hTehTlhU-gThUOgUgUgTiTDiTpiU*gTiUHgUgUgTsgUgTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hVhTZhVOgUgU|hTiU ?iU9iUiT \iU OiU iU|iTfRjVdeathc12iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU>jU:iViTZiVOhUhU|iTjU?jU9jUjT\jUOiUiU|jTfRjVdeathc13iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU >jU:iViT ZiV OhU hU|iTjU?jU9jUjT\jUOiUiU|jTeRjVdeathc14iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUgUgTshUhTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hViTZhVOhUhU|iTjU?jU9iUiT\iUOiUiU|iTfRjVdeathc15iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU>jU:iViTZiVOhUhU|iTjU?jU9jUjT\jUOiUiU|jTDVaHYqdeathd1GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd2GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd3GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd4GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkHVPMY`deathd5KXRKYY IXYKXR?KXRKX^ KVYmKVRrMXY3JX]eJX_lJX_-IX]JX]OIX]IX^IX^LWZDLW^pLY^*JWZLYZHJYZJY^JW^sJX`JX`KX`KX`IX_HX_XIX_MIX`IX`HX`HX_HX`LXT>LXZ:KYZKWTZKYTOJXTJXZ|KWZLXP?LXZ9LXZLXP\LXPOKXPKXZ|LXZHV<MYLdeathd6KX?KYE IXDKX??KX?KXK KVDmKV?rMXD3JXIeJXKlJXK-IXIJXIOIXIIXJIXJLWFDLWJpLYJ*JWFLYFHJYFJYJJWJsJXLJXLKXLKXLIXKHXKXIXKMIXLIXLHXLHXKHXLLX@>LXF:KYFKW@ZKY@OJX@JXF|KWFLXKX):JY)JW"ZJY"OIX"IX)|JW)KX?KX)9KX)KX\KXOKXKX)|KX)HVMYdeathd8KXKY IX KXCIXQKXKV mKVZMX 3JX eJXlJX-IX JX OIX IXIXLW DLWpLY*JW LY HJY JYJWsJXJXKXKXIXHXXIXMIXIXHXHXHXLX>LX :KY KWZKYOJXJX |KW LX?LX 9LX LX\LXOKXKX |LX HVMYdeathd9KXKY IX KXCIXQKXKV mKVZMX 5JX eJXlJX-IX JX OIX IXIXLW DLWpLY*JW LY HJY JYJWsJXJXKXKXIXHXXIXMIXIXHXHXHXLX>LX :KY KWZKYOJXJX |KW LX?LX 9LX LX\LXOKXKX |LX TRxYXdeathe1XV{XX,VUXU{CVU{RXU XRhXU{sYU4VTeVTlVU-VTVUOVUVUVTXTDXTpXU*VTXUHVUVUVTsVUVTXUXTVTTTXVUMVUVTTTTUTUXU|>XU:WVWT|ZWV|OVU|VU|WTXUx?XU9XUXTx\XUxOXUxXU|XTjRgpXxdeathe2nVjnXp,kUpnUjCkUjRnUw nRphnUjspUp4mTtemTvlmUv-lTumUtOlUulUvlTvnTrDnTvpnUv*lTrnUrHlUrlUvlTvslUwlTwnUxnTxlTvjTvXlUvMlUxlTxjTxjUvjUxnUk>nUr:mVrmTkZmVkOlUklUr|mTrnUg?nUr9nUrnTg\nUgOnUgnUr|nTrjRYpXideathe3nVYnXa,kUanUYCkUYRnUg nRahnUYspUa4lTeelTgllUg-kTflUeOkUfkUgkTgnTcDnTgpnUg*lTcnUcHlUclUglTgslUilTimUimTikTgjTgXkUgMkUikTijTijUgjUinU\>nUc:mVcmT\ZmV\OlU\lUc|mTcnUY?nUc9nUcnTY\nUYOnUYnUc|nTcjUJpXZdeathe4nXKnXR$kVRnVKCkVKWnVYnURhnVKhpVR7lVVelVXllVX-kVWlVVOkVWkVXkVXnUTDnUXpnWX*lUTnWTHlWTlWXlUXslVZlVZmVZmVZkVXjVXXkVXMkVZkVZjVZjVXjVZnVM>nVT:mWTmUMZmWMOlVMlVT|mUTnVJ?nVT9nVTnVJ\nVJOnVJnVT|nVTjU@pXPdeathe5nXBnXH$kVHnVBCkVBWnVOnUHhnVBhpVH7mVMemVNlmVN-lVMmVMOlVMlVNlVNnUJDnUNpnWN*lUJnWJHlWJlWNlUNslVPlVPnVPnVPlVOjVOXlVOMlVPlVPjVPjVOjVPnVD>nVJ:mWJmUDZmWDOlVDlVJ|mUJnV@?nVJ9nVJnV@\nV@OnV@nVJ|nVJkU9pXIdeathe6nX;nXB$kVAnV;CkV;WnVHnUAhnV;hpVA7mVEemVGlmVG-lVFmVEOlVFlVGlVGoUCDoUGpoWG*mUCoWCHmWClWGlUGsmVImVInVInVIlVGkVGXlVGMlVIlVIkVIkVGkVInV<>nVC:mWCnUnV1:mW1mU*ZmW*OlV*lV1|mU1nV&?nV19nV1nV&\nV&OnV&nV1|nV1jUpX-deathe8nXnX&$kV&nVCkVWnV,nU&hnVhpV&7mV*emV+lmV+-lV*mV*OlV*lV+lV+nU'DnU+pnW+*lU'nW'HlW'lW+lU+slV-lV-nV-nV-lV,jV,XlV,MlV-lV-jV-jV,jV-nV!>nV':mW'mU!ZmW!OlV!lV'|mU'nV?nV'9nV'nV\nVOnVnV'|nV'jUpX"deathe9nXnX$kVnVCkVWnV!nUhnVhpV7lVelV llV -kVlVOkVkV kV nUDnUpnW*lUnWHlWlW lU slV!lV!mV"mV"kV jV XkV MkV!kV!jV"jV jV"nV>nV:mWmUZmWOlVlV|mUnV?nV9nVnV\nVOnVnV|nV*#cnailatt1)- ((((<#g$x(TNU :::%:9k:k:`NU;:6:6:C:;9k6:y;:YNU;:6:6:C:;9k6:y;:YNU>>-j>:RwgABv{@1"1!!"!r1111!!!r1111111111111111""!!!!rrrsrrssrsrrs!!!!!1!!"""rrssrr!!rr11"""!!"!!!!!rrrr!!111111!!!!!"1!!"!!1rrrr!!!11"!!!!!11rrr!!!!!"rrrr!!!rr11!!"!!"rr1r"!!!!!rrr!!rr11!!!"!!rrssrssrsrrs!11!!!!!"rr!rr11111111111111111111!!"!!srrrr!!11!!!"!!rrr!!rrr111111111111111111"!!!!!!rrr!!11!!!!!!1rrrrr!!rr111111111111111111!!"!!!1rrr!1111!"!!!!rr!#rrrr1111111111111111111111!!!!!!!rrrrr!!11!""!!1rrr!#rrr1111111111111111111111111111111111"!!!!!!r!11"!!!!!!!1rrrr!!rrrrr111111111111111111111111111111111!!!!!!!!r!11!!!!!!!1rrrrr!!rrsrrr111111111111111111111111111111!!!!"!rrr!!11!!"!!!!r!!sr1111!!!!!"!1rrr!!11"!!!!"1rrr!rrsrr1111!!1111!""!!!!rr!#11!!!!!"rrr!rrr11111111!"!!!!1rrrr!#11111!"!"!!!rrrrrrr11!!!!11"!!!!!"!!1rr!!11!!!!!!!rrr!rrsr11!!!!!!11!!!"!!!!!1rrrr!!11"!!!"!!!"rrr!rsrr1111!!!!!!1111!!"!!!!rr!!11111111!!!!"!!!rr!!rsr1111!!1111"!!!!"!1r!111111111!!!!!!!1rrrrrrrsrr111!!!!111!!!!!!!rr!111111111"!"!!"rrr1!!rsrr11!!!!!!11!""!!!"!rrrr1111111111111111!"!!!!rrr!rrsr111!!!!!!111!!!!!!!rrr!111111111111111111111111111111"!!!"!!!"1rrr1!rssr11!!!!!!11"!!!"!!!!!rr!1111111111111111111111111!!!!!!rrrr1!rstr1!!!!!!1!!!"!"!!r!!1111111111111111111111111!!"!!!r!rttsr!!!!!!!!"!1rrr111111111111111111111111!!!"!"rr!stttsr!!"!""!!!rrr1!!111111111111111111111111111111111"!!!!"rrr1!rrstvtsr!!!"!!!!!rrrr!1111111111111111111111111111!!!"!!1!r1!!!!!!1!!!"!!1rr1!111111111!!!!!!!!!!!!!!!!!!!rrr1!111111111111"!!"1!!!""!!!!!rr!111111111111111"!!!!!!!!!!!!r!11111111111111!!"!!!!11!!!!rr1!111111r1111111111!!!!!!!!!!!!!!!!!11111!!"!"!1!1!111111111111111111111111111111111111111111111!!!!!!!!!!!!!!!!!11111!!!"!11!!1111111111111111111111111111111111111"!"11111!!!!11!1111111111111111111111111111111111111111111111111!"1111111111111111111111111rrsrrr11!!!!111!!1111111111111111111111111111111111111111111111!111111111111111111111111rrrssrr1!!!!"!111!!111111111111111111111111111111111111111111111111!!1111111111111111111111rssr!!!!!1!!!!!!!!!!!!1111111111111111111111111111111111111!"1111111111111111111111srr!!!!!!!!!!!!!!!!!!11r111111111111!!1111111111111111111111!!111111111111111111111111111111111111111!!!1111111111111111111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!111111111111111111111111111111111111111!!!1111111111111111111111111111111111111!1111111111111111111111111111111111111111111!!111111111111111111111111!!!!11111111111111111111111111111111!11111111111111111111111111111111!11111111111111111111111111111111!111111111111111111111111111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111!!!1111111111111111111111111111111!!111111111111111111111111111111!!!11111111111111!!11111111111111111!111111111111111!!!!1111111111!11111111!!!1111111111111111111111111!!!!1111111111111111111!!!!!1111111111111111111!!!1111111111111111111!!!!1111111111111111111!!!!11111111111111111!!!!!!111111!!!!111111!!!111111!!111111111111111111111111111111111!!1111111111111111111!!111111111111111111111!!11111111111111111!1111111111111111111!!11111111111111111!!!!!111111!111111!!!111111!!111111111111111111111111111111111!1111111111111111111!!111111111111111111111111111111111111!!1111111111111111111!11111111111111111!!111111!!!!111111!111111!!111111!111111111111111111111111111!1111111111111111111!!!!1111111111111111111!11111111111111111!!1111111111111111111!!!11111111111111111!!!!!!! " " '   ' * * .   .+ 0 !+) ! 7 ( > >/ !) (/( U U M% MM XA Y+A$ A+M1 LG D D A @AA: w q p l6d/ c/ p= c> [6d d w7 [ ~ ~* |* || y* yp*  * +  * w*                   $  9 # #) ?   94 '/   m F:9 F m '  aa/N uN u            !"#$%&'%( ")#$*)'$('#+!)#")%"!&"%  (!*&&*$%$''(!+**+#$#)')&%",-./012-,3/4453.617,04853-2164/14,.0.-60.127/5862,732/35-70/684-569:;<9=;>??=;:@><?>>@<<@::9<;=9=?<:>;ABCDAECFGGECBHFDGFFHDDHBBADCEAEGDBFCIJKLIMKNOOMKJPNLONNPLLPJJILKMIMOLJNKQRSTQUSVWWUSRXVTWVVXTTXRRQTSUQUWTRVSYZ[\Y][^__][Z`^\_^^`\\`ZZY\[]Y]_\Z^[abcdaefghijklcjmecgbnhionlidmlbadhpfnhgdnbjcbgfkbgjceaemdfokkoijilclmfpoophihnlndkjgqrstusvwxyz{|}z~}wqxy|yt~|qutxvxwtq}v|t{xyx{yzy|}|~}r{rqr~s~vsuqz}wv}{zqwsr~tsDRړaxrun1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxrun2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxrun3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxrun4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxrun5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxrun6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_:rockrun1c:)Myc:)MjQpX>K pdoooo Ah@@Au@]DDpOp%>xpL󞍽ʜʛP-ʛEIʜnŰ}ůƮdOŴm̪ʰŮȬ9Ʀ_ðzŪiŵћIПɜʞ<ʚ@ƟxɜbɢګyڥW2ۧEKګڬ«äڭ ڤ LWťLۦKí dΜͭ ͧl{ǰ>ƞKů1Ŗbœ^|~Ņ9‰B^_ɥ9Ũ@̾*IZn[kQQ``M}rockrun3`]Sn^4bk&Uxa m]pn~FIsxǀan'4#}^,=+ |(7H< 2W(W$OUO OC[[ O AmOULREmEbO A}OGK= rm#WcGI9.{=>䆛煚S.(煚^C邛ZӺĖ—շ2Ӻ'ŖaָKĔtΗ(ěΐoɔ`}ʐrŔ뉙Kߐی邜煗_ۉ{灙q݉⬮ڝ}۞P穮<䭪&a穫Aߚl؞ϋы1۞t}ʈ~ۀCΉvPڅ?䘦A؄1lakjʟϖǞImg^bD=^y}@䏣.ⓗ>ǂ7lCxʈSlSIrD՚G|rockrun4OX>mHFSYIC}L]m[WmdFpyI[}g}"g nF]? | +H2$%ZIHMR䛌0’ 䛌eK暐nɯ~ĤĥȲʯǤcɮHǢk̦'Ũ¦ϡ7ɥS¢ʟǢ硌Iۥء瘑8䛋U؝v旌q۝߿گڰ侤0߭b価A߭ذћѝତ0رł̗ڐ;ۓA̚Ņژ>ଡ଼Kڗ1~a{lŰѦ ŬSyto8tBL^ڌ8֒@⤙)ݨKɒGnLyǘN{QS~PϬM2yrockrun6z^t3zMty ^=My 2b68G=6y^H(6jG 2}6tLzNLHĚ2byw y>{dW…AśH„1beadga 6g22n96X6fgGa*3xdLϻѻ/ѻe>ӻp㭀} 㬏bOl7`xgŽG–ļջ9ѻUźxոgǻߤͣ͜Wޤ2ߞ͞eߟK̢n̤ͤ2͜ǰ1ɱ>Ƕ>͜HŴ2ǛeŘƕâb|Nj9ōCb_ʪ9ǭ@Ù*ƌI`nakQRddŎN|K::zaK3H|UDEzLz@Vz&U"V Iovm6wVeYz6ŋD]keokIi EuG=I>X:ibCa0~K[7M䔕T2I䔕n?䔗jۙPۜ ۗGºmؙCʶ=!Qɰdzfǰr闕Cݥ"ڞW䔚䓔c؞䒖s؟Ȝֺ۶YÞ1ÖLݳmE۶ֻɪΥV۶ ۶Iĩ̡Ә7̢HYӟ7చFΥ LjkĢSϴ&̷ǻrzvdVbђ֍eߥ0䟐FYo}ΗU`kQ`ڨA~:uۡstand3rygpz9wy{yAv|yugǗ:uǘuK|žv:h>I::xaK3H|SDDxLyAVy&U"V Imvo6wVeYz6ċF]meokIi EwE|=H>[:ibAa0~I[7▕T2L▕l4▗ۙPۜۗGmؙCɶ=!Qɱdzfűr瘕?ۦ!ڟR┙䔓e֟⒖sءɜֻڷYÞ ŖLݴk7ڶռɪ"ΥVڶ ڷLĪ"ʡӚ7ʢHYӟ7߱FΥ Ljk¤Sδ&ʷǼr{vdVbѓ֍eߦ0䡏FYm}̘U`kQ`کJ~9uءstand4oygmy9tyyyAt|~yMugɔ:uɖuA|Ěěu9h=I::yaI3H~S~D~DyKy@Uy&U"~V Im~tl6vVdYw6ňD}[kdmiIh EuE=H>X9iaC`0~KZ7M䒔`1>䒔p6䒖jؗ؛ ؖ·z՗C|ʳ= Qʯɰcǯw锔?ݢ ۛY䒙搓b؛䏕sڝśط۳Y I߰k龙F۳ָʨ"ϢV۳ ۳IŨ̞Ֆ7̟HY՝7୙FϢDžkġSϱ&̴ɺpysdUbѐ֋e࢙0杏FWm}ΖU~`iQ^ۦJ|7wԣstand5l{gkt9r{v{Ar|{{{wgʐ:wʒwA|Ŗŗw7zĻ!Q̪ʬcɪr¶돖Cߝ"ۗR䌚拕bڗ䉗wۘ俜ڳݯY黟 黗Lજk븜Eݭڴ̤"ўVݭ ݯLǤ"ΚՒ6ΛJY֗8⨜FўɁkŝSӭIΰ ʶotooRbӋ؅e0旑F¡Uk|ϐUz`hQ[ۡADRړaxstnd1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd7|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd8|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd9|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd10|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd11|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxstnd12|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxpain6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_Kpain1c5Ixc5ŒIxȓNiP`5Rfb)UdRVgHlgS { FO~YF> wpy{ SsO}KlWR]Nb~Kw/Uty?ȯȯT2&ȯd?ƱmعڸP׸bKػض(޹ڷӸձf׹vӶq׼ͯ+ӰͫRƲƬDʰ{ïg̲}T &޸p?߻͸̱O޽ &{ʸý µ4ɮGRȵ4޷?ɻpɰɣQަں ޲žEweŻʼDӶ/Ԫ=Ÿtl~xáVT{إH=opain2RFKF MYM'FhAGFF=8 ?Y?6h1:iK8dK^Y oS4a^#XEkSS_ErcO]fh(ZbWY08AH58Bhs:}A{M/FGPr@D/<*=Sp8IhjDkKsDg\EbW=z_A\K]fNBhN9Uw'Nk UAqWt-.ɕ=wAV00A91%AnԼuYӾ}ԻRo ս(z R" ">s"e?$3ƾ8ûU?džB36gB65}ĕs%̾J'Č %"jƿ%.G"%̽.s%,Ƅ6/1:U1-***?85j$0S'ƮAi11}G P0_y4 wpy{ SsO}KlWR]Nb~Kw/Uty?ȯȯT2&ȯd?ƱmعڸP׸bKػض(޹ڷӸձf׹vӶq׼ͯ+ӰͫRƲƬDʰ{ïg̲}T &޸p?߻͸̱O޽ &{ʸý µ4ɮGRȵ4޷?ɻpɰɣQަں ޲žEweŻʼDӶ/Ԫ=Ÿtl~xáVT{إHDRړaxdeth1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth7|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth8|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxdeth9|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_SoyXudeatha1SqVq:VqbSrSqVr VrISrSq~Vq~:Vq}bSr~Sq}Vr~ Vr}ISr}UqWq8WqbTqxUq]Ws2WsIUsTsTqTsNUsWs}WsWrXr}CVr}PWsWsXr?WqgVrVrWqgWq}qXr?WqXrWuyWu{WuyqWu{2Ws{WWu{IVu{Ws{oVs{vWu| Ws|Wu{.Wo{Vq{GVq{Wo{7Vo{zVq|Wo|Wq{*WsyWsz-WrzXryCWryPWqzWqyqXrz]uy]u{]uyq]u{2]s{W]u{I]u{]s{o\s{v]u| ]s|^u{.]o{]q{G\q{]o{7]o{z]q|]o|]q{*]sy]sz-]rz^ryC]ryP]qz]qyq^rz<]sz]s|]r|^rzC]rzP]s}]s|^r|F]q|Z\r|\r}]q|Z]qzq^r|C]q}^r}<\t|[s|[s{]s{L\t{\t\t ]s)]q6\ph\py]q|6\p|s]q{f\p{[]s|)^p:]s [q|[q\s[s\q[q{foykudeatha3fqiq:iqbfrfqir irIfrfq~iq~:iq}bfr~fq}ir~ ir}Ifr}hqiq8iqbfqxhq]is2isIhsfsfqfsNhsjs~jsirkr~Cir~Pjsjskr?jqgirirjqgjq~qkr?jqkriuyju|juyqju|2is|Wju|Iiu|js|ois|vju| is|ju|.io{iq{Giq|jo|7io|ziq|jo|jq|*jsyjs{-ir{jryCiryPjq{jqyqjr{iurjutjurqjut2istWjutIiutjstoistvjut istjut.iotiqtGiqtjot7iotziqtjotjqt*jsrjss-irsjrrCirrPjqsjqrqjrsiubjudjubqjud2isdWjudIiudjsdoisdvjue isejud.iodiqdGiqdjod7iodziqejoejqd*jsbjsc-ircjrbCirbPjqcjqbqjrciuRjuUjuRqjuU2isTWjuTIiuUjsUoisUvjuU isUjuU.ioTiqTGiqUjoU7ioUziqUjoUjqU*jsRjsS-irSjrRCirRPjqSjqRqjrSpu)pu+pu)qpu+2ps+Wpu+Ipu+ps+oos+vpu, ps,qu+.po+pq+Goq+po+7po+zpq,po,pq+*ps)ps*-pr*qr)Cpr)Ppq*pq)qqr*iujujuqju2isWjuIiujsoisvju isju.ioiqGiqjo7ioziqjojq*jsjs-irjrCirPjqjqqjriu juju qju2isWjuIiujsoisvju isju.ioiqGiqjo7ioziqjojq*js js-irjr Cir Pjqjq qjriuju juqju 2is Wju Iiu js ois vju is ju .io iq Giq jo 7io ziq jo jq *jsjs -ir jrCirPjq jqqjr iujujuqju2isWjuIiujsoisvju is ju.ioiqGiqjo7ioziq jo jq*jsjs-irjrCirPjqjqqjrkusluulusqluu2ksuWluuIkuulsuoksuvluv ksvluu.koukquGkqulou7kouzkqvlovlqu*lsslst-krtlrsCkrsPlqtlqsqlrtPurPutPurqQut2PstWPutIPutQstoPstvPut PstQut.PotPqtGPqtQot7PotzPqtPotPqt*QsrQss-PrsQrrCPrrPQqsQqrqQrsq{8>qzb;q{x=qz]>s{2>szI=s{;s{;qz;szN=sz>st>su>ru?rtC>rtP>sx>sv?rv??qvg=rv=rx>qug>qtq?ru??qx?rx<>sx=sx?sxA>r{?s{2?q{=s{=q{~>q{j=qx?qx^>s{ >qxZ>oo>or>or>oo@>oo>orj>ooq>or>uo >ur>ur>uo>>uo>ur>uoq>ur2>sqW>uqI>ur>sro=srv>ur >sr?ur.>oq>qqG=qr>or7>orz>qr>or>qr*>so>sq->rq?roC>roP>qq>qoq?rq<>sq>sr>rr?rqC>rqP>st>sr?rrF>qrZ=rr=rt>qrZ>qqq?rrC>qt?rt<=tssqL=tq=tx=tu >su)>qu6=puh=pxy>qs6=pss>qqf=pq[>ss)?px:>sx ;uO;uR;uOq;u';u);u'qq8>qb;qx=q]>s2>sI=s;s;q;sN=s>s>s>r?rC>rP>s>s?r??qg=r=r>qg>qq?r??q?r<>s=s?sA>r?s2?q=s=q~>qj=q?q^>s >qZ>o>o>o>o@>o>oj>oq>o>u >u>u>u>>u>u>uq>u2>sW>uI>u>so=sv>u >s?u.>o>qG=q>o7>oz>q>o>q*>s>s->r?rC>rP>q>qq?r<>s>s>r?rC>rP>s>s?rF>qZ=r=r>qZ>qq?rC>q?r<=tsL=t=t=t >s)>q6=ph=py>q6=ps>qf=p[>s)?p:>s q8>qb;qx=q]>s2>sI=s;s;q;sN=s>s>s>r?rC>rP>s>s?r??qg=r=r>qg>qq?r??q?r<>s=s?sA>r?s2?q=s=q~>qj=q?q^>s >qZ>o>o>o>o@>o>oj>oq>o>u >u>u>u>>u>u>uq>u2>sW>uI>u>so=sv>u >s?u.>o>qG=q>o7>oz>q>o>q*>s>s->r?rC>rP>q>qq?r<>s>s>r?rC>rP>s>s?rF>qZ=r=r>qZ>qq?rC>q?r<=tsL=t=t=t >s)>q6=ph=py>q6=ps>qf=p[>s)?p:>s q8>qb;qx=q]>s2>sI=s;s;q;sN=s>s>s>r?rC>rP>s>s?r??qg=r=r>qg>qq?r??q?r<>s=s?sA>r?s2?q=s=q~>qj=q?q^>s >qZ>o>o>o>o@>o>oj>oq>o>u >u>u>u>>u>u>uq>u2>sW>uI>u>so=sv>u >s?u.>o>qG=q>o7>oz>q>o>q*>s>s->r?rC>rP>q>qq?r<>s>s>r?rC>rP>s>s?rF>qZ=r=r>qZ>qq?rC>q?r<=tsL=t=t=t >s)>q6=ph=py>q6=ps>qf=p[>s)?p:>s q8>qb;qx=q]>s2>sI=s;s;q;sN=s>s>s>r?rC>rP>s>s?r??qg=r=r>qg>qq?r??q?r<>s=s?sA>r?s2?q=s=q~>qj=q?q^>s >qZ>o>o>o>o@>o>oj>oq>o>u >u>u>u>>u>u>uq>u2>sW>uI>u>so=sv>u >s?u.>o>qG=q>o7>oz>q>o>q*>s>s->r?rC>rP>q>qq?r<>s>s>r?rC>rP>s>s?rF>qZ=r=r>qZ>qq?rC>q?r<=tsL=t=t=t >s)>q6=ph=py>q6=ps>qf=p[>s)?p:>s puupuxpuuqpux2pswWpuwIpuxpsxopsxvpux psxqux.powpqwGoqxpox7poxzpqxpoxpqx*psupsv-prvqruCpruPpqvpquqqrvpupupuqpu2psWpuIpupsoosvpu psqu.popqGoqpo7pozpqpopq*psps-prqrCprPpqpqqqr|u|u|uq|u2|sW|uI|u|so{sv|u |s}u.|o|qG{q|o7|oz|q|o|q*|s|s-|r}rC|rP|q|qq}r<|s|s|r}rC|rP|s|s}rF|qZ{r{r|qZ|qq}rC|q}r<{tzszs|sL{t{t{t |s)|q6{ph{py|q6{ps|qf{p[|s)}p:|s zqzq{szs{qzqoudeathc4qq:qbrqr rIrqq:qbrqr rIrqq8qbqxq]s2sIssqsNsssrrCrPssr?qgrrqgqqr?qruuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqrusuuusquu2suWuuIuusuosuvuu suuu.ouquGquou7ouzquouqu*ssst-rtrsCrsPqtqsqrtu\u_u\qu_2s^Wu^Iu_s_os_vu_ s_u_.o^q^Gq_o_7o_zq_o_q_*s\s^-r^r\Cr\Pq^q\qr^uJuMuJquM2sLWuLIuMsMosMvuM sMuM.oLqLGqMoM7oMzqMoMqM*sJsK-rKrJCrJPqKqJqrKs<rq;gq:qr;?q>r>s>s>ArAsA2qAsAqA~qAjq>q>^sA q>Zo5o8o8o5@o5o8jo5qo8u5 u8u8u5>u5u8u5qu82s7Wu7Iu8s8os8vu8 s8u8.o7q7Gq8o87o8zq8o8q8*s5s6-r6r5Cr5Pq6q5qr6t; s;)q;6p;hp>yq96p9sq7fp7[s9)p>:s> q9q;s>s;q>q7o"u.deathc9q)q):q(br)q(r) r(Ir(q'q':q&br'q&r' r&Ir&q.q-8q,bq.xq,]s-2s,Is.s.q,s,Ns,s&s(r(r&Cr&Ps*s)r)?q)gr)r*q(gq&qr(?q*r*u"u$u"qu$2s$Wu$Iu$s$os$vu% s%u$.o$q$Gq$o$7o$zq%o%q$*s"s#-r#r"Cr"Pq#q"qr#uuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqru uu qu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqruuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqruuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqruuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqruuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqrWuaWudWuaqWud2WsdWWudIVudWsdoVsdvWud WsdWud.WodVqdGVqdWod7VodzVqdWodWqd*WsbWsc-WrcXrbCWrbPWqcWqbqXrcWuaWudWuaqWud2WsdWWudIVudWsdoVsdvWud WsdWud.WocVqcGVqdWod7VodzVqdWodWqd*WsbWsc-WrcXrbCWrbPWqcWqbqXrcWuaWudWuaqWud2WsdWWudIVudWsdoVsdvWud WsdWud.WodVqdGVqdWod7VodzVqdWodWqd*WsbWsc-WrcXrbCWrbPWqcWqbqXrcWuaWudWuaqWud2WsdWWudIVudWsdoVsdvWud WsdWud.WodVqdGVqdWod7VodzVqdWodWqd*WsbWsc-WrcXrbCWrbPWqcWqbqXrc\uQ\uT\uQq\uT2\sSW\uSI[uT\sTo[sTv\uT \sT\uT.\oS[qSG[qT\oT7[oTz[qT\oT\qT*\sQ\sR-\rR\rQC\rQP\qR\qQq\rR<\sR\sT[rT]rRC[rRP\sV\sT]rTF\qTZ[rT[rV\qTZ\qRq]rTC\qV]rV<[tUZsUZsS\sSL[tS[tZ[tW \sW)\qW6[pWh[pZy\qU6[pUs\qSf[pS[\sU)\pZ:\sZ ZqUZqWZsZZsWZqZZqSXo>]uJdeathd6XqE[qE:[qDbXrEXqD[rE [rDIXrDXqC[qC:[qBbXrCXqB[rC [rBIXrBZqJ\qI8\qHbXqJxZqH]\sI2\sHIZsJXsJXqHXsHNZsH\sB\sD\rD]rBC[rBP\sF\sE]rE?\qEg[rE[rF\qDg\qBq]rD?\qF]rF<\sFZsF]sFA\rI]sJ2]qJZsIZqJ~\qIjZqF]qF^\sJ \qFZ\o>\o@\o@\o>@[o>\o@j\o>q\o@\u> \u@\u@\u>>\u>\u@\u>q\u@2\s@W\u@I[u@\s@o[s@v\u@ \s@\u@.\o@[q@G[q@\o@7[o@z[q@\o@\q@*\s>\s?-\r?\r>C\r>P\q?\q>q\r?<\s?\sA[rA]r?C[r?P\sB\sA]rAF\qAZ[rA[rB\qAZ\q?q]rAC\qB]rB<[tAZsAZs@\s@L[t@[tF[tD \sD)\qD6[pDh[pFy\qA6[pAs\q@f[p@[\sA)\pF:\sF ZqAZqDZsFZsDZqFZq@Xo!]u-deathd7Xq)[q):[q(bXr)Xq([r) [r(IXr(Xq&[q&:[q%bXr&Xq%[r& [r%IXr%Zq-\q-8\q,bXq-xZq,]\s-2\s,IZs-Xs-Xq,Xs,NZs,\s&\s(\r(]r&C[r&P\s*\s(]r(?\q(g[r([r*\q(g\q&q]r(?\q*]r*<\s*Zs*]s*A\r-]s-2]q-Zs-Zq-~\q-jZq*]q*^\s- \q*Z\o!\o$\o$\o!@[o!\o$j\o!q\o$\u! \u$\u$\u!>\u!\u$\u!q\u$2\s#W\u#I[u$\s$o[s$v\u$ \s$\u$.\o#[q#G[q$\o$7[o$z[q$\o$\q$*\s!\s#-\r#\r!C\r!P\q#\q!q\r#<\s#\s$[r$]r#C[r#P\s&\s$]r$F\q$Z[r$[r&\q$Z\q#q]r$C\q&]r&<[t%Zs%Zs#\s#L[t#[t*[t' \s')\q'6[p'h[p*y\q%6[p%s\q#f[p#[\s%)\p*:\s* Zq%Zq'Zs*Zs'Zq*Zq#Xo]u deathd8Xq [q :[qbXr Xq[r [rIXrXq[q:[qbXrXq[r [rIXrZq \q 8\q bXq xZq ]\s 2\s IZs Xs Xq Xs NZs \s\s\r]rC[rP\s \s]r?\qg[r[r \qg\qq]r?\q ]r <\s Zs ]s A\r ]s 2]q Zs Zq ~\q jZq ]q ^\s \q Z\o\o\o\o@[o\oj\oq\o\u \u\u\u>\u\u\uq\u2\sW\uI[u\so[sv\u \s\u.\o[qG[q\o7[oz[q\o\q*\s\s-\r\rC\rP\q\qq\r<\s\s[r]rC[rP\s\s]rF\qZ[r[r\qZ\qq]rC\q]r<[tZsZs\sL[t[t [t \s)\q6[ph[p y\q6[ps\qf[p[\s)\p :\s ZqZqZs ZsZq ZqXo]u deathd9Xq[q:[qbXrXq[r [rIXrXq[q:[qbXrXq[r [rIXrZq \q 8\q bXq xZq ]\s 2\s IZs Xs Xq Xs NZs \s\s\r]rC[rP\s \s]r?\qg[r[r \qg\qq]r?\q ]r <\s Zs ]s A\r ]s 2]q Zs Zq ~\q jZq ]q ^\s \q Z\o\o\o\o@[o\oj\oq\o\u \u\u\u>\u\u\uq\u2\sW\uI[u\so[sv\u \s\u.\o[qG[q\o7[oz[q\o\q*\s\s-\r\rC\rP\q\qq\r<\s\s[r]rC[rP\s\s]rF\qZ[r[r\qZ\qq]rC\q]r<[tZsZs\sL[t[t [t \s)\q6[ph[p y\q6[ps\qf[p[\s)\p :\s ZqZqZs ZsZq Zqio|nudeathe1jqlq:lqbjrjqlr lrIjriqlq:lqbiriqlr lrIirlqmq8mqbjqxlq]ms2msIlsjsjqjsNlsmsmsmrnrCmrPmsmsnr?nqglrlrmqgmqqnr?nqnrmu|mu~mu|qmu~2ms~Wmu~Imu~ms~ols~vmu msnu~.mo~mq~Glq~mo~7mo~zmqmomq~*ms|ms}-mr}nr|Cmr|Pmq}mq|qnr}uiuluiqul2slWulIulsloslvul slul.olqlGqlol7olzqlolql*sjsk-rkrjCrjPqkqjqrkuYu\uYqu\2s[Wu[Iu\s\os\vu\ s\u\.o[q[Gq\o\7o\zq\o\q\*sYs[-r[rYCrYPq[qYqr[uKuNuKquN2sMWuMIuNsNosNvuN sNuN.oMqMGqNoN7oNzqNoNqN*sKsL-rLrKCrKPqLqKqrLuBuDuBquD2sDWuDIuDsDosDvuE sEuD.oDqDGqDoD7oDzqEoEqD*sBsC-rCrBCrBPqCqBqrCu;u=u;qu=2s=Wu=Iu=s=os=vu= s=u=.o=q=Gq=o=7o=zq=o=q=*s;s<-rr>rr>Fq>Zr>r?q>ZqCq?r?s>s=s=Lt=tCtA s@)q@6p@hpCyq>6p>sq=fp=[s>)pC:sC q>q@sCs@qCq=o'u3deathe7q/q/:q.br/q.r/ r.Ir.q,q,:q+br,q+r, r+Ir+q3q38q2bq3xq2]s32s2Is3s3q2s2Ns2s,s.r.r,Cr,Ps0s.r.?q.gr.r0q.gq,qr.?q0r0u'u*u'qu*2s*Wu*Iu*s*os*vu* s*u*.o)q)Gq*o*7o*zq*o*q**s(s)-r)r(Cr(Pq)q(qr)uu!uqu!2s!Wu!Iu!s!os!vu! s!u!.o!q!Gq!o!7o!zq!o!q!*ss -r rCrPq qqr uuuqu2sWuIusosvu su.oqGqo7ozqoq*ss-rrCrPqqqrU= >CKK$=1m>UD1d@aDa6dEc9d/w9f6cK/p$($ T!;#C w b |[ [[1[KWvWc[LE^/^OKjNZ^L[d1*/S g11D(D>R=>C9v9i=G(G%>@= >CKK$= 1m>A>R5p5b= 1v=S HVH>L2S,RS L /'h*q/'g/:'bL ,L6`6YGHO66_NsYnailatt23v33l>y>2S9R=R1U=S1U(wz1fy1:RDz(p I T:Cwp|W WWNW2WKSvScWHFY/YOEH\YHW E,**Rg,,@(@9R: :C5v5b9A(A,9U9 9CEE,9 ,p9A9R1p1b9 +}9NAVA>H2O(wKN G * hy!s*!g*:!bH w'wG1`/Yy@AOy/1__t^light1U= >CKK$=1m>UD1d@aDa6dEc9d/w9f6cK/p$($ T!;#C w b |[ [[1[KWvWc[LE^/^OKjNZ^L[d1*/S g11D(D>R=>C9v9i=G(G%>@= >CKK$= 1m>A>R5p5b= 1v=S HVH>L2S,RS L /'h*q/'g/:'bL ,L6`6YGHO66_NsYlight23v33l>y>2S9R=R1U=S1U(wz1fy1:RDz(p I T:Cwp|W WWNW2WKSvScWHFY/YOEH\YHW E,**Rg,,@(@9R: :C5v5b9A(A,9U9 9CEE,9 ,p9A9R1p1b9 +}9NAVA>H2O(wKN G * hy!s*!g*:!bH w'wG1`/Yy@AOy/1_DRړrockatt1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړrockatt2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړrockatt3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړrockatt4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړrockatt5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړrockatt6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړshotatt6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxatt6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattb6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattc6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd1|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd2|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd3|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd4|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd5|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_DRړaxattd6|mס|m쁈mn|vמmf|vv-vImҡmmnvҞmfvv-vIDivIiWinDirWi6IyWy-DyDy؜Wi^Wy>Wy,{({'rTr rCo'r emrUopRiiibr oevoro'oyAoy1ItGyGlIyGlIdwolfolGodpYKYUTVvڌbD/N􂸁[񗸐Ree*dQURgeRey(yrRr rCmvmir{({,rUr rC,r epr@rRipibr evr{V{>2,m dZhm]sdZgd:Zd mami`iYm{癑{Omi盾i_QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_nail.mdl000066400000000000000000004202641475442401000254420ustar00rootroot00000000000000IDPOwe>>%h>W. ~4QTB0Z19@ %%$r$%$!!! ppppppp #$&##$&# !! pppppppp  !!!! !!!!"r$%$##$%%%#r !! ! ppppppppppp  r#$&#"%$#! !! ppppppppppppp  !!!! !! !!! !! !!!!! !! ! !!!!!!! !!!!!!"!!!!""!!!!"p #$%%%#r!#$&#r! rrr !!!! pppppppppppppp !!! ! ! !! ! !! ppp !! !!! !! ! ! !! !!! ! ! !""%$# ""r%%$#!  ! !!! ppppppppppppppppp  !! !!!!!! !! ! ! ! ! ! !! ! ! ! ! ppp #$&#r! r#$%&#!   !!!! ppppppppppppppppp  !! ! ! !! !! ! !! !!pppp ""r%%$#! "#$%#r    ! !!! ppppppppppppppppp ! ! ! ! ! ! !ppp r#$%&#! "%%$#!     !!! ppppppppppppppppp rrr ! ! ! !! !! ! ! !! !! !!ppp "#$%#r "#$&#r     !! ppppppppppppppppppp   ! !!!!!! !!! ! !! !!! ! !!!pppp "%%$#! "r$%$#    ! !!! ppppppppppppppppppp  !! !! ! ! !! !! ! ! !! !! ! ppp "#$&#r r#$&#     !"!! pppppppppppppppppppp   ! !!!!!! !!! !! !!! !!!ppp "r$%$# #$#r!      !!!!! pppppppppppppppppppp  !! !!! !!! ! !!! !!! ! !!! !! !!!! ! ! ! ! ! ! ! ppppppp !!!!! ! ! !! ! ! !!!! ! ! r#$&# ""%%$#    ! !! pppppppppppppppppppp   ! !!!!! ! ! !!!!! ! ! ppppppp #$#r! r    ! !! pppppppppppppppppppp   ! ! !!!! !!!! pppp ""%%$# r! !!!    ! ! pppppppppppppppppppp ! !!""!!  ! !!!!!! !! !! ! !! !! !!ppppp ! !r " "    " ! pppppppppppppppppppp !""!!  ! !!!!!!! !!! !!! !!!!! !!! !!! ! ppppppp "r !! " " r"     !" pppppppppppppppppppp !!!""!  ! !!!!!!! !!ppppppp r  # r$   ! pppppppppppppppppppp !"""!  ! !   ppppppp "r " !! r!!    ! pppppppppppppppppppp !"""!  !ppppppppp !#!r !$!  !   ! pppppppppppppppppppp ! !"!  ! !  $    pppppppppppppppppppp !""!!  ! !!!!!!  ! "! !"   ! pppppppppppppppppppp !!"""!  !! ! pppp "$! !" "! #   " pppppppppppppppppppp ! !"!!  ! !!!!!!pppppp "! !# # r$r    pppppppppppppppppppp !!"!!  ! !pppppp !r "! r!"!     " pppppppppppppppppppp !!""!!  !pppp "#r $"! !! !  " pppppppppppppppppppp !""""!  ! !pppp "!r !#! !! !"    pppppppppppppppppppp !""!  !!!!!! pppppp !! !" $ r     ! pppppppppppppppppppp !""!  ! !! ! ppppp ! ! !! !#   !!! pppppppppppppppppppp 迿 !""""!  !!!!!!pppp !$r # " !  pppppppppppppppppppp !""! !pppp "! !! $ r$r  pppppppppppppppppppp ! !""! ! !pppppp r # r!   pppppppppppppppppppp 迿 !"!!  !pppp $r $ !! r!#!   pppppppppppppppppppp !""!!  ! !!!!!!pppp !#r !#! # $  pppppppppppppppppppp !!!"! ! !!!pppppp !r ! " $r  pppppppppppppppppppp """"! !!!!! pppp # $r ! !#   pppppppppppppppppppp 濿 !!""!! ! !!pppppp " $# $ qsq"  pppppppppppppppppppp ! !""! !! ! ! pppp ! ! # t  pppppppppppppppppppp !!"!! pppp $qsq " "! st#  pppppppppppppppppppp !!""!! pppppp "#t # " r$  pppppppppppppppppppp !""""! ppppp ts ! # wr$r pppppppppppppppppppp !""! pppp "r $r "! str" pppppppppppppppppppp !!"! pppp "#rw $" "! "! pppppppppppppppppppp !!"""! pppppp "rts !"! $ pppppppppppppppppppp !"!! pppp  ! #$r pppppppppppppppppppp !"""! pppp "$" "# pppppppppppppppppppp !"!! pppppp "#$# "#(%$" pppppppppppppppppppp !""!! pppp "" "#&&$# pppppppppppppppppppp !"""! pppp #(%$ !#&#r"! pppppppppppppppppppp !!"! pppppp !"#&&$#"! "r#&#! pppppppppppppppppppp !"""! pppppp "r#&#! "$%%$# pppppppppppppppppppp !""! pppp "$%%$# #r#%&$r# pppppppppppppppppppp pppp #r#%&$r# "#&#!! pppppppppppppppppppp pppppp "#&#!! "$%%$# pppppppppppppppppppp ppppp "$%%$# "#&#!! pppppppppppppppppppp pppp "r$&&$# "$%%$# pppppppppppppppppppp pppp "$%%$# "r$&&$# pppppppppppppppppppp pppppp "r$&&$# !#%'## pppppppppppppppppppp pppp !#'## "r$&&$# pppppppppppppppppppp pppp #r#%&$r! !#$'## pppppppppppppppppppp pppppp !#'## #r#%&$r! pppppppppppppppppppp ppppppp #r#%&$r! !"$%%$# pppppppppppppppppppp ppppppp !"$%%$# !""##$&$###! pppppppppppppppppppp ppppp !##%&%$#! !"#$$$#"! pppppppppppppppppppp ppppppppp "$%%$# !!"###""!! pppppppppppppppppppp pppp !"#$$$#"! ! !"!"#""!  pppppppppppppppppppp pppppp !!"###"!!! !!!""!!! pppppppppppppppppppp ppppp !!!"#""!   !!!!!  pppppppppppppppppppp pppppp !!!""!!   !!  pppppppppppppppppppp pppp  !!!!  p!pppppppppppppppppppp pppppppp  !!   p pppppppppppppppppppp pppppp!p!pppppppppppppppppppp pppppp p ppppppppppppppppppppp ppppppp!pppppppppppppppppppp pppppp ppppppppppppppppppppp pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp D #$$ D D  $ D $ +.?$ '6$ & &   5$ 6 , - 2#2 < . <# . 8P f I >f > NC S S# > C$C W U U z W z x ( |# | (   #               T YO      YO  T        G MB      MB  G F KB    '""  % K A  F&                  !"##$$#%" $&!'('"&()&% ""'!%#%)$$ $)"'(&")()%&!&*+,-*./.,-/0-1+-/.,.*./-,0/01-+*-.*-+100,+234526764578593675462439487895325625984:;<=:>?><=?@=A;>?=<>:;A@<@?@A=;:=>:=@<;BCDEBFGFDEGHEICFGEDFBHDCDHGHIECBEFBECIHJKLMNOPQORKJSTPSPUVMWUXSLYOZJNU[XSKROYUPOUJLNLKYNLORZ\\VWZMVX[YWQPWT\RJZSRTSXKZNMOQMZV\R\TY[UKXYQWMWPT]^_`]aba_`bc`d^ab`_a]c_^_cbcd`^]`a]`^dcefghijkljmfenoknkpqhrpsngtjueipvsnfmjtpkjpegigftigjmuwwqruhqsvtrlkrowmeunmonsfuihjlhuqwmwotvpfstlrhrkoxyz{|}~}yx~~{z}x|y}~}xz|zy|z}{~xy|{}{y{~=Vmaxrun1K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vmaxrun2K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vmaxrun3K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vmaxrun4K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vmaxrun5K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vmaxrun6K|m K|q K|qL|m>K|mK|uKyqmKymL|q)n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^K;rockrun1L~L~$K|L|CK|L| LyhL|wM|4yx\m`a:Yu[[`DO,\Lvc<)quuO|nAdM:a=uM?OG>aa >nRRc" 7>;4e4nA@T7X;D;{2sG.C>;2|HOKEaFlyT}QR|JXKDxK|{CsH.xT>yKKrockrun4L~L~$K|L|CK|L| LyhL|wM|4R|TF2qwu{lj'qyaKK>3l#|@CyW[FnTFt^fHK}[ ykh gqxFa]r =jo" aZj*Oc2 j*<@>G/[|Y/gvKuK{["ECMLx"XJm{}t'TrCyHc[[mhpCIz[rmwtk2kotoZokjnRlWufh |jwpHf5heCh4C6G'[Q%m}A|CR~~u #'#al-*R##f'|wyHr5/rC'2v;{@}<{6ay7kuFxCRvK{Ĭrockrun5L~L~$K|L|CK|L| LyhL|wM|4p|pj26z41nu;|72cmOf)y9}h>ut{\j|?quv{Mm~ rx a#6?l%{^|;Ly'|9 q#e(q>{NjCt>j?kGY]}uYa{ct{e|uoAtG>Xr;d>W4X>B4x/hN%;|L4HNy]ydyyӏӇՑ kt t:kek8rrYkXrBkfmӅOՎ*r~ӆKk{ӡ|Ӛգ-ktt9kfk}rrYkXrCkxfhӗOՠ*}r|әKkA4qڢstand1Ew Ey AwEwCBwQEwEtmEtZHw4uxHx-dYvc^hTaYhM[lJm}tC}z0^ap7}pth}y:xwr|qAx|qM`9kcCkQ:`4{ikM3ZQ~c^!WFWAzkHy@cVx&c[m7mA`gq `hjjq7>k[g|!k`gf|ga|O7Ah |GĖ7Ahڔ Ɩ|ՇMHYJ\Q`J`>m]E]ORaH^]A[eApWMYAvA0YV7ZFr7pAehq!fj|jqHya~|faVm}[|cR^^}Y[YoxcyYvA0yj7y^ӎˉHЕ-d~hkkymh~hRk^h|[n|ocd|vƊBɕ0d7eA6pݡstand2Ew Ey AwEwCBwQEwEtmEtZHw4uvHvd[vc`jVcYjO[nKm}wC}~0^ct7|trh||:xzqpAx|!pM`;kcEkR:`6zikO3ZR~c`WHWCykJx@cWw&c\p7pAcgo chjjoM7>k\Z|!k`gh|gc|O7Ag!|Mɕ7ĉAhݔ ɕ|ĉ؇MHZJ~]QaJa>h^E^ORcH]^A[gApWMZCvA/YV4ZFu7tAhgo!hj|joMH{c~}hcYm}\}eR`^}[[\oxe{[vA0ym7{`׎ΉHӕ-d~gkkzmhgRk^h|[n~ocd|vɉA͕0dƐ7eA6oݡstand3Ew Ey AwEwCBwQEwEtmEtZHw4tvHvdYvc^jTcYjO[nKm}wC}~0^at7|tqg||9x|poAx|}}oM`;kcEkR:`6yikO3ZR~c`WHWCxkJw@cWv&c\p7pAcgo chhhoM7>k[Z{"k`gf|gc{O7Ag!|Mɕ7ƈAgݔ!ɕ|ƈڇMHZJ]QaJa>h^C^ORcH]^AXgApYKZAuA0YT4\Fu7tAhgo!hh|hoH{c~}hcYm}\}fP`^}[[\oxe{[vB0ym7{`׎ЈHӔd~gkkymhgRk^h|[n~ocd|vˉAΕ0cƏ4eA6pܡstand4Ew Ey AwEwCBwQEwEtmEtZHw4uvHvd[vc`hVa[hO[lKm}uC}~0^cr7|trh||:xzqpAx|pM`;kcEkR:`6zikO3ZR~c`WHWCykJx@cWw&c\o7oAcgo chjjoM7>k\Z|!k`gh|gc|O7Ag!|Gȕ7ĉAgܔ!ȕ|ĉ؇MHZK~]RaKa>m^E]OPaH^^A[gCpWMZCvA2YV9ZHt9tAfho!hj|joMH{c~}hcYm}\}eP`^}[[\oxe{[vA0ym7{`ՎΉHҕ-d~gkkzmhgRk^h~[n~ocd~vɉA͕0dĐ7eA4qآstand5Ew Ey AwEwCBwQEwEtmEtZHw4uxHxdYvc^hTaYhM[lJmtCz0^cp7}pth}y:xyr|rAx|qG`9kcAkQ:`4{ikM3ZO~c^WFWAzkHy@cVx&c[k7kA`gq `hjjq7?k[Z|!k^gfgc|O7Ag!|Gė7Agؕ!Ɨ|ՈGHYK~\Q`J`>h]E]ORaH]]A[eApWMYCuA0WV7ZHp9pAchq!ejjqKy`~|f`Vl}[|cQ\^}W[YoxcyWvB0yj7y^ҏˊHΖ-e~hkkymh~hRk^h|[n|oce|vĊBȖ0d7e=Vaxstnd1I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd2I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd3I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd4I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd5I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd6I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd7I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd8I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd9I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd10I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd11I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxstnd12I|I~ HyKyDIyPIyIwhIysKy9n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain1E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain2E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain3E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain4E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain5E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V|axpain6E|| E| B|E||CB||QE|2EyoEy|ZE|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^HQ{pain1I~{I~ H|I|{?I|{I|IysI|{K|4vx|toztp|kopxk[hdK/lt{?|b5vH{yuRmx[{m5rReym+n`qtjYgYvmJltnt3Hbq"plulo?L{u\|uvy}ty}N?H͡aͮձ}գ𢞊?Hܦa{ܳv}t橛xרСMЮ oWr^v\xRbuToaPu^`tT[|[ElYtqQsРHέ/kaɥ3oW3Ibro}orMdP`]E{~zK/?y}MlnrtdqlPq`o]vEj{nzK/h3lC{Mpain2-~{-~ -|.|{C-|{-|.yh-|{w.|3&.):^p6Yy=`:`[BffEf96(03Ys8%871-23X6&,k'0IQ8ER?e-MT?Dj$:Ky6^?HrDM[FmI=f8a=,=GAFA7#zh#zX,*.';jF&8f3ak6f)N,%0&6շ73Ë%ƿk'ɳX"ⳝ׻%ܯ&î7˷ kXЪ %'>Ej=JBM;EKFDH:QP>TVAJ`FW?:Cs?Ci)ó-6Jt1÷,=HX8%:&=F=:uhwX"ݹ'⶞#=y:}>D7A=TAABfD5;~sA~p,&'7.%>]ɱ έ ˸#ky r%u,r9'o#uY'yA)rB*z."kq'jiҮ&ιpӵ%&p]E{Opain3-~{-~$,|.|{C-|{P-| -yh-|{r.|4&-';`p7Yz>`;a[DjBEh96'06Yg7%8F1,-3X3&,k&-LT8FVAf O\?Dm!=Mj7^BKrFT]HtI>k;e;,;G?F?7#yh#yXN*%-=kF%8e4`k7f'N&%)&1ӺFÎ-Ƌ k#ƵX߶п%ճ&Fùh Xɬ?Fy=KBOIO4DJ?RTDWJFMBHY.>EqEEb#& :J)%BJ`7%7=F;‡pkrYؽ"ݹ=y:>D9A=TAABBD5;~sA~p&&#7)%>]ó ȯMú#hy m%r,p9'm#tT'wK*pB*w."hq)hp ˱& ƽmͷ%'m]E{Zpain48~{8~*7|8|{?7|{8|08yi8|{w8|48?;KaiF^xOaIc[RhfVh9H(DD^rL*IEEA-DXF&>z;?WR8UVPh-ZWFSk$KOyFaMKwPQXVpIKjHeP*P'SE1S64h4X1?*B'LmD:KhDezFj=ND*F&LطE6Iċ;z=δX7鶝**,&1ȲEջ.ľz"Xد07í4MHyKMPQVM7RJLTYRW@SM_WY5KFrREi;Ȯ&:HMAƵ*OJ]M%M&R7.P1|y1|.8⻗>跞;PMSW9UPYUAVBW5MrUpB(?KE%R]Ӷ"ײ ӽ4ry3w7z=w88t4|Y:~@:wf=53rr8pi'ڳ&%վ0w*ڸ*8u]>Rzvpain5?~z?~$>|?|z??|z?|?yh?|zA|4W]MZ^ph\p}dp]pep^kp6gLd-Wpuk)eedd0`eI]x]`gWne^er0hWEgr,Z^Zr\Wt]WhrK]r\rq)qIqeOqdOwOOc)c(cze\cz\zx]z]Nv)vIveevẊexgᬠgZ)ZIZeIZḊIxI᪠IWج^קM]״]W]^~c^gWdcW^aYda_dW^ja7ZWu`RhdبIc׵-W^j׭)^WXo0qIqoMoMzOWONglMkkk~qt6qlRq@q^u4jwohqIq-gu)lKOMOOOSWoSOWU_U^Y9LuRhUIS-KY.R>Qzpain6?~z?~$>|?|z??|z?|?yh?|zA|4vx|toztp|kopxk[hdK/lt{?|b5vH{yuRmx[{m5rReym+n`qtjYgYvmJltnt3Hbq"plulo?L{u\|uvy}ty}N?H͡aͮձ}գ𢞊?Hܦa{ܳv}t橛xרСMЮ oWr^v\xRbuToaPu^`tT[|[ElYtqQsРHέ/kaɥ3oW3Ibro}orMdP`]E{~zK/?y}MlnrtdqlPq`o]vEj{nzK/h3l=Vxaxdeth1?~x?~|"?||A|x>?|x?|Ay|i?|xsA||.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vxaxdeth2?~x?~|"?||A|x>?|x?|Ay|i?|xsA||.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vxaxdeth3?~x?~|"?||A|x>?|x?|Ay|i?|xsA||.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=VTaxdeth4?~T?~Y"?|YA|T>?|T?|_AyYi?|TsA|Y.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=V#axdeth5>~#>~' >|'?|#C>|#>|-?y'i>|#r?|'3n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxdeth6>~>~$=|>|C=|>| >yh>|w?|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxdeth7>~>~$=|>|C=|>| >yh>|w?|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxdeth8>~>~$=|>|C=|>| >yh>|w?|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vaxdeth9>~>~$=|>|C=|>| >yh>|w?|4n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^8y|=deatha1;~|;~ :|=||C;||P;|;yh;||r=|5;:~<~A;}<~2<|::~:||;{j:|<|f;;{Z8};}:;}b8~8};~ ;~I8~:|;|8;|b8|x:|];~2;~I:~8~8|8~N:~;zZ;z;z;G;z; ;;=}Z;}X;}}=~I=}=~ ;~;~=y}Z;y};y~=|}I=y~=|~ ;|~;|}=~}Z;~};~~=}I=~~=~ ;~;};;~<~C<~2<~.<}8;|<};;~;}{;}~;{k;~ ;};}<}f;!;{Z;}=zZ=z=z=I=z= ==<|};{}={}><{0={.=z8A{0A{.Az8AzjAz@{@z{@z|AyhA{Az@z}Bz}fA|!Ay}Z@{A}@}B}AA2B.A8AjA;@@@|A~hAA@}B}fA!A~}Z@Dy|Ideatha3H~|H~,E|H||4H||H|1HymH||rI|4GF~H~AG}H~2H|:F~F||G{jF|H|fGG{ZD}G}:G}bD~D}G~ G~ID~F|G|8G|bD|xF|]G~2G~IF~D~D|D~NF~GzZGzGzGGGzG GGI}ZG}XG}}I~II}I~ G~G~Iy}ZGy}GyI|}IIyI| G|G|}I~}ZG~}G~I}II~I GG}GG~H~CH~2H~.H}8G|H};G~G}{G}~G{kG~ G}G}H}fG!G{ZG}IzZIzIzIIIzI IIH|~G{~I{~>H{0I{.Iz8HzjHzG{Gz{Hz|HyhH{HzGz~Iz~fH|!Hy~ZH{H~G~I~AH2I.I8HjH;GGH|H~hHHG~I~fH!H~~ZHGyuLdeatha4K~uK~z$I|zL|uCK|uPK| KyzhK|usL|z4JzI~zK~zAJ}}K~}2K|}:I~}I|}|J{}jI|zK|zfJ}J{zZG}zJ}z:J}ybG~zG}yJ~z J~yIG~yI|~J|~8J|}bH|~xI|}]J~~2J~}II~~H~~H|}H~}NI~}JzzZJzzJz{JzGJz{J{ J{JzL}yZJ}yXJ}|}L~yIL}|L~| J~|J~yLyuZJyuJywL|uILywL|w J|wJ|uL~uZJ~uJ~wLuIL~wLw JwJuKwJ~wK~wCK~~2K~~.K}~8K|~K}~;J~~J}~{J}~~K{~kK~~ K}J}wK}wfJ~!K{wZJ}~LzzZLzzLz{LzILz{L{ L{LzK|uK{uL{u>K{{0L{{.Lz{8Kz{jKz{K{{Kz{{Kz{|Ky{hK{{Kz|KzuLzufK|{!KyuZK{{KuKuLuAK{2L{.L{8K{jK{;K{K{K{|K~{hK{K|KuLufK{!K~uZK{GyeLodeatha5K~eK~k$I|kL|eCK|ePK|o KykhK|esL|k4JjI~jK~jAJ}mK~m2K|m:I~mI|m|J{mjI|jK|jfJmJ{jZG}jJ}j:J}ibG~jG}iJ~j J~iIG~iI|nJ|n8J|mbH|nxI|m]J~n2J~mII~nH~nH|mH~mNI~mKziZJziJzjKiGKzjKj JjJiL}iZJ}iXJ}l}L~iIL}lL~l J~lJ~iLyeZKyeKyfL|eILyfL|f K|fK|eL~eZK~eK~fLeIL~fLf KfKeKgJ~gK~gCK~n2K~n.K}n8K|nK}n;J~nJ}n{J}n~K{nkK~n K}nJ}gK}gfKn!K{gZJ}nLziZLziLzjLiILzjLj LjLiK|eK{eL{e>L{k0L{k.Lzk8KzkjLzkK{kKzk{Kzk|KykhK{kKzkKzeLzefK|k!KyeZK{kKeKeLeALk2Lk.Lk8KkjLk;KkKkKk|K~khKkKkKeLefKk!K~eZKkGyUL`deatha6K~UK~Z$I|ZL|UCK|UPK|`2KyZhK|UsL|Z4JZI~ZK~ZAJ}]K~]2K|]:I~]I|]|J{]jI|ZK|ZfJ]J{ZZG}ZJ}Z:J}YbG~ZG}YJ~Z J~YIG~YI|_J|^8J|]bH|_xI|]]J~^2J~]II~_H~_H|]H~]NI~]JzZZJzZJz[JZGJz[J[ J[JZL}ZZJ}ZXJ}]}L~ZIL}]L~] J~]J~ZLyVZJyVJyWL|VILyWL|W J|WJ|VL~VZJ~VJ~WLVIL~WLW JWJVKWJ~XK~XCK~_2K~^.K}^8K|_K}_;J~^J}^{J}_~K{^kK~_ K}_J}WK}XfJ^!K{XZJ}_LzZZLzZLz[LZILz[L[ L[LZK|VK{VL{V>K{\0L{[.Lz[8Kz\jKz\K{[Kz[{Kz\|Ky[hK{\Kz\KzVLzVfK|[!KyVZK{\KVKVLVAK\2L[.L[8K\jK\;K[K[K\|K~[hK\K\KVLVfK[!K~VZK\My-R7deatha7P~-P~2$O|2P|-?P|-P|6Py2zP|-R|24P2O~2Q~2AP}5Q~52Q|5:O~5O|5|P{5jO|2Q|2fP5P{2ZM}2P}2:P}1bM~2M}1P~2 P~1IM~1O|7P|68P|5bM|7xO|5]P~62P~5IO~7M~7M|5M~5NO~5Pz2ZPz2Pz3P2GPz3P3 P3P2Q}2ZP}2XP}5}Q~2IQ}5Q~5 P~5P~2Qy-ZPy-Py/Q|-IQy/Q|/ P|/P|-Q~-ZP~-P~/Q-IQ~/Q/ P/P-P/P~/Q~/CQ~72Q~6.Q}68P|7Q}7;P~6P}6{P}7~P{6kP~7 P}7P}/Q}/fP6!P{/ZP}7Rz2ZQz2Qz3R2IRz3R3 Q3Q2Q|.P{.Q{.>Q{40Q{3.Qz38Qz4jQz4P{3Pz3{Pz4|Qy3hQ{4Qz4Pz.Qz.fQ|3!Qy.ZP{4Q.P.Q.AQ42Q3.Q38Q4jQ4;P3P3P4|Q~3hQ4Q4P.Q.fQ3!Q~.ZP4GyL deatha8K~K~,I|K|CI|WK| 2KyiK|sL|4JI~K~AJ}K~2K|:I~I||J{jI|K|fJJ{ZG}J}:J}bG~G}J~ J~IG~I|J|8J|bG|xI|]J~2J~II~G~G|G~NI~JzZJzJzJGJzJ JJL}ZJ}XJ}}L~IL}L~ J~J~LyZJyJyL|ILyL| J|J|L~ZJ~J~LIL~L JJJJ~K~CK~2K~.K}8J|K};J~J}{J}~J{kJ~ J}J}K}fJ!J{ZJ}LzZLzLzLILzL LLK|J{L{>K{0L{.Lz8KzjKzJ{Jz{Kz|KyhK{KzJzLzfK|!KyZK{KJLAK2L.L8KjK;JJK|K~hKKJLfK!K~ZKGyLdeatha9K~K~,I|K|4K|K| KymK|uL|4JI~K~AJ}K~2K|:I~I||J{jI|K|fJJ{ZG}J}:J}bG~G}J~ J~IG~I|J|8J|bG|xI|]J~2J~II~G~G|G~NI~JzZJzJzJGJzJ JJL}ZJ}XJ}}L~IL}L~ J~J~LyZJyJyL|ILyL| J|J|L~ZJ~J~LIL~L JJJJ~K~CK~2K~.K}8J|K};J~J}{J}~J{kJ~ J}J}K}fJ!J{ZJ}LzZLzLzLILzL LLK|J{L{>K{0L{.Lz8KzjKzJ{Jz{Kz|KyhK{KzJzLzfK|!KyZK{KJLAK2L.L8KjK;JJK|K~hKKJLfK!K~ZKGy Ldeatha10K~ K~,I|K| 4K| K|2KyiK| uL|4JI~K~AJ}K~2K|:I~I||J{jI|K|fJJ{ZG}J}:J}bG~G}J~ J~IG~I|J|8J|bG|xI|]J~2J~II~G~G|G~NI~JzZJzJzJGJzJ JJK}ZJ}XJ}}K~IK}K~ J~J~Ky ZJy Jy K| IKy K| J| J| K~ ZJ~ J~ K IK~ K J J J J~ K~ CK~2K~.K}8J|K};J~J}{J}~J{kJ~ J}J} K} fJ!J{ ZJ}LzZKzKzLILzL KKK| J{ K{ >K{0K{.Kz8KzjKzJ{Jz{Jz|KyhK{KzJz Kz fK|!Ky ZJ{K J K AK2K.K8KjK;JJJ|K~hKKJ K fK!K~ ZJGyLdeatha11K~K~,I|K|4K|K|2KyhK|uL|4JI~K~AJ}K~2K|:I~I||J{jI|K|fJJ{ZG}J}:J} bG~G} J~ J~ IG~ I|J|8J|bH|xI|]J~2J~II~H~H|H~NI~KzZJzJzKGKzK JJL} ZJ} XJ}}L~ IL}L~ J~J~ Ly ZKy Ky L| ILy L| K| K| L~ ZK~ K~ L IL~ L K K K J~ K~ CK~2K~.K}8K|K};J~J}{J}~K{kK~ K}J} K} fK!K{ ZJ}LzZLzLzLILzL LLK| K{ L{ >L{0L{.Lz8KzjLzK{Kz{Kz|KyhK{KzKz Lz fK|!Ky ZK{K K L AL2L.L8KjL;KKK|K~hKKK L fK!K~ ZKIyuOdeathb1L~uL~{ K|{M|uBL|uPL|My{hL|usO|{3L{K~{M~{AL}~M~~2M|~:K~~K|~|L{~jK|{M|{fL~L{{ZI}{L}{:L}zbI~{I}zL~{ L~zII~zK|L|8L|~bJ|xK|~]L~2L~~IK~J~J|~J~~NK~~Mz{ZLz{Lz|M{GMz|M| L|L{N}zZL}zXL}}}N~zIN}}N~} L~}L~zNyvZMyvMyxN|vINyxN|x M|xM|vN~vZM~vM~xNvIN~xNx MxMvMxL~xM~xCM~2M~.M}8M|M};L~L}{L}~M{kM~ M}L}xM}xfM!M{xZL}Nz{ZNz{Nz|N{INz|N| N|N{M|vM{vN{v>N{|0N{|.Nz|8Mz|jNz|M{|Mz|{Mz||My|hM{|Mz}MzvNzvfM||!MyvZM{|MvMvNvAN|2N|.N|8M|jN|;M|M|M||M~|hM|M}MvNvfM|!M~vZM|3yt:deathb27~tM7~z$3|z8|tB7|tP7|7yzh7|ts:|z46{5~{7~{A6}~7~~27|~:5~~5|~|6{~j5|{7|{f6~6{{Z3}{6}{:6}zb3~{3}z6~{ 6~zI3~z5|6|86|~b3|x5|~]6~26~~I5~3~3|~3~~N5~~6zzZ6zz6z{6zG6z{6{ 6{6z8}zZ6}zX6}}}8~zI8}}8~} 6~}6~z8yvZ6yv6yx8|vI8yx8|x 6|x6|v8~vZ6~v6~x8vI8~x8x 6x6v6x6~x7~xC7~27~.7}86|7};6~6}{6}~6{k6~ 6}6}x7}xf6!6{xZ6}8zzZ8zz8z{8zI8z{8{ 8{8z7|v6{v8{v>7{|07{|.7z|87z|j7z|6{|6z|{6z||7y|h7{|7z|6zv8zvf7||!7yvZ6{|7v6v8vA7|28|.7|87|j7|;6|6|6||7~|h7|7|6v8vf7|!7~vZ6|#yq)~deathb3'~q'~x$%|x'|qC%|qW'|~'yxh'|qs)|x4&w%~w'~wA&}z'~z2'|z:%~z%|z|&{zj%|w'|wf&z&{wZ#}w&}w:&}vb#~w#}v&~w &~vI#~v%||&|{8&|zb#||x%|z]&~{2&~zI%~|#~|#|z#~zN%~z&zwZ&zw&zx&wG&zx&x &x&w'}wZ&}wX&}z}'~wI'}z'~z &~z&~w'yrZ&yr&yt'|rI'yt'|t &|t&|r'~rZ&~r&~t'rI'~t't &t&r&t&~t'~tC'~|2'~{.'}{8&||'}|;&~{&}{{&}|~&{{k&~| &}|&}t'}tf&{!&{tZ&}|(zwZ'zw'zx(wI(zx(x 'x'w'|s&{s'{s>'{x0'{x.'zx8'zxj'zx&{x&zx{&zx|'yxh'{x'zy&zs'zsf'|x!'ysZ&{x's&s'sA'x2'x.'x8'xj'x;&x&x&x|'~xh'x'y&s'sf'x!'~sZ&x!yR'_deathb4%~R&%~X$"|X%|RC"|RR%|_ %yXh%|Rs'|X4$X#~X%~XA$}[%~[2%|[:#~[#|[|${[j#|X%|Xf$[${XZ!}X$}X:$}Wb!~X!}W$~X $~WI!~W#|]$|\8$|[b!|]x#|[]$~\2$~[I#~]!~]!|[!~[N#~[$zXZ$zX$zY$XG$zY$Y $Y$X%}XZ$}XX$}[}%~XI%}[%~[ $~[$~X%yTZ$yT$yU%|TI%yU%|U $|U$|T%~TZ$~T$~U%TI%~U%U $U$T$U$~V%~VC%~]2%~\.%}\8$|]%}];$~\$}\{$}]~${\k$~] $}]$}U%}Vf$\!${VZ$}]&zXZ%zX%zY&XI&zY&Y %Y%X%|T${T%{T>%{Z0%{Y.%zY8%zZj%zZ${Y$zY{$zZ|%yYh%{Z%zZ$zT%zTf%|Y!%yTZ${Z%T$T%TA%Z2%Y.%Y8%Zj%Z;$Y$Y$Z|%~Yh%Z%Z$T%Tf%Y!%~TZ$Z"y('5deathb5%~(%~/$"|/'|(C%|(P%|5 %y/h%|(s'|/5%-#~.&~.A%}1&~12&|1:$~1$|1|%{1j#|.&|.f%1%{.Z"}.%}.:%}-b"~."}-%~. %~-I"~-#|2%|28%|0b"|2x#|0]%~22%~0I#~2"~2"|0"~0N#~0%z-Z%z-%z.%-G%z.%. %.%-&}-Z%}-X%}0}&~-I&}0&~0 %~0%~-&y)Z%y)%y*&|)I&y*&|* %|*%|)&~)Z%~)%~*&)I&~*&* %*%)%+$~+&~+C%~22&~2.&}28%|2%}2;$~1$}1{%}2~%{1k%~2 %}2$}+&}+f%2!%{+Z%}2&z-Z&z-&z.&-I&z.&. &.&-%|)%{)&{)>&{/0&{..&z.8%z/j&z/%{.%z.{%z/|%y.h%{/%z/%z)&z)f%|.!%y)Z%{/%)%)&)A&/2&..&.8%/j&/;%.%.%/|%~.h%/%/%)&)f%.!%~)Z%/#y)deathb6'~'~$%|'|C%|W'|'yh'|s)|4&%~'~A'}'~2'|:%~%||'{j%|'|f'&{Z#}&}:&}b#~#}&~ &~I#~%|'|8'|b$|x%|]'~2'~I%~$~$|$~N%~'zZ'z'z'G'z' ''(}Z'}X'}}(~I(}(~ '~'~(yZ'y'y(|I(y(| '|'|(~Z'~'~(I(~( '''&~'~C'~2'~.'}8'|'};&~&}{&}~'{k'~ '}&}'}f'!'{Z&}(zZ(z(z(I(z( (('|'{({>({0({.(z8'zj(z'{'z{'z|'yh'{'z'z(zf'|!'yZ'{''(A(2(.(8'j(;'''|'~h'''(f'!'~Z'#y)deathb7'~'~$%|'|C%|W'|'yh'|s)|4&%~'~A'}'~2'|:%~%||'{j%|'|f'&{Z#}&}:&}b#~#}&~ &~I#~%|'|8'|b$|x%|]'~2'~I%~$~$|$~N%~'zZ'z'z'G'z' ''(}Z'}X'}}(~I(}(~ '~'~(yZ'y'y(|I(y(| '|'|(~Z'~'~(I(~( '''&~'~C'~2'~.'}8'|'};&~&}{&}~'{k'~ '}&}'}f'!'{Z&}(zZ(z(z(I(z( (('|'{({>({0({.(z8'zj(z'{'z{'z|'yh'{'z'z(zf'|!'yZ'{''(A(2(.(8'j(;'''|'~h'''(f'!'~Z'#y)deathb8'~'~$%|'|C%|W'|'yh'|s)|4&%~'~A'}'~2'|:%~%||'{j%|'|f'&{Z#}&}:&}b#~#}&~ &~I#~%|'|8'|b$|x%|]'~2'~I%~$~$|$~N%~'zZ'z'z'G'z' ''(}Z'}X'}}(~I(}(~ '~'~(yZ'y'y(|I(y(| '|'|(~Z'~'~(I(~( '''&~'~C'~2'~.'}8'|'};&~&}{&}~'{k'~ '}&}'}f'!'{Z&}(zZ(z(z(I(z( (('|'{({>({0({.(z8'zj(z'{'z{'z|'yh'{'z'z(zf'|!'yZ'{''(A(2(.(8'j(;'''|'~h'''(f'!'~Z'#y)deathb9'~'~$%|'|C%|W'|'yh'|s)|4&%~'~A'}'~2'|:%~%||'{j%|'|f'&{Z#}&}:&}b#~#}&~ &~I#~%|'|8'|b$|x%|]'~2'~I%~$~$|$~N%~'zZ'z'z'G'z' ''(}Z'}X'}}(~I(}(~ '~'~(yZ'y'y(|I(y(| '|'|(~Z'~'~(I(~( '''&~'~C'~2'~.'}8'|'};&~&}{&}~'{k'~ '}&}'}f'!'{Z&}(zZ(z(z(I(z( (('|'{({>({0({.(z8'zj(z'{'z{'z|'yh'{'z'z(zf'|!'yZ'{''(A(2(.(8'j(;'''|'~h'''(f'!'~Z'MuvR}deathc1P|vP||$Oy|PyvCOyvPyPw|sPyvwRy|4P{|Oz|Qz|APyQz2Qx:OzOx|PwjOx|Qx|fP{Pw|ZMy|Py|:Py{bMz|My{Pz| Pz{IMz{OxPx8PxbMxxOx]Pz2PzIOzMzMxMzNOzPv|ZPv|Pv}P||GPv}P|} P|}P||Ry|ZPy|XPy}Rz|IRyRz PzPz|RuxZPuxPuyRxxIRuyRxy PxyPxxRzxZPzxPzyR}xIRzyR}y P}yP}xP{zPzzQzzCQz2Qz.Qy8PxQy;PzPy{Py~PwkPz PyPyzQyzfP{!PwzZPyRv|ZRv|Rv}R||IRv}R|} R|}R||QxxPwxRwx>Qw~0Qw}.Qv}8Qv~jQv~Pw}Pv}{Pv~|Qu}hQw~Qv~PvxRvxfQx}!QuxZPw~Q}xP|xR|xAQ|~2R|}.Q{}8Q{~jQ{~;P|}P{}P{~|Qz}hQ}~Q|~P{xR{xfQ}}!QzxZP|~MuR}deathc2P|P|$OyPyCOyPyPwhPywRy4P{OzQzAPyQz2Qx:OzOx|PwjOxQxfP{PwZMyPy:PybMzMyPz PzIMzOxPx8PxbMxxOx]Pz2PzIOzMzMxMzNOzPvZPvPvP|GPvP| P|P|QyZPyXPy}QzIQyQz PzPzQuZPuPuQxIQuQx PxPxQzZPzPzQ}IQzQ} P}P}P{PzQzCQz2Qz.Qy8PxQy;PzPy{Py~PwkPz PyPyQyfP{!PwZPyRvZQvQvR|IRvR| Q|Q|QxPwQw>Qw0Qw.Qv8QvjQvPwPv{Pv|QuhQwQvPvQvfQx!QuZPwQ}P|Q|AQ|2Q|.Q{8Q{jQ{;P|P{P{|QzhQ}Q|P{Q{fQ}!QzZP|Wu\}deathc3Z|Z| Yy\yCZyZyZwhZys\y9Z{Yz[zAZy[z2[x:YzYx|ZwjYx[xfZ{ZwZWyZy:ZybWzWyZz ZzIWzYxZx8ZxbWxxYx]Zz2ZzIYzWzWxWzNYzZvZZvZvZ|GZvZ| Z|Z|\yZZyXZy}\zI\y\z ZzZz\uZZuZu\xI\u\x ZxZx\zZZzZz\}I\z\} Z}Z}Z{Zz[zC[z2[z.[y8Zx[y;ZzZy{Zy~ZwkZz ZyZy[yfZ{!ZwZZy\vZ\v\v\|I\v\| \|\|[xZw\w>[w0[w.[v8[vj[vZwZv{Zv|[uh[w[vZv\vf[x![uZZw[}Z|\|A[|2\|.[{8[{j[{;Z|Z{Z{|[zh[}[|Z{\{f[}![zZZ|^uc}deathc4`|`| ^ycyB`yP`y`wh`yscy9a{_zbzAaybz2bx:`z`x|awj_xbxfa{awZ^yay:ayb^z^yaz azI^z_xax8axb^xx_x]az2azI_z^z^x^zN_zavZavava|Gava| a|a|byZayXay}bzIbybz azazbuZauaubxIbubx axaxbzZazazb}Ibzb} a}a}a{`zbzCaz2bz.by8axay;`z`y{ay~awkaz ay`ybyfa{!awZaybvZbvbvb|Ibvb| b|b|axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|^utc}deathc5`|t`|z ^yzcytB`ytP`y`wzh`ytscyz9a{y_zybzyAay|bz|2bx|:`z|`x||aw|j_xybxyfa{|awyZ^yyayy:ayxb^zy^yxazy azxI^zx_x}ax}8ax|b^x}x_x|]az}2az|I_z}^z}^x|^z|N_z|avyZavyavza|yGavza|z a|za|ybyxZayxXay{}bzxIby{bz{ az{azxbutZautauvbxtIbuvbxv axvaxtbztZaztazvb}tIbzvb}v a}va}ta{v`zvbzvCaz}2bz}.by}8ax}ay};`z}`y}{ay}~aw}kaz} ay~`yvbyvfa{}!awvZay}bvyZbvybvzb|yIbvzb|z b|zb|yaxtawtbwt>bwz0bwz.bvz8avzjbvzawzavz{avz|auzhawzav{avtbvtfaxz!autZawza}ta|tb|tAb|z2b|z.b{z8a{zjb{z;a|za{za{z|azzha}za|{a{tb{tfa}z!aztZa|z]u_c}ldeathc6`|_`|e ^yecy_B`y_P`yl`weh`y_scye9`{d_zdazdA`ygazg2axg:_zg_xg|`wgj_xdaxdf`{g`wdZ]yd`yd:`ycb]zd]yc`zd `zcI]zc_xh`xh8`xgb^xhx_xg]`zh2`zgI_zh^zh^xg^zgN_zgavcZ`vc`vda|cGavda|d `|d`|cbycZ`ycX`yf}bzcIbyfbzf `zf`zcbu_Zau_auabx_Ibuabxa axaax_bz_Zaz_azab}_Ibzab}a a}aa}_a{a`zaazaCazh2azh.ayh8axhayh;`zh`yh{`yh~awhkazh ayh`yaayafa{h!awaZ`yhbvcZbvcbvdb|cIbvdb|d b|db|cax_aw_bw_>bwe0bwe.bve8avejbveaweave{ave|auehaweaveav_bv_faxe!au_Zawea}_a|_b|_Ab|e2b|e.b{e8a{ejb{e;a|ea{ea{e|azeha}ea|ea{_b{_fa}e!az_Za|e^uKc}Ydeathc7`|K`|S ^yScyKB`yKP`yY`wSh`yKscyS9a{P`zPbzPAaySbzS2bxS:`zS`xS|awSj`xPbxPfa{SawPZ^yPayP:ayOb^zP^yOazP azOI^zO`xUaxT8axSb^xUx`xS]azT2azSI`zU^zU^xS^zSN`zSavPZavPavQa|PGavQa|Q a|Qa|PbyPZayPXayS}bzPIbySbzS azSazPbuLZauLauMbxLIbuMbxM axMaxLbzLZazLazMb}LIbzMb}M a}Ma}La{NazNbzNCbzU2bzT.byT8axUbyU;azTayT{ayU~awTkazU ayUayNbyNfa{T!awNZayUcvPZbvPbvQc|PIcvQc|Q b|Qb|PbxLawLbwL>bwR0bwQ.bvQ8bvRjbvRawQavQ{avR|buQhbwRbvRavLbvLfbxQ!buLZawRb}La|Lb|LAb|R2b|Q.b{Q8b{Rjb{R;a|Qa{Qa{R|bzQhb}Rb|Ra{Lb{Lfb}Q!bzLZa|R]u6c}Ddeathc8`|6`|= ^y=cy6B`y6P`yD`w=h`y6scy=9`{<_zaw>0bw=.bv=8av>jav>`w=`v={av>|au=haw>av>`v8bv8fax=!au8Zaw>a}8`|8b|8Aa|>2b|=.b{=8a{>ja{>;`|=`{=a{>|az=ha}>a|>`{8b{8fa}=!az8Za|>^u#c}0deathc9`|#`|) ^y)cy#B`y#P`y0`w)h`y#scy)9a{(_z(bz(Aay+bz+2bx+:`z+`x+|aw+j_x(bx(fa{+aw(Z^y(ay(:ay'b^z(^y'az( az'I^z'_x,ax,8ax+b^x,x_x+]az,2az+I_z,^z,^x+^z+N_z+av(Zav(av)a|(Gav)a|) a|)a|(by'Zay'Xay*}bz'Iby*bz* az*az'bu#Zau#au%bx#Ibu%bx% ax%ax#bz#Zaz#az%b}#Ibz%b}% a}%a}#a{%`z%bz%Caz,2bz,.by,8ax,ay,;`z,`y,{ay,~aw,kaz, ay-`y%by%fa{,!aw%Zay,bv(Zbv(bv)b|(Ibv)b|) b|)b|(ax#aw#bw#>bw)0bw).bv)8av)jbv)aw)av){av)|au)haw)av*av#bv#fax)!au#Zaw)a}#a|#b|#Ab|)2b|).b{)8a{)jb{);a|)a{)a{)|az)ha})a|*a{#b{#fa})!az#Za|)^uc}'deathc10`|`| ^y cyB`yP`y'`w h`yscy 9a{_zbzAay!bz!2bx!:`z!`x!|aw!j_xbxfa{!awZ^yay:ayb^z^yaz azI^z_x#ax"8ax!b^x#x_x!]az"2az!I_z#^z#^x!^z!N_z!avZavava|Gava| a|a|byZayXay!}bzIby!bz! az!azbuZauaubxIbubx axaxbzZazazb}Ibzb} a}a}a{`zbzCaz#2bz".by"8ax#ay#;`z"`y"{ay#~aw"kaz# ay#`ybyfa{"!awZay#bvZbvbvb|Ibvb| b|b|axawbw>bw 0bw.bv8av jbv awav{av |auhaw av avbvfax!auZaw a}a|b|Ab| 2b|.b{8a{ jb{ ;a|a{a{ |azha} a| a{b{fa}!azZa| ^uc}deathc11`|`| ^ycyB`yP`y`wh`yscy9a{_zbzAaybz2bx:`z`x|awj_xbxfa{awZ^yay:ayb^z^yaz azI^z_xax8axb^xx_x]az2azI_z^z^x^zN_zavZavava|Gava| a|a|byZayXay}bzIbybz azazbuZauaubxIbubx axaxbzZazazb}Ibzb} a}a}a{`zbzCaz2bz.by8axay;`z`y{ay~awkaz ay`ybyfa{!awZaybvZbvbvb|Ibvb| b|b|axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|]uc}deathc12`|`| ^y cyB`yP`y`w h`yscy 9`{ _z az A`yaz2ax:_z_x|`wj_x ax f`{`w Z]y `y :`y b]z ]y `z `z I]z _x`x8`xb^xx_x]`z2`zI_z^z^x^zN_zav Z`v `va| Gava| `|`| by Z`y X`y}bz Ibybz `z`z buZauau bxIbu bx ax axbzZazaz b}Ibz b} a} a}a{ `z az Caz2az.ay8axay;`z`y{`y~awkaz ay`y ay fa{!aw Z`ybv Zbv bvb| Ibvb| b|b| axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|]uc}deathc13`|`| ^y cyB`yP`y`w h`yscy 9`{ _z az A`yaz2ax:_z_x|`wj_x ax f`{`w Z]y `y :`y b]z ]y `z `z I]z _x`x8`xb^xx_x]`z2`zI_z^z^x^zN_zav Z`v `va| Gava| `|`| by Z`y X`y}bz Ibybz `z`z buZauau bxIbu bx ax axbzZazaz b}Ibz b} a} a}a{ `z az Caz2az.ay8axay;`z`y{`y~awkaz ay`y ay fa{!aw Z`ybv Zbv bvb| Ibvb| b|b| axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|]uc}deathc14`|`| ^y cyB`yP`y`w h`yscy 9`{ _z az A`yaz2ax:_z_x|`wj_x ax f`{`w Z]y `y :`y b]z ]y `z `z I]z _x`x8`xb^xx_x]`z2`zI_z^z^x^zN_zav Z`v `va| Gava| `|`| by Z`y X`y}bz Ibybz `z`z buZauau bxIbu bx ax axbzZazaz b}Ibz b} a} a}a{ `z az Caz2az.ay8axay;`z`y{`y~awkaz ay`y ay fa{!aw Z`ybv Zbv bvb| Ibvb| b|b| axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|]uc}deathc15`|`| ^y cyB`yP`y`w h`yscy 9`{ _z az A`yaz2ax:_z_x|`wj_x ax f`{`w Z]y `y :`y b]z ]y `z `z I]z _x`x8`xb^xx_x]`z2`zI_z^z^x^zN_zav Z`v `va| Gava| `|`| by Z`y X`y}bz Ibybz `z`z buZauau bxIbu bx ax axbzZazaz b}Ibz b} a} a}a{ `z az Caz2az.ay8axay;`z`y{`y~awkaz ay`y ay fa{!aw Z`ybv Zbv bvb| Ibvb| b|b| axawbw>bw0bw.bv8avjbvawav{av|auhawavavbvfax!auZawa}a|b|Ab|2b|.b{8a{jb{;a|a{a{|azha}a|a{b{fa}!azZa|8yc=odeathd1;~c;i :~i=~cC;~cP;~o;|ih;|c=~i9;h:~h<~hA;}k<~k2<|k::~k:|k|;{kj:|h<|hf;k;{hZ8}h;}h:;}gb8~h8}g;~h ;~gI8~g:|m;|l8;|kb8|mx:|k];~l2;~kI:~m8~m8|k8~kN:~k;zhZ;zh;zi;hG;zi;i ;i;h=}hZ;}hX;}k}=~hI=}k=~k ;~k;~h=ydZ;yd;ye=|dI=ye=|e ;|e;|d=~dZ;~d;~e=dI=~e=e ;e;d;f;~f<~fC<~m2<~l.<}l8;|m<}m;;~l;}l{;}m~;{lk;~m ;}m;}f<}ff;l!;{fZ;}m=zhZ=zh=zi=hI=zi=i =i=h<|d;{d={d><{j0={i.=zi8<{j0={i.=zi8<{j0={i.=zi8<{j0={i.=zi8~Z?~TF?~T?~`?|Zh?|TuA~Z4?Y>~Z@~ZA?}]@~]2@|]:>~]>|]|?{]j>|Z@|Zf?]?{ZZ<}Z?}Z:?}Yb<~Z<}Y?~Z ?~YI<~Y>|^?|^8?|]b<|^x>|]]?~^2?~]I>~^<~^<|]<~]N>~]?zYZ?zY?zZ?YG?zZ?Z ?Z?YA}YZ?}YX?}\}A~YIA}\A~\ ?~\?~YAyUZ?yU?yVA|UIAyVA|V ?|V?|UA~UZ?~U?~VAUIA~VAV ?V?U?W?~W@~WC@~^2@~^.@}^8?|^@}^;?~^?}^{?}^~?{^k?~^ ?}^?}W@}Wf?^!?{WZ?}^AzYZAzYAzZAYIAzZAZ AZAY@|U?{UA{U>@{[0A{[.Az[8@z[j@z[?{[?z[{?z[|@y[h@{[@z[?zUAzUf@|[!@yUZ?{[@U?UAUA@[2A[.A[8@[j@[;?[?[?[|@~[h@[@[?UAUf@[!@~UZ?[~F?~@F?~@?~L?|Fh?|@uA~F4?F>~F@~FA?}I@~I2@|I:>~I>|I|?{Ij>|F@|Ff?I?{FZ<}F?}F:?}Eb<~F<}E?~F ?~EI<~E>|K?|J8?|Ib=|Kx>|I]?~J2?~II>~K=~K=|I=~IN>~I@zFZ?zF?zG@FG@zG@G ?G?FA}FZ?}FX?}I}A~FIA}IA~I ?~I?~FAyAZ@yA@yCA|AIAyCA|C @|C@|AA~AZ@~A@~CAAIA~CAC @C@A@C?~C@~CC@~K2@~J.@}J8@|K@}K;?~J?}J{?}K~@{Jk@~K @}K?}C@}Cf@J!@{CZ?}KAzFZAzFAzGAFIAzGAG AGAF@|B@{BA{B>A{H0A{G.AzG8@zHjAzH@{G@zG{@zH|@yGh@{H@zH@zBAzBf@|G!@yBZ@{H@B@BABAAH2AG.AG8@HjAH;@G@G@H|@~Gh@H@H@BABf@G!@~BZ@H;y#A/deathd7?~#?)>~(?~#C>~#?~/?|(h?|#A~(4>(=~(?~(A>}+?~+2?|+:=~+=|+|>{+j=|(?|(f>+>{(Z;}(>}(:>}'b;~(;}'>~( >~'I;~'=|->|,8>|+b<|-x=|+]>~,2>~+I=~-<~-<|+<~+N=~+?z(Z>z(>z)?(G?z)?) >)>(@}(Z>}(X>}+}@~(I@}+@~+ >~+>~(@y$Z?y$?y%@|$I@y%@|% ?|%?|$@~$Z?~$?~%@$I@~%@% ?%?$?&>~&?~&C?~-2?~,.?},8?|-?}-;>~,>},{>}-~?{,k?~- ?}->}&?}&f?,!?{&Z>}-@z(Z@z(@z)@(I@z)@) @)@(?|$?{$@{$>@{*0@{).@z)8?z*j@z*?{)?z){?z*|?y)h?{*?z*?z$@z$f?|)!?y$Z?{*?$?$@$A@*2@).@)8?*j@*;?)?)?*|?~)h?*?*?$@$f?)!?~$Z?*~ ?~C>~?~?| h?|A~ 4? >~ @~ A?} @~ 2@| :>~ >| |?{ j>| @| f? ?{ Z<} ?} :?} b<~ <} ?~ ?~ I<~ >|?|8?| b<|x>| ]?~2?~ I>~<~<| <~ N>~ ?z Z?z ?z ? G?z ? ? ? A} Z?} X?} }A~ IA} A~ ?~ ?~ AyZ?y?yA|IAyA| ?|?|A~Z?~?~AIA~A ????~@~C@~2@~.@}8?|@};?~ ?} {?}~?{ k?~ ?}?}@}f?!?{Z?}Az ZAz Az A IAz A A A @|?{A{>@{ 0@{ .@z 8@z j@z ?{ ?z {?z |@y h@{ @z ?zAzf@| !@yZ?{ @?AA@ 2A .@ 8@ j@ ;? ? ? |@~ h@ @ ?Af@ !@~Z? ~ ?~C>~?~?| m?|A~ 4?>~@~A?} @~ 2@| :>~ >| |?{ j>|@|f? ?{Z<}?}:?}b<~<}?~ ?~I<~>| ?| 8?| b<| x>| ]?~ 2?~ I>~ <~ <| <~ N>~ ?zZ?z?z ?G?z ? ? ?@}Z?}X?} }@~I@} @~ ?~ ?~@yZ?y?y@|I@y@| ?|?|@~Z?~?~@I@~@ ???>~@~C?~ 2@~ .@} 8?| ?} ;>~ >} {?} ~?{ k?~ ?} >}@}f? !?{Z?} @zZ@z@z @I@z @ @ @?|?{@{>@{ 0@{ .@z 8?z j@z ?{ ?z {?z |?y h?{ ?z ?z@zf?| !?yZ?{ ??@A@ 2@ .@ 8? j@ ;? ? ? |?~ h? ? ?@f? !?~Z? Jv|O~deathe1M||M~$LyMy|CLy|MyMwzMy|wOy7M|K{N{AMzN{2Ny:L{Ly|MxjKyNyfM|MxZJyMy:MybJ{JyM{ M{IJ{KyMy8MybJyxKy]M{2M{IK{J{JyJ{NK{MwZMwMwM}GMwM} M}M}NyZMyXMy}N{INyN{ M{M{NvZMvMvNyINvNy MyMyN{ZM{M{N~IN{N~ M~M~M{LzNzCMz2Nz.Ny8MyMy;LzLy{My~MxkM{ MzLyNyfM{!MxZMzNwZNwNwN}INwN} N}N}MxMxNx>Nx0Nx.Nw8MvjNwMxMw{Mw|MvhMxMwMwNwfMx!MvZMxM~M}N}AN}2N}.N|8M{jN|;M}M|M||M{hM}M|M|N|fM~!M{ZM}cvlh~zdeathe2e|le~r'dyreylCdyleyz}ewrseylwhyr7e|rd{sf{sAfzvf{v2fyv:d{vdyv|fxvjdysfysff|vexsZcyseys:eyrbc{scyre{s e{rIc{rdywfyv8fyubcywxdyu]f{v2f{uId{wc{wcyuc{uNd{ufwrZfwrfwsf}rGfwsf}s f}sf}rgyrZfyrXfyu}g{rIgyug{u f{uf{rgvnZfvnfvogynIgvogyo fyofyng{nZf{nf{og~nIg{og~o f~of~nf{pezpfzpCfzw2fzv.fyv8fywfyw;ezveyv{eyw~fxvkf{w fzweypfypff{v!fxpZezwgwrZgwrgwsg}rIgwsg}s g}sg}rfxnfxngxn>gxt0gxs.gws8fvtjgwtfxsfws{fwt|fvshfxtfwtfwngwnffxs!fvnZfxtf~nf}ng}nAg}t2g}s.g|s8f{tjg|t;f}sf|sf|t|f{shf}tf|tf|ng|nff~s!f{nZf}tbvZh~ideathe3e|Ze~b$dybeyZCdyZeyiewbzeyZwhyb7e|ad{af{aAezdf{d2fyd:d{ddyd|exdjdyafyafe|dexaZbyaeya:ey`bb{aby`e{a e{`Ib{`dyeeye8eydbbyexdyd]e{e2e{dId{eb{ebydb{dNd{dewaZewaewbe}aGewbe}b e}be}afy`Zey`Xeyd}f{`Ifydf{d e{de{`fv\Zev\ev^fy\Ifv^fy^ ey^ey\f{\Ze{\e{^f~\If{^f~^ e~^e~\e{^dz^fz^Ceze2fze.fye8eyefye;dzedye{eye~exeke{e ezfdy^fy^fe{e!ex^ZezegwaZfwafwbg}aIgwbg}b f}bf}afx\ex\fx\>fxb0fxb.fwb8fvbjfwbexbewb{ewb|fvbhfxbfwcew\fw\ffxb!fv\Zexbf~\e}\f}\Af}b2f}b.f|b8f{bjf|b;e}be|be|b|f{bhf}bf|ce|\f|\ff~b!f{\Ze}bbvLh~Zdeathe4e~Le~T d|Te|LCd|Le|ZeyTze|Lwh|T4e|Rd{Rf{RAezUf{U2fyU:d{UdyU|exUjdyRfyRfe|UexRZbyReyR:eyQbb{RbyQe{R e{QIb{QdyWeyV8eyUbcyWxdyU]e{V2e{UId{Wc{WcyUc{UNd{UewRZewRewSe}RGewSe}S e}Se}RgyRZeyRXeyU}g{RIgyUg{U e{Ue{RgvNZevNevOgyNIgvOgyO eyOeyNg{NZe{Ne{Og~NIg{Og~O e~Oe~Nf{OezPfzPCfzW2fzV.fyV8fyWfyW;ezVeyV{eyW~fxVkf{W fzWeyOfyPfe{V!fxPZezWgwRZgwRgwSg}RIgwSg}S g}Sg}RfxNfxNgxN>fxT0gxS.gwS8fvTjfwTfxSfwS{fwT|fvShfxTfwTfwNgwNffxS!fvNZfxTf~Nf}Ng}NAf}T2g}S.g|S8f{Tjf|T;f}Sf|Sf|T|f{Shf}Tf|Tf|Ng|Nff~S!f{NZf}TcvBh~Rdeathe5e~Be~I d|Ie|BCd|Be|ReyIse|Bwh|I4e|Jd{Jf{JAfzMf{M2fyM:d{MdyM|fxMjdyJfyJff|MexJZcyJeyJ:eyIbc{JcyIe{J e{IIc{IdyOfyN8fyMbcyOxdyM]f{N2f{MId{Oc{OcyMc{MNd{MfwJZfwJfwKf}JGfwKf}K f}Kf}JgyJZfyJXfyM}g{JIgyMg{M f{Mf{JgvFZfvFfvGgyFIgvGgyG fyGfyFg{FZf{Ff{Gg~FIg{Gg~G f~Gf~Ff{GezHfzHCfzO2fzN.fyN8fyOfyO;ezNeyN{eyO~fxNkf{O fzOeyGfyHff{N!fxHZezOgwJZgwJgwKg}JIgwKg}K g}Kg}JfxFfxFgxF>gxL0gxK.gwK8fvLjgwLfxKfwK{fwL|fvKhfxLfwLfwFgwFffxK!fvFZfxLf~Ff}Fg}FAg}L2g}K.g|K8f{Ljg|L;f}Kf|Kf|L|f{Khf}Lf|Lf|Fg|Fff~K!f{FZf}Lbv;h~Ideathe6e~;e~B d|Ae|;Cd|;e|IeyAse|;wh|A4e|Bd{Bf{BAezEf{E2fyE:d{EdyE|exEjdyBfyBfe|EexBZbyBeyB:eyAbb{BbyAe{B e{AIb{AdyFeyF8eyEbcyFxdyE]e{F2e{EId{Fc{FcyEc{ENd{EewBZewBewCe}BGewCe}C e}Ce}BgyAZeyAXeyD}g{AIgyDg{D e{De{Agv=Zev=ev?gy=Igv?gy? ey?ey=g{=Ze{=e{?g~=Ig{?g~? e~?e~=f{?ez?fz?CfzF2fzF.fyF8fyFfyF;ezFeyF{eyF~fxFkf{F fzGey?fy?fe{F!fx?ZezFgwBZgwBgwCg}BIgwCg}C g}Cg}Bfx=fx=gx=>fxC0gxC.gwC8fvCjfwCfxCfwC{fwC|fvChfxCfwDfw=gw=ffxC!fv=ZfxCf~=f}=g}=Af}C2g}C.g|C8f{Cjf|C;f}Cf|Cf|C|f{Chf}Cf|Df|=g|=ff~C!f{=Zf}Cbv(h~6deathe7e~(e~0 d|0e|(Cd|(e|6ey0ze|(wh|04e|.d{/f{/Aez2f{22fy2:d{2dy2|ex2jdy/fy/fe|2ex/Zby/ey/:ey.bb{/by.e{/ e{.Ib{.dy3ey38ey2bby3xdy2]e{32e{2Id{3b{3by2b{2Nd{2ew.Zew.ew/e}.Gew/e}/ e}/e}.fy.Zey.Xey1}f{.Ify1f{1 e{1e{.fv*Zev*ev+fy*Ifv+fy+ ey+ey*f{*Ze{*e{+f~*If{+f~+ e~+e~*e{,dz,fz,Cez32fz3.fy38ey3fy3;dz2dy2{ey3~ex2ke{3 ez3dy,fy,fe{3!ex,Zez3gw.Zfw.fw/g}.Igw/g}/ f}/f}.fx*ex*fx*>fx00fx0.fw08fv0jfw0ex0ew0{ew0|fv0hfx0fw0ew*fw*ffx0!fv*Zex0f~*e}*f}*Af}02f}0.f|08f{0jf|0;e}0e|0e|0|f{0hf}0f|0e|*f|*ff~0!f{*Ze}0bv h~.deathe8e~ e~' d|'e| Cd| e|.ey'se| wh|'4e|&d{&f{&Aez)f{)2fy):d{)dy)|ex)jdy&fy&fe|)ex&Zby&ey&:ey%bb{&by%e{& e{%Ib{%dy+ey*8ey)bby+xdy)]e{*2e{)Id{+b{+by)b{)Nd{)ew&Zew&ew'e}&Gew'e}' e}'e}&gy&Zey&Xey)}g{&Igy)g{) e{)e{&gv!Zev!ev#gy!Igv#gy# ey#ey!g{!Ze{!e{#g~!Ig{#g~# e~#e~!e{#ez$fz$Cfz+2fz*.fy*8ey+fy+;ez*ey*{ey+~ex*ke{+ ez+ey#fy$fe{*!ex$Zez+gw&Zgw&gw'g}&Igw'g}' g}'g}&fx"ex"gx">fx(0fx'.fw'8fv(jfw(ex'ew'{ew(|fv'hfx(fw(ew"gw"ffx'!fv"Zex(f~"e}"g}"Af}(2g}'.f|'8f{(jf|(;e}'e|'e|(|f{'hf}(f|(e|"g|"ff~'!f{"Ze}(bvh~!deathe9e~e~ d|e|Cd|e|!eyse|wh|4e|d{f{Aezf{2fy:d{dy|exjdyfyfe|exZbyey:eybb{bye{ e{Ib{dyey8eybcyxdy]e{2e{Id{c{cyc{Nd{ewZewewe}Gewe} e}e}gyZeyXey}g{Igyg{ e{e{gvZevevgyIgvgy eyeyg{Ze{e{g~Ig{g~ e~e~f{ezfzCfz2fz.fy8fyfy;ezey{ey~fxkf{ fzeyfyfe{!fxZezgwZgwgwg}Igwg} g}g}fxfxgx>fx0gx.gw8fvjfwfxfw{fw|fvhfxfwfwgwffx!fvZfxf~f}g}Af}2g}.g|8f{jf|;f}f|f||f{hf}f|f|g|ff~!f{Zf}Dpfnailatt1'"* #%%#5gx#TuQ$tHAtF1UAUEU6UHU7U-wt7ft6:UOt-pkVJ,y"py"Bort\,owj[j[t\Iy7py9DY9yC/Z7ZCYEyEHpf1/}122IHpJfJe/HeffLM$CAA1FCKA K7E2uF7|LCNL9YE9L/hEJD>9f7:KM/pEAy py Bort\%ojYjYt\I/'(A'1h'l'lgwhl(Ol Yg Wlsg-e# f:l/ bg(c'\A[1c[g[gRcMwcRg\NgTYcTWgKhca`WTfR:gcKpcY6phnailatt2^aYYPY[CRgVwYTgQ'eHAgH1F@HEH6FFF6H,we7fg7:FOg-pa9puc9n9naFpl9pBcFlF-kFpI74v=4H4n74urH46=HHH-7H7HuF4t^FHt>HH,g ig f]#k\)]#ta^a^Mk\Kl9pk9DL9lF*M9LELEkFHpf4*}444IKpKfKuh/KhhhIO'EAE18A>C>782w87|>CN>7X87>-h8H6>;f;:=M/p8@g ig f]"k[/]"a^a^Mk[K2'*A*1V(Z( Z VwV Z(SZ YU ZsU/S#"f":Z1pU(f'^A^2Z\`\`TZMwZT^\N^TYZT`KhZcWWVfV:^eMpZ[=(light1-1 ,,,,F(h,y,Tn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=#light2P,Z-Z(P(P(c(CZ#gP'wZ(Tn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=rockatt1#' 4i zUn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^Mrockatt2R V QQQQ; MkQy QTn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^)Mrockatt3)R.V .Q)Q)Q7Q;.Mz)Q.QTn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^)Mrockatt4)R.V .Q)Q)Q7Q;.Mz)Q.QTn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vrockatt5>fHf He>e>eMe/H`i>aHeVn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vrockatt6IfPfPeIeIeYe(P`ZIa}PeSn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=(shotatt146'11115(i-x1Jn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^="Ǧshotatt24;'- ---4"i(w-@n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^,Vshotatt3,1$1,P,381i,w1`n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^,Vshotatt4,1$1,P,381i,w1`n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^,Vshotatt5,|!1~$1|,|P,|3|.1wb,y}1|Vn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^,Vshotatt6,|!1~$1|,|P,|3|.1wb,y}1|Vn$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxatt1EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Viaxatt2EtiEwo BtoHtiAEtiPEty HooiEriIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxatt3EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxatt4EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxatt5EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxatt6EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattb1EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Viaxattb2EtiEwo BtoHtiAEtiPEty HooiEriIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattb3EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattb4EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattb5EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattb6EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattc1EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattc2EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vhaxattc3EthEwq BtqHthAEthPEtz HoqmErhItq.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattc4EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattc5EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattc6EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattd1EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattd2EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vhaxattd3EthEwq BtqHthAEthPEt{ HoqmErhItq.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattd4EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattd5EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^=Vfaxattd6EtfEwo BtoHtfAEtfPEty HoomErfIto.n$lAl1MMMu~MMuMkwluflu:Mlkplyѡlyvynlўvyflv-vI?tvDtOtn?trOt6DO-??ӜOt^O>O,o`po`fe`o*e`ueeoIrypryDSyr/Sy}SSrHVpVfVr/V}rrrIpf𡜦/}𞜦I'A1?DDy?ru?y~ESEyY?yEmh?=~yfyDmp?o`po`fe`o/e`}eeoIp'hAh1^hch c`^[w^`chOc`Y^`WcWh^m\c`f`:cpWp^h򝚤'A1^cc^w^~cScY^Wch^\f:cp^QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_nail2.mdl000066400000000000000000003644641475442401000255350ustar00rootroot00000000000000IDPOs>D<>Y>*ۍ±`BE?B@1111111111111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111111111 !! 1111111111111111111111111111111111111111!! 1111 111 11111 1111 1111111111111111111111111111111111111111111111 !! 11 !! 111 !! 1111 !!!! 111111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111 !!!! 1 !!!! 11 !!!! 111 !!!! 11111111111111111111111111111111111111111111111111111!! 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111111111111! !!!! !!!! 111 !!!! 11 "#$$#"!1111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 111111111111111111111111111111111111111111111111111111111! "#$#"! "#$$#"! "#$$#"! !#$$#"! 1111111111111111111111111111111111111111111111111!!!! 1111 1111 11111 1111 111111111111111111111111111111111111111111111111111111111111111! !#$#"! !#$$#"! !#$$#"! "#$$##! 111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111 "#$##! "#$$##! "#$$##! !#$$#" 11111111111111111111111111111r11111111111111111111!!!! 1111 1111 11111 1111 111111111111111111111111111111111111111r1111111111111111! !#$#" !#$$#" !#$$#" !!#$$#"! 111111111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 11111111111111111111111111111111111111r11111111111111111!!!#$#"! !!#$$#"! !!#$$#"! !#$$#"! 1111111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111111111111! !#$#"! !#$$#"! !#$$#"! !#$$#"! 111111111111111111111111111111111111111111111111111111111!!!! 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! "#$$#"!11111111111111111111111111111111111111111111111111111111111111111!!!! 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! "#$$##!111111111111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111111111111 "#$##! "#$$##! "#$$##! !#$$$#!11111111111111111111111111111111111111111111111111111111111111!!! 1111 1111 11111 1111 111111111111111111111111111111111111111111111111111111111111111 !#$$#! !#$$$#! !#$$$#! "#$$#"! 1111111111111111111111111111111111111111111111111111111111111111! 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111111111111111111! "#$#"! "#$$#"! "#$$#"! !"#$$#"!1111111111111111111111111111111111111111111111111111111111111! 1111 1111 11111 1111 11111111111111111111111111111111111111111 11111111111!!!"#$#"!!"#$$#"!!"#$$#"!!"#$$#"!11111111111111111111111111111111111111111111111111111111111111!! 1111 1111 11111 1111 1111111111111111111111111111111111111111!"!""!""!111111111!!!"#$#"!!"#$$#"!!"#$$#"! !#$$$"!11111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111111 ! 111111111! !#$$"! !#$$$"! !#$$$"! !#$$#"! 111111111111111111111111111111111111111111111111111111111111! 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111111 11111111111! !#$#"! !#$$#"! !#$$#"! !"#$$#" 11111111111111111111111111111111111111111111111111111111!! 1111 1111 11111 1111 111111111111111111111111111111111111111111111111111111111 1111111111!!"#$#" !"#$$#" !"#$$#" "#$$$"! 11111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111111111111 111111111! "#$$"! "#$$$"! "#$$$"! !#$$#"!111111111111111111111111111111111111111111111111111111111111!! 1111 1111 11111 1111 111111111111111111111111111111111111111111111 11111111111! !#$#"! !#$$#"! !#$$#"! !#$$#"!111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111111111 111111111! !#$#"! !#$$#"! !#$$#"! "#$$#"!111111111111111111111111111111111111111111111111111111111111111!! 1111 1111 11111 1111 11111111111111111111111111111111111111111111 111111111! "#$#"! "#$$#"! "#$$#"!!!#$$#"! 11111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111 11111111111!!!#$#"!!!#$$#"!!!#$$#"! !#$$#"!1111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111 111111111! !#$#"! !#$$#"! !#$$#"! !#$$##! 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111 111111111111111111111 111 !#$##! !#$$##! !#$$##! !#$$#"!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111111111 111! !#$#"! !#$$#"! !#$$#"! !#$$$"!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111111111111 11 !#$$"! !#$$$"! !#$$$"! "#$$#"! 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111111111 1 "#$#"! "#$$#"! "#$$#"! !#$$#"!11111111111111111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111 11 !#$#"! !#$$#"! !#$$#"! !#$$#"! 1111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111 11 !#$#"! !#$$#"! !#$$#"! !#$$#"!1111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! "#$$#"! 11111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! !#$$$#!11111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111 !#$$#! !#$$$#! !#$$$#! !#$$#"!1111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! "#$$#"!11111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! !!#$$#"! 11111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111!!#$#"! !!#$$#"! !!#$$#"! !#$$$#! 11111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111 !#$$#! !#$$$#! !#$$$#! "#$$#"!11111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111 11111 "#$#"! "#$$#"! "#$$#"! "#$$#"!11111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! "#$$#"!11111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! !!#$$#"! 1111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111!!#$#"! !!#$$#"! !!#$$#"! "#$$#"! 11111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! "#$$#"! 1111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! !#$$#"! 11111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! "#$$##!1111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111 "#$##! "#$$##! "#$$##! !!#$$#"! 1111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111!!#$#"! !!#$$#"! !!#$$#"! !!#$$#"! 1111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111!!#$#"! !!#$$#"! !!#$$#"! "#$$$"! 1111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111 "#$$"! "#$$$"! "#$$$"! !#$$#"!1111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! !#$$#"!111111111111111111111111111111111111111111111111 1111 1111 11111 1111 11111111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! !#$$#"! 1111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! !#$$#"!111111111111111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! "#$$#"! 1111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111 "#$#"! "#$$#"! "#$$#"! !#$$#"! 1111111111111111111111111111 1111 1111 11111 1111 111111111111111111111111111 !#$#"! !#$$#"! !#$$#"! !!#$$$"! 111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111!!#$$"!!!#$$$"!!!#$$$"! !#$$$"!1111111111111111111111111 1111 1111 11111 1111 111111111111111111111111 !#$$"! !#$$$"! !#$$$"! "#$$$"!111111111111111111111111 1111 1111 11111 1111 11111111111111111111111 "#$$"! "#$$$"! "#$$$"! "#$$#"!11111111111111111111111 1111 1111 11111 1111 1111111111111111111111 !!!!!! "#$$#"! !!!!!! !!!!!!1111111111111111111111 1111 1111 11111 1111 11111111111111111111 !!!!!! 11111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111111111111111111111 1111 1111 11111 1111 1111111111111111111111111111111111111111111 1111 111111111111111111111111111111111111111111111111111111111111 D #$ D D  $ D $ 19 +C+- ' +  +   C- 2 9 < 4 @ 4 @8 8 N B R B RE E ["[ m T m" T f.E y oE o }t   o tt= >>   OL S RO   ? ? @  A A A]    [ @ @[ ?X ? @> h e e    @>  ?h @ @? u r r    @?  ?u 4 71      70 4                 !"##$$#!" $ ""%!!#!%$$ $%"&'()&*+'&'+,,+)*(,(*&*-)&)+)-,,(',-*./01.23/./3443520461787268965.02.271.5359440/492786298956.16:;<=>?@A?B;:CD@C@EF=GEHC<I?J:>EKHC;B?IE@?E:<><;I><?BJLLFGJ=FHKIGA@GDLB:JCBDCH;J>=?A=JFLBLDIKE;HIAG=G@DMNOPQRSTRUNMVWSVSXYPZX[VO\R]MQX^[VNUR\XSRXMOQON\QORU]__YZ]PY[^\ZTSZW_UM]VUWV[N]QPRTP]Y_U_W\^XN[\TZPZSW`abcdefgeha`ijfifklcmkniboep`dkqniaheokfek`bdbaodbehprrlmpclnqomgfmjrh`pihjinapdcegcplrhrjoqkanogmcmfjstuvwxyzx{ts|}y|y~v~|uxsw~|t{x~yx~suwutwux{vzy}{s|{}|twvxzv{}~tzvy}:Muraxrun1U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Muraxrun2U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Muraxrun3U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Muraxrun4U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Muraxrun5U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Muraxrun6U_u U_y U_yV_uLU_uU_}U\ynU\uV_y)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"UpqdU-rockrun1V`V` U_V_CU_WV_V\sV_wX_3||UmVĉWOuO[UDO,PyLBcD:P)BtMODPM}mcs:)tl|Orq}9c?:W)8SO=ĂVP2d9:E)-fD(8E1~-u?S|?B +74Dqe~{vm~G1蕝qPvIpzvx|}_4E |[~mv*qzWuf|骎}餝&\"-4|(1G&}. ~2UZM_4~YfGSb l\ &4v-G- ~4}i"4t^&=z~( t|mz,Or.z,ñ ű?ddjEj_hd\mmhmdjdwñKjf|NKpvsmorfp6mbromz3sP2m\ fljdcdlomRhWjfh{drH±.o±Cj2mpolalmsrYmoeo{lwK.s?o PWVOcOn\[TSXVDV|MsH.\>UUҤrockrun4V`V` U_V_CU_WV_V\sV_wX_3WYM2"wɀlx,"aSHD5|(ECv[|n"Ft!}(Hx}& x)I[?nM7~PYHDU `x [nFn!Hz ǃ! z,r gx 7i]z=qx lbr$Ol, r$ї ͘Ҕ4OpSoUfUPZWYSYOP{˙їIU˙SNŞK`fd[_~`^_d[b__[wƞFdQŝ1\]ɚʚ͘ SVUPaPlYWRSUeUPu͘Hї.YїCV£&Ş1[_\YaWkb`R[X[c_|YwÞJǚ4dǚC\y2BEB=a=lOKRBWDfE|=w}Hv5MvCEUδrockrun5V`V` U_V_CU_WV_V\sV_wX_3rsm 9s42n=94crOl)9}mK1\-88?1vE|F|Uwv]}}w{}vsz˛ʔG|;˖wΣˣIͩ}y|_Fye;}ysͤ>ͫ˫2|]˪˧ʫ2v||:vcvo}}Pw|BwszʣMǩ)}~ʣKwΝ͘˟2|:ycyR|B|}yz͔Gʛ.˖>|2_fd:\c\nljP`fB`}YzO)j>`U)~rockrun6V`V` U_V_CU_WV_V\sV_wX_3IhIIIuHXHfO,HxK<\<:H=mkCr0lWf7qxE:m@xCAmB|tJtHMVwg\k:`vduAg|u!mtMn.gn4}H:b>}BAbC|qW!qQGj,kl1u=:j)iu:3dyF:n@yDAnB|uKuIMWwg_m}CAbC|qWqQMl-km2u>mmCs0lWj7ryF:n@yDAnB|uJuIGYvg_m9buguAh|wqsMp.gp3~H:b=~CAbB|qVqQMl,kn1u=9l)iu:3e<~mF!d5d3~u7}BmB|&mDʶ ɷ α9qwvdspg}}uxYvsɷMΰC{ʴVvčU3Őblw5œ ]ęi›ÿH yh}R`|[~d|vƻJƼ0ɺFºH» }~wmyQ|^w{o~yvƶCƷ0ǵ7|HmrmbmhpPl^fhopfvC0w7kL+tĸstand4P[ P\ L[P[CM[RP[ PYmPYZR[3xHuPvqVzJrPzC?mmCs0lWh7r=gr?xF:nBxDAnC|tKtIGWwg_m9j+iu<3d=lH!b8b4u8~_lB}&lEʹ ˵ Ѯ9pvudrog}|swYu~r{˴MѮC{ͱVuU»FĎ bmwý9Ē!` iƼHƿym|P^{X}p|tɹAɺ0˶FûŶHŹ-|~}vmx{^vyo}xtdzAǵ0ʱ9{HmrmbmhpPl^f[hoqfvC0w7kL(uҽstand5P[ P\ L[P[CM[RP[ PYmPYZR[3~uH|uMvqTzFqNz@[~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd2T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd3T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd4T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd5T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd6T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd7T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd8T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd9T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd10T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd11T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxstnd12T_T`,R\U\DT\PT\T[hT\sU\7~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain1P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain2P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain3P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain4P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain5P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxpain6P_ P_ M_P_CM_QP_2P\8P\ZP_4~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"UpqdRJpain1T`T`,R_T_?T_T_ T\hT_U_3Mkzk΀fˈzlf[bdK/vmt?[a[g5z^gH|^}h}ha5HMaMȇf5rSfHxS˃}mym~JmN\5|Je\+vSyatOqO\Juaxa5n9DaRzIN|SL|f8nz3YcMƀƅbĈ`XEwH/=M pl`[6tzK/?ֵӬMӼdP`]7{zѫKѼ/γ?5Xpain29`9` 9_:_>9_9_:\h9_r:_)!,$=Tp6MxATՇ=V[J[fM[98&04Ns<%LOEIMEW-FMWHZDJzAUDWDEЇDV-D·FU H9NTiHMxTSӊMV[YZf^Z7J&EDNsP*ZNEXKUV2UKXVY&TIkPURWTENyI-H{XNDuz>DaBE]<̇VU2Q:XZ[&M5zFOJTa?o^?ZN2dCF\P$T[^TITOQK0.5%L:J0J=I^MEBtDĠHƟHUHjHi.̜6'Eτ2OFw#O',ȓ211Ē6ȉ2x9?81994ʄ8f8p%-6U!9F$֗'% D7@Շ=A E7D>YBKEfE5=qBi.(-:1/@],ȏ41BxɃA~ˀFΆN}7HyʊBYH@I|fL5>wrHui8&5<}–=%Ey]IIvpain5J`J`$I_J_?J_J_J\zJ_L_3YbM`ehh`f}mfՈbhpf^vf6pLm-Yfwv)lZelZlf0fZlfIfZxffffqdnn0eqIbxbeqMdnMЇnh0`MqhI^Mx^h`hnIpnMn\0pIEn\,bMb\dIteIp\Ke\d\pmu*uČu~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth2J`J`"J_L_KJ_J_L\iJ_rL_*~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth3J`J`"J_L_KJ_J_L\iJ_rL_*~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:MZraxdeth4J`ZJ`_"J__L_ZKJ_ZJ_eL\_iJ_ZrL__*~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:M&raxdeth5I`&I`+ I_+J_&>I_&I_0J\+hI_&rJ_+)~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth6I`I`$H_I_CH_WI_ I\hI_wJ_3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth7I`I`$H_I_CH_WI_ I\hI_wJ_3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth8I`I`$H_I_CH_WI_ I\hI_wJ_3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mraxdeth9I`I`$H_I_CH_WI_ I\hI_wJ_3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"UpqdC\Hadeatha1F`F` E_H_AF_PF_F\hF_rH_5Ga EaHa>G`Ha-H_:EaE_|G^lE_H_fGaG^aE_F_:F_bE`E_F` F`IE`C_F_:F_bC`C_F` F`IC`F_H_:H_bFaF_Ha HaIFaE_F_:F_bC_xE_]F` F`IE`C`C_C`NE`G_4G_GG^bG^hG^pF^hF^F^hG_,F_F_F^G^4G^F_F^XG^4F_G_0FaF`FaFa Fa Ga Ga4Ga F`}G`nGaGa4FaGaG`DGaOFaGa4Fa}H` G`H`CH`4H`4H_4H_hH_4G`G_uG_|H_hH`H_G_rH_@H` H_hG`F` E`F`CF`4F`4F_4F_jF_4E`E_uE_~F_hF`F`E_rF_@F` F_hF`Ga&F`G`AG`0H`.H_9G_G_1F`F_tF_G^kGa G`F_G_BGa G^^F`I\Nadeatha2L`&L`,J_L_CJ_RL_-L\hL_sM_3La KaNa>L`Na-N_:KaK_|L^yK_N_^LaL^qJ_K_:K_bJ`J_K` K`IJ`I_K_:K_bI`I_K` K`II`K_N_:N_bKaK_Na NaIKaJ_K_:K_bI_xJ_]K` K`IJ`I`I_I`NJ`M_CL_GL^^L^hL^iL^L^L^L_,L_L_L^M^L^L_L^M^7L_L_%LaL`LaLaLaLa Ma2La L`L`nLaMa3LaLaL`bLaLaMaJLaM` M`N`>N`-N`,N_6M_hN_M`M_M_M_hM`M_M_N_cM` M_hM`K` K`L`>L`/L`,L_6K_jL_K`K_K_K_hK` K`K_L_cK` K_hK`LaK`M`>M`0M`)M_8L_M_L`L_L_L^zLaL`K_M_fLaL^ZL`N\Tadeatha3R`R`$P_R_?R_R_ R\hR_uT_3Ra PaTa>R`Ta T_;PaP_R^jP_T_^RaR^ZP_Q_:Q_bP`P_Q` Q`IP`N_Q_:Q_bN`N_Q` Q`IN`Q_S_:S_bQaQ_Sa SaIQaP_Q_:Q_bN_xP_]Q` Q`IP`N`N_N`NP`R_4R_R^4R^R^4R^hQ^|R^hR_4R_R_Q^R^4R^R_R^qR^4Q_QR_4QaR`XRaGRa Ra RaRa4RaR`xR`4RaRa4QaRaR`4RaQaRa4RayS` R`S`CS`4S`4S_4S_hS_4R`R_vS_S_hS`S_R_rS_@S` S_hS`Q` Q`Q`4Q`4Q`4Q_4Q_hQ_4P`P_vQ_Q_hQ`Q`Q_uQ_4Q` Q_Q`RaQ`S`>R`0S`.S_:R_R_1Q`Q_tQ_R^kRa R`Q_S_fRa R^ZQ`Q\{Wadeatha4U`}U`$T_V_}CU_}PU_U\hU_}rV_3Ua SaVa>U`Wa-W_:SaS_|U^jS_V_fUaU^aS_T_:T_bS`S_T` T`IS`Q_T_:T_bQ`Q_T` T`IQ`T_V_:V_bTaT_Va VaITaS_T_8T_bQ_xS_]T`0T`IS`#Q`Q_Q`NS`U_{4U_{U^{4U^U^4U^hT^U^U_4U_U_T^U^U^U_{U^{qU^4T_{QU_Ta{U`{XUa{GUaUa UaUaUaU`xU`4UaUa4TaUaU`{4Ua{TaUa{4UaV`{ U`{V`{CV`V`4V_4V_V_U`U_|V_V_hV`V_U_{rV_{@V` V_{hV`T`{ S`{T`{CT`T`4T_4T_T_S`S_tS_T_hT`T`S_{rT_{@T` T_{hT`Ua~T`~V`~>U` V`2V_;U_U_1T`T_T_U^jUa-U` T_~V_~fUaU^~ZT`Q\kWa{deatha5U`lU`r$T_rV_lCU_lPU_wU\rhU_lrV_r3Uat SatVat>U`xWayW_y:SaxS_yU^yjS_tV_tfUayU^taS_zT_z:T_ybS`zS_yT`z T`yIS`yQ_uT_u:T_tbQ`uQ_tT`u T`tIQ`tT_{V_{:V_xbTa{T_xVa{ VaxITaxS_{T_{:T_ybQ_{xS_y]T`{ T`yIS`{Q`{Q_yQ`yNS`yU_k4U_kU^k4U^sU^r4U^rhT^s|U^shU_r4U_rU_sT^rU^s4U^sU_kU^kqU^r4T_kQU_s4TakU`kXUakGUas Uar UarUas4UasU`rxU`r4UasUar4TasUasU`k4UakTarUak4UasyV`k U`kV`kCV`s4V`r4V_r4V_shV_s4U`rU_rvV_sV_rhV`sV_sU_krV_k@V`r V_khV`sT`k S`kT`kCT`s4T`r4T_r4T_sjT_s4S`rS_ruS_s~T_rhT`sT`sS_krT_k@T`r T_khT`sUaoT`oV`o>U`u0V`t.V_t:U_uU_u1T`tT_ttT_uU^tkUau U`uT_oV_ofUat U^oZT`uQ\ZVaideatha6U`\U``$T_`V_\CU_\PU_fU\`gU_\V_`3Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cQ\0\aideatha7Z`0Z`5 Y_5Z_0?Z_0Z_;Z\5sZ_0\_53Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cQ\Vaideatha8U`U`$T_U_CT_WU_!U\hU_wV_3Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cQ\Vaideatha9U`U`$T_U_?U_U_U\hU_V_3Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cQ\ Vaideatha10U` U`$T_U_ ?U_ U_U\hU_ V_3Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cQ\Vaideatha11U`U`$T_U_?U_U_U\hU_V_3Uab SabVab>U`gVag-V_g:SagS_g|U^glS_bV_bfUagU^baS_hT_h:T_gbS`hS_gT`h T`gIS`gQ_dT_d:T_bbQ`dQ_bT`d T`bIQ`bT_iV_i:V_gbTaiT_gVai VagITagS_iT_i:T_hbQ_ixS_h]T`i T`hIS`iQ`iQ_hQ`hNS`hU_Z4U_ZGU^ZbU^ahU^`pT^`hT^aT^ahU_`,T_`T_aT^`U^a4U^aT_ZT^ZXU^`4T_ZU_a0TaZT`ZTaZTaa Ta` Ua` Uaa4Uaa T``}U``nUaaUa`4TaaUaaU`ZDUaZOTa`UaZ4Taa}U`Z U`ZV`Z>V`a-V``,V_`6U_ahV_aU``U_`U_aU_`hU`aU_aU_ZV_ZcU`` U_ZhU`aT`Z S`ZT`ZCT`a4T``4T_`4T_ajT_a4S``S_`uS_aT_`hT`a T`aS_ZrT_Z@T`` T_ZhS`aUa]IT`]U`]CU`c4U`c4U_c4U_cyU_c4T`bT_btT_c}U^bkUac-U`d T_]U_]AUac U^]^T`cS\{Yadeathb1V`}V` U_X_}AV_}PV_X\hV_}sY_.Wa VaYa>W`Ya-Y_:VaV_|W^yV_Y_^WaW^qU_V_:V_bU`U_V` V`IU`S_V_:V_bS`S_V` V`IS`V_X_:X_bVaV_Xa XaIVaU_V_8V_bS_xU_]V`0V`IU`#S`S_S`NU`X_{CW_{GW^{^W^W^iW^W^W^W_$W_W_W^W^W^W_{W^{X^W_{W_Wa{W`{Wa{WaWaWa WaWaW`W`WaXa0WaWaW`{bWa{WaXa{JWaX`{X`{X`{4X`X`4X_4X_X_X`X_X_X_X`X_X_{X_{4X`X_{X`V`{ V`{W`{>W`W`,W_6V_W_V`V_V_V_hV`V`V_{W_{cV` V_{hV`Wa~V`~X`~>X`2X`)X_9W_X_V`V_|W_W^jWaW`V_~X_~fWaW^~ZW`>\{Eadeathb2B`|MB` >_D_|AB_|PB_B\hB_|qE_5Ba AaDa>B`Da-D_:AaA_|B^yA_D_^BaB^q@_A_:A_b@`@_A` A`I@`>_A_:A_b>`>_A` A`I>`A_C_:C_bAaA_Ca CaIAa@_A_:A_b?_x@_]A` A`I@`?`?_?`N@`C_{CB_{GB^{^B^hB^iB^B^B^B_$B_B_B^C^B^B_{B^{C^7B_{B_-Ba{B`{Ba{BaBaBa CaBa B`B`BaCa3BaBaB`{bBa{BaCa{JBaC`{ C`{C`{4C` D`/D_:C_C_1C`C_C_C_hC`C_C_{C_{dC` C_{C`A`{ A`{B`{>B`-B`,B_6A_B_A`A_A_A_hA` A`A_{B_{cA` A_{hA`BaA`C`>C`0C`)C_8B_C_A`A_{B_B^kBaB`A_C_fBa B^ZB`0\y5adeathb34`y&4`,1_4_yC1_yR4_/4\i4_ys5_33a 2a5a>3`5a-5_:2a2_|3^y2_5_^3a3^q1_2_:2_b1`1_2` 2`I1`0_2_:2_b0`0_2` 2`I0`2_5_:5_b2a2_5a 5aI2a1_2_:2_b0_x1_]2` 2`I1`0`0_0`N1`4_yC3_yG3^y^3^h3^i3^3^3^3_,3_3_3^4^3^3_y3^y4^73_y3_%3ay3`y3ay3a3a3a 4a23a 3`3`n3a4a33a3a3`yb3ay3a4ayJ3a4`y 4`y5`y>5`-5`,5_64_h5_4`4_4_4_h4`4_4_y5_yc4` 4_yh4`2`y 2`y3`y>3`/3`,3_62_j3_2`2_2_2_h2` 2`2_y3_yc2` 2_yh2`3a|2`|4`|>4`24`)4_83_4_2`2_{3_3^k3a3`2_|4_|f3a3^|Z3`-\V4afdeathb41`W&1`^$._^1_WC._WR1_e 1\^h1_Ws4_^31a^ /a^2a^>1`c2ac-2_c:/ac/_c|1^cl/_^2_^f1ac1^^a/_d0_d:0_cb/`d/_c0`d 0`cI/`c-_`0_`:0_^b-``-_^0`` 0`^I-`^0_e2_e:2_cb0ae0_c2ae 2acI0ac/_f0_e80_db-_fx/_d]0`e00`dI/`f#-`f-_d-`dN/`d1_V41_V1^V41^]1^]41^]h0^]1^]h1_]41_]1_]0^]1^]41^^1_V1^Vq1^]40_VQ1_]40aV1`VX1aVG1a] 1a] 1a]1a]1a]1`]x1`]41a]1a]40a]1a^1`V41aV0a]1aV41a]2`V 1`V2`VC2`]42`]42_]42_]2_]41`]1_]|2_]2_]h2`]2_^1_Vr2_V@2`] 2_Vh2`]0`V /`V0`VC0`]40`]40_]40_]0_]4/`]/_]t/_]0_]h0`]0`^ /_Vr0_V@0`] 0_Vh0`]1aZ0`Z2`Z>1``02`_.2__:1_`1_`10`_0__t0_`1^_k1a` 1``0_Z2_Zf1a_ 1^ZZ0``-\(4a9deathb51`,1`3 ._34_,A1_,P1_9 1\3h1_,q4_351a1 0a13a1>1`63a6-3_6:0a60_6|1^6y0_13_1^1a61^1q/_70_7:0_6b/`7/_60`7 0`6I/`6-_30_3:0_1b-`3-_10`3 0`1I-`10_82_8:2_6b0a80_62a8 2a6I0a6/_80_8:0_7b._8x/_7]0`8 0`7I/`8.`8._7.`7N/`72_(C1_(G1^(^1^0h1^/i1^/1^01^01_/,1_/1_01^/2^01^01_(1^(2^/71_(1_0%1a(1`)1a)41a01a/1a/ 2a021a0 1`/1`/n1a02a/31a01a01`(\1a)1a/2a)I1a02`( 2`(2`(42`023`/*3_/82_0h2_012`/2_/2_02_/h2`02_02_(2_(d2`/ 2_(2`00`( 0`)1`)C1`0/1`/,1_/60_0j1_00`/0_/0_00_/h0`0 0`00_)1_)c0`/ 0_)h0`01a,0`,2`,>2`222`2)2_281_22_20`10_1{1_21^1k1a21`30_,2_,f1a21^,Z1`20\5a!deathb64`&4`,1_4_C1_R4_ 24\i4_s5_33a 2a5a>4`5a-5_:2a2_|4^j2_5_f4a3^q2_2_42_42`2_2`42`42`0_2_:2_b0`0_2` 2`I0`2_!5_!:5_b2a!2_5a! 5aI2a2_!3_!:3_b0_!x2_]3`! 3`I2`!0`!0_0`N2`4_44_G4^b4^h4^p3^h3^3^h4_,3_3_3^4^44^3_3^X4^43_4_03a3`3a3a 3a 4a 4a44a 3`}4`n4a4a43a3a4`D4aO3a4a43a}4` 4`5`>5`-5`,5_64_h5_4`4_4_4_h4`4_4_5_c4` 4_h4`3` 2`3`C3`/3`*3_62_j3_2`2_2_2_h2` 2`2_3_^2` 3_h2`3a3`4`>4`44`34_44_4_43`3_t3_4^m4a 4`3_4_B4a,3^X3`0\5a!deathb74`&4`,1_4_C1_R4_ 24\i4_s5_33a 2a5a>4`5a-5_:2a2_|4^j2_5_f4a3^q2_2_42_42`2_2`42`42`0_2_:2_b0`0_2` 2`I0`2_!5_!:5_b2a!2_5a! 5aI2a2_!3_!:3_b0_!x2_]3`! 3`I2`!0`!0_0`N2`4_44_G4^b4^h4^p3^h3^3^h4_,3_3_3^4^44^3_3^X4^43_4_03a3`3a3a 3a 4a 4a44a 3`}4`n4a4a43a3a4`D4aO3a4a43a}4` 4`5`>5`-5`,5_64_h5_4`4_4_4_h4`4_4_5_c4` 4_h4`3` 2`3`C3`/3`*3_62_j3_2`2_2_2_h2` 2`2_3_^2` 3_h2`3a3`4`>4`44`34_44_4_43`3_t3_4^m4a 4`3_4_B4a,3^X3`0\5a!deathb84`&4`,1_4_C1_R4_ 24\i4_s5_33a 2a5a>4`5a-5_:2a2_|4^j2_5_f4a3^q2_2_42_42`2_2`42`42`0_2_:2_b0`0_2` 2`I0`2_!5_!:5_b2a!2_5a! 5aI2a2_!3_!:3_b0_!x2_]3`! 3`I2`!0`!0_0`N2`4_44_G4^b4^h4^p3^h3^3^h4_,3_3_3^4^44^3_3^X4^43_4_03a3`3a3a 3a 4a 4a44a 3`}4`n4a4a43a3a4`D4aO3a4a43a}4` 4`5`>5`-5`,5_64_h5_4`4_4_4_h4`4_4_5_c4` 4_h4`3` 2`3`C3`/3`*3_62_j3_2`2_2_2_h2` 2`2_3_^2` 3_h2`3a3`4`>4`44`34_44_4_43`3_t3_4^m4a 4`3_4_B4a,3^X3`0\5a!deathb94`&4`,1_4_C1_R4_ 24\i4_s5_33a 2a5a>4`5a-5_:2a2_|4^j2_5_f4a3^q2_2_42_42`2_2`42`42`0_2_:2_b0`0_2` 2`I0`2_!5_!:5_b2a!2_5a! 5aI2a2_!3_!:3_b0_!x2_]3`! 3`I2`!0`!0_0`N2`4_44_G4^b4^h4^p3^h3^3^h4_,3_3_3^4^44^3_3^X4^43_4_03a3`3a3a 3a 4a 4a44a 3`}4`n4a4a43a3a4`D4aO3a4a43a}4` 4`5`>5`-5`,5_64_h5_4`4_4_4_h4`4_4_5_c4` 4_h4`3` 2`3`C3`/3`*3_62_j3_2`2_2_2_h2` 2`2_3_^2` 3_h2`3a3`4`>4`44`34_44_4_43`3_t3_4^m4a 4`3_4_B4a,3^X3`WZ~\_deathc1Z_~Z_$Y\Z\~CY\~Z\Z[hZ\~s\\7Z^Y]\]>[]\]2\[:Y]Y[|[ZjY[\[f[^ZZqX\Y\:Y\bX]X\Y] Y]IX]W\Y\:Y\bW]W\Y] Y]IW]Y[\[:\[bY]Y[\] \]IY]Y\Z\:Z\bW\xY\]Z] Z]IY]W]W\W]NY][[~4[\~I[[~Z[[h[[hZ[hZ[Z[h[\/Z\Z[Z[[[[[Z\~Z[~][[4Z[~[[/Z]~Z]~[Z^~Z^ Z^[^ [^<[^ Z]w[]d[][^4Z^Z^[]~c[^~HZ^[]~4Z]|[]~[\~\\~H\\%\\,\\n[\y\\h[\[\[\[[z[][\[\~\\~i[][\~h[\Z]~Y\~NZ\~AZ\%Z\)Z\nY\yZ\hY\Y\Y\Y[zY]Y\Y\~uZ\~pY]Z\~hY\Z]'Z][]>[]4[])[\4[[k[\4Z]Z\tZ\{[[m[] [\ Z\[\B[^Z[XZ]VZ\_deathc2Z_Z_$Y\Z\CY\Z\Z[hZ\s\\7Z^Y]\]>Z]\]-\[:Y]Y[|ZZyY[\[^Z^ZZqX\Y\:Y\bX]X\Y] Y]IX]V\Y\:Y\bV]V\Y] Y]IV]Y[[[:[[bY]Y[[] []IY]X\Y\8Y\bW\xX\]Y]0Y]IX]#W]W\W]NX][[DZ\HZ[[Z[Z[hZ[Z[Z[Z\%Z\Z[Z[[[Z[Z\Z[[[Z[Z[Z]Z]Z^Z^Z^Z^ [^Z^Z]Z]pZ][^4Z^Z^Z]aZ^&Z^[]_Z][][\[\4[\\\0\\[\[\[\[\[\[[[][\[\[\p[][\[\Y]Y\Z\HZ\Z\,Z\Y\Z\Y\Y\Y\Y[yY]Y\Y\Z\iY]Y\hY\Z] Y][]>[][]+[\7Z[[\Y]Y\|Z\Z[hZ] Z\Y\[\fZ^Z[ZZ]`Zf_deathc3d_d_,b\e\Dd\Pd\d[hd\se\7d^c]f]>d]f]-f[:c]c[|dZyc[f[^d^dZqb\c\:c\bb]b\c] c]Ib]`\c\:c\b`]`\c] c]I`]c[e[:e[bc]c[e] e]Ic]b\c\:c\b`\xb\]c] c]Ib]`]`\`]Nb]e[Dd\Hd[[d[hd[hd[d[d[d\%d\d[d[d[d[d\d[e[:d[d[-d]d]d^d^d^d^ d^5d^d]d]8d]4e^5d^d^d]ad^&d^e]_d]e]e\e\4e\4e\4e\4e\e\e\e\e\e[e]e\e\e\4e]e\e\c]c\d\Hd\%d\,d\nc\yd\hc\c\c\c[zc]c\c\d\ic]c\hc\d] c]e]>e]e]+e\6d[e\c]c\{d\d[hd] d\c\e\fd^d[Zd]gZl_deathc4i_i_ h\l\Di\i\i[hi\sl\9j^i]l]>j]l]-l[:i]i[|jZyi[l[^j^jZqh\i\:i\bh]h\i] i]Ih]g\i\:i\bg]g\i] i]Ig]i[l[:l[bi]i[l] l]Ii]h\i\:i\bg\xh\]i] i]Ih]g]g\g]Nh]k[Dj\Hj[[j[hj[hj[j[j[j\%j\j[j[k[j[j\j[k[:j[j[#j]j]j^j^j^j^ k^0j^ j]j]pj]k^4j^j^j]aj^&j^k]_j]k]k\l\Hl\%l\,l\nk\yl\hk\k\k\k[zk]k\k\l\ik]k\hk\i]i\j\Hj\%j\,j\ni\yj\hi\i\i\i[zi]i\i\j\ii]i\hi\j] i]k]>k]2k])k\7j[jk\i]i\{j\j[hj] j\i\k\fj^!j[Zj]fZ|l_deathc5i_|i_ h\l\|Di\|Pi\}i[hi\|sl\9i^h]k]>j]k]-k[;h]h[iZjh[k[^i^iZqg\h\:h\bg]g\h] h]Ig]f\h\:h\bf]f\h] h]If]h[k[:k[bh]h[k] k]Ih]h\i\:i\bf\xh\]i] i]Ih]f]f\f]Nh]j[|4j\|Ij[|Zj[hj[hi[hi[i[hj\/i\i[i[j[i[i\|i[|]j[4i[|j[/i]|i]|hi^|i^ i^j^ j^j]2j])j\7i[j\i]i\i\i[wi] i\i\j\fi^"i[Xi]fZel_udeathc6i_ei_l h\ll\eDi\ePi\si[lhi\esl\l9j^mh]mk]m>j]rk]r2k[r:h]rh[r|jZrlh[mk[mfj^rjZmah\si\s:i\rbh]sh\ri]s i]rIh]rf\oi\o:i\mbf]of\mi]o i]mIf]mi[tk[t:k[rbi]ti[rk]t k]rIi]rh\ui\t8i\sbf\uxh\s]i]t0i]sIh]u#f]uf\sf]sNh]sj[e4j\eIj[eZj[lj[lhi[lhi[li[lj\l2i\li[li[lj[lj[li\ei[e]j[l4i[ej[li]ei]e[i^ei^li^lj^l j^lj^li]luj]lpj]lj^l4i^lj^lj]ecj^eHi^lj]e4i]lj]ej\ek\eHk\lk\l)k\l4k\lk\lj\lj\lj\lk[llk]lk\lj\ewk\edk]l,j\ehj\li]eIh\eNi\eAi\li\l4i\l4i\li\lh\lh\lh\li[lli]li\lh\esi\e4i]l,i\ehh\lj]h'i]hj]hCj]n4j]n4j\n4j[nj\n4i]ni\ni\nj[npj]n j\o i\hj\hAj^n j[h^i]nfZPl_`deathc7i_Pi_X h\Xl\PDi\Pi\_i[Xhi\Psl\X9j^Xh]Xk]XAj]]l]]/l[]:h]]h[]|jZ]jh[Xk[Xfj^]jZXah\^i\^:i\]bh]^h\]i]^ i]]Ih]]f\Zi\Z:i\Xbf]Zf\Xi]Z i]XIf]Xi[`k[`:k[]bi]`i[]k]` k]]Ii]]h\`i\`:i\^bf\`xh\^]i]` i]^Ih]`f]`f\^f]^Nh]^j[P4j\P4j[Pj[Wj[Wj[Whi[Wj[Whj\W4j\Wj[Wi[Wj[Wj[Xj\Pj[PZj[W4i[PWj[Wi]Pj]P[j^PNj^W j^Wj^Wj^W4j^Wj]Wzj]W4j]W4j^W4i^Wj^X2j]P4j^P4i^Wj]P4j]Wk]PIj\PNk\PAk\W4k\W4k\W4k\Wk\Wj\Wj\Wk\Wk[Wlk]Wk\Xj\Psk\P4k]W k\Phk\Wi]P(i\Pi\P4i\W4i\W4i\W4i\Wi\Wh\Wh\Wi\Wi[Wi]Wi\Xi\Pwi\P4i]W i\Pi\Wj]T i]Tk]T>j]Z1k]Y/k\Y:j[Zjj\Z1i]Yi\Yti\Z|j[Yhj]Z j\Zi\Tk\Tfj^Y!j[TZi]ZfZ;l_Ldeathc8i_;i_A h\Al\;Di\;Pi\J}i[Ahi\;sl\A9j^Di]Dl]D>j]Il]I-l[I:i]Ii[I|jZIyi[Dl[D^j^IjZDqh\Ji\J:i\Ibh]Jh\Ii]J i]IIh]If\Fi\F:i\Dbf]Ff\Di]F i]DIf]Di[Kk[K:k[Ibi]Ki[Ik]K k]IIi]Ih\Li\K8i\Jbg\Lxh\J]i]K0i]JIh]L#g]Lg\Jg]JNh]Jk[k]Ek]E+k\E7j[Ek\Ei]Ei\E|j\Ej[Ehj]E j\Fi\?k\?fj^Ej[?Zj]EfZ%l_5deathc9i_&i_- h\-l\&Di\&Pi\4i[-hi\&sl\-9j^.i].l].>j]3l]3-l[3:i]3i[3|jZ3yi[.l[.^j^3jZ.qh\4i\4:i\3bh]4h\3i]4 i]3Ih]3f\/i\/:i\.bf]/f\.i]/ i].If].i[5k[5:k[3bi]5i[3k]5 k]3Ii]3h\5i\5:i\4bg\5xh\4]i]5 i]4Ih]5g]5g\4g]4Nh]4k[%Dj\%Hj[%[j[-hj[,hj[,j[-j[-j\,%j\,j[-j[,j[-j[-j\%j[%k[,:j[%j[--j]%j]&j^&j^-j^,j^, j^-5j^-j],j],8j]-4k^,5j^-j^-j]%gj^&j^,k]&>j]-k]%k\%k\%4k\-.l\,.l\,nk\-k\-k\,k\,k\-k[,xk]-k\-k\%k\%pk],k\%k\-i]%i\&j\&Aj\-%j\,,j\,ni\-yj\-hi\,i\,i\-i[,zi]-i\-i\&j\&ii],i\&hi\-j]) i])k])>k]/2k].)k\.7j[/jk\/i].i\.{j\/j[.hj]/ j\/i\)k\)fj^.!j[)Zj]/fZl_+deathc10i_i_! h\!l\Di\Pi\+}i[!hi\sl\!9j^#i]#l]#>j](l](-l[(:i](i[(|jZ(yi[#l[#^j^(jZ#qh\)i\):i\(bh])h\(i]) i](Ih](f\%i\%:i\$bf]%f\$i]% i]$If]$i[+k[+:k[(bi]+i[(k]+ k](Ii](h\+i\+:i\)bg\+xh\)]i]+ i])Ih]+g]+g\)g])Nh])k[Dj\Hj[[#hj["hj["j[#j[#j\"%j\"j[#j["j[#j[#j\j[k[":j[j[#-j]j]j^j^#j^"j^" j^#5j^#j]"j]"8j]#4k^"5j^#j^#j]aj^&j^"k]_j]#k]k\k\4k\#.l\".l\"nk\#k\#k\"k\"k\#k["xk]#k\#k\k\pk]"k\k\#i]i\j\Hj\#%j\",j\"ni\#yj\#hi\"i\"i\#i["zi]#i\#i\j\ii]"i\hi\#j] i]k]>k]%2k]$)k\$7j[%jk\%i]$i\${j\%j[$hj]% j\%i\k\fj^$!j[Zj]%gZl_!deathc11i_i_ h\l\Di\Pi\i[hi\sl\9j^i]l]>k]l]2l[:i]i[|kZji[l[fk^jZqi\j\:j\bi]i\j] j]Ii]g\j\:j\bg]g\j] j]Ig]i[ l[ :l[bi] i[l] l]Ii]i\!j\ 8j\bg\!xi\]j] 0j]Ii]!#g]!g\g]Ni]k[4k\Ik[Zk[k[hj[hj[j[k\2j\j[j[k[k[j\j[]k[4j[k[j]j][j^j^j^k^ k^k^j]uk]pk]k^4j^j^k]ck^Hj^k]4j]k]k\l\Hl\l\,l\k\l\k\k\k\k[yk]k\k\l\ik]k\hk\j]Ii\Nj\Aj\j\4j\4j\j\i\i\i\j[lj]j\i\sj\4j],j\hi\j]'j]k]>k]4k])k\4k[k\4j]j\j\k[hk] k\ j\k\Bk^-j[Xj]fZl_deathc12i_i_ h\l\Di\Pi\i[hi\sl\9j^h]k]Aj]l]/l[:h]h[|jZjh[k[fj^jZah\i\:i\bh]h\i] i]Ih]f\i\:i\bf]f\i] i]If]i[k[:k[bi]i[k] k]Ii]h\i\:i\bf\xh\]i] i]Ih]f]f\f]Nh]j[4j\4j[j[j[j[hi[j[j\4j\j[i[j[j[j\j[Zj[4i[Wj[i]j][j^Nj^j^j^j^j^j]zj]4j]j^4i^j^j]4j^4i^j]4j]k]Ij\Nk\Ak\k\4k\4k\k\j\j\k\k[lk]k\j\sk\4k] k\hk\i](i\i\4i\i\4i\4i\i\h\h\i\i[i]i\i\wi\4i] i\i\j] i] k] >j] k]-k\;j[j\1i]i\i\j[hj] j\ i\ k\ fj^j[ Zi]fZl_deathc13i_i_ h\l\Di\Pi\i[hi\sl\9j^h]k]Aj]l]/l[:h]h[|jZjh[k[fj^jZah\i\:i\bh]h\i] i]Ih]f\i\:i\bf]f\i] i]If]i[k[:k[bi]i[k] k]Ii]h\i\:i\bf\xh\]i] i]Ih]f]f\f]Nh]j[4j\4j[j[j[j[hi[j[j\4j\j[i[j[j[j\j[Zj[4i[Wj[i]j][j^Nj^j^j^j^j^j]zj]4j]j^4i^j^j]4j^4i^j]4j]k]Ij\Nk\Ak\k\4k\4k\k\j\j\k\k[lk]k\j\sk\4k] k\hk\i](i\i\4i\i\4i\4i\i\h\h\i\i[i]i\i\wi\4i] i\i\j] i] k] >j] k]-k\;j[j\1i]i\i\j[hj] j\ i\ k\ fj^j[ Zi]fZl_deathc14i_i_ h\l\Di\Pi\i[hi\sl\9j^h]k]Aj]l]/l[:h]h[|jZjh[k[fj^jZah\i\:i\bh]h\i] i]Ih]f\i\:i\bf]f\i] i]If]i[k[:k[bi]i[k] k]Ii]h\i\:i\bf\xh\]i] i]Ih]f]f\f]Nh]j[4j\4j[j[j[j[hi[j[j\4j\j[i[j[j[j\j[Zj[4i[Wj[i]j][j^Nj^j^j^j^j^j]zj]4j]j^4i^j^j]4j^4i^j]4j]k]Ij\Nk\Ak\k\4k\4k\k\j\j\k\k[lk]k\j\sk\4k] k\hk\i](i\i\4i\i\4i\4i\i\h\h\i\i[i]i\i\wi\4i] i\i\j] i] k] >j] k]-k\;j[j\1i]i\i\j[hj] j\ i\ k\ fj^j[ Zi]fZl_deathc15i_i_ h\l\Di\Pi\i[hi\sl\9j^h]k]Aj]l]/l[:h]h[|jZjh[k[fj^jZah\i\:i\bh]h\i] i]Ih]f\i\:i\bf]f\i] i]If]i[k[:k[bi]i[k] k]Ii]h\i\:i\bf\xh\]i] i]Ih]f]f\f]Nh]j[4j\4j[j[j[j[hi[j[j\4j\j[i[j[j[j\j[Zj[4i[Wj[i]j][j^Nj^j^j^j^j^j]zj]4j]j^4i^j^j]4j^4i^j]4j]k]Ij\Nk\Ak\k\4k\4k\k\j\j\k\k[lk]k\j\sk\4k] k\hk\i](i\i\4i\i\4i\4i\i\h\h\i\i[i]i\i\wi\4i] i\i\j] i] k] >j] k]-k\;j[j\1i]i\i\j[hj] j\ i\ k\ fj^j[ Zi]C^gHbwdeathd1F`kFbq E`qH`kBF`kPF`wF_qhF_kH`q9Fao EaoHao>G`tHauH_u;EatE_uG^ujE_oH_ofGauF^oqE_vF_v:F_ubE`vE_uF`v F`uIE`uC_qF_q:F_pbC`qC_pF`q F`pIC`pE_wH_w:H_tbEawE_tHaw HatIEatE_wF_w:F_ubC_wxE_u]F`w F`uIE`wC`wC_uC`uNE`uG_g4G_gGG^gbG^ohG^npF^nhF^oF^ohG_n,F_nF_oF^nG^o4G^oF_gF^gXG^n4F_gG_o0FagF`gFagFao Fan Gan Gao4Gao F`n}G`nnGaoGan4FaoFaoG`gDGagOFanGag4Fao}G`g G`gH`g>H`o-H`n,H_n6G_ohH_oG`nG_nG_oG_nhG`oG_oG_gH_gcG`n G_ghG`oF`g E`gF`gCF`o4F`n4F_n4F_ojF_o4E`nE_nuE_oF_nhF`o F`oE_grF_g@F`n F_ghE`oFakF`kG`k>G`q4G`p3G_p4G_qG_q4F`pF_ptF_qG^pmGaq G`qF_kG_kBGap,F^kXF`qC^gHbwdeathd2F`kFbq E`qH`kBF`kPF`wF_qhF_kH`q9Fao EaoHao>G`tHauH_u;EatE_uG^ujE_oH_ofGauF^oqE_vF_v:F_ubE`vE_uF`v F`uIE`uC_qF_q:F_pbC`qC_pF`q F`pIC`pE_wH_w:H_tbEawE_tHaw HatIEatE_wF_w:F_ubC_wxE_u]F`w F`uIE`wC`wC_uC`uNE`uG_g4G_gGG^gbG^ohG^npF^nhF^oF^ohG_n,F_nF_oF^nG^o4G^oF_gF^gXG^n4F_gG_o0FagF`gFagFao Fan Gan Gao4Gao F`n}G`nnGaoGan4FaoFaoG`gDGagOFanGag4Fao}G`g G`gH`g>H`o-H`n,H_n6G_ohH_oG`nG_nG_oG_nhG`oG_oG_gH_gcG`n G_ghG`oF`g E`gF`gCF`o4F`n4F_n4F_ojF_o4E`nE_nuE_oF_nhF`o F`oE_grF_g@F`n F_ghE`oFakF`kG`k>G`q4G`p3G_p4G_qG_q4F`pF_ptF_qG^pmGaq G`qF_kG_kBGap,F^kXF`qC^gHbwdeathd3F`kFbq E`qH`kBF`kPF`wF_qhF_kH`q9Fao EaoHao>G`tHauH_u;EatE_uG^ujE_oH_ofGauF^oqE_vF_v:F_ubE`vE_uF`v F`uIE`uC_qF_q:F_pbC`qC_pF`q F`pIC`pE_wH_w:H_tbEawE_tHaw HatIEatE_wF_w:F_ubC_wxE_u]F`w F`uIE`wC`wC_uC`uNE`uG_g4G_gGG^gbG^ohG^npF^nhF^oF^ohG_n,F_nF_oF^nG^o4G^oF_gF^gXG^n4F_gG_o0FagF`gFagFao Fan Gan Gao4Gao F`n}G`nnGaoGan4FaoFaoG`gDGagOFanGag4Fao}G`g G`gH`g>H`o-H`n,H_n6G_ohH_oG`nG_nG_oG_nhG`oG_oG_gH_gcG`n G_ghG`oF`g E`gF`gCF`o4F`n4F_n4F_ojF_o4E`nE_nuE_oF_nhF`o F`oE_grF_g@F`n F_ghE`oFakF`kG`k>G`q4G`p3G_p4G_qG_q4F`pF_ptF_qG^pmGaq G`qF_kG_kBGap,F^kXF`qC^gHbwdeathd4F`kFbq E`qH`kBF`kPF`wF_qhF_kH`q9Fao EaoHao>G`tHauH_u;EatE_uG^ujE_oH_ofGauF^oqE_vF_v:F_ubE`vE_uF`v F`uIE`uC_qF_q:F_pbC`qC_pF`q F`pIC`pE_wH_w:H_tbEawE_tHaw HatIEatE_wF_w:F_ubC_wxE_u]F`w F`uIE`wC`wC_uC`uNE`uG_g4G_gGG^gbG^ohG^npF^nhF^oF^ohG_n,F_nF_oF^nG^o4G^oF_gF^gXG^n4F_gG_o0FagF`gFagFao Fan Gan Gao4Gao F`n}G`nnGaoGan4FaoFaoG`gDGagOFanGag4Fao}G`g G`gH`g>H`o-H`n,H_n6G_ohH_oG`nG_nG_oG_nhG`oG_oG_gH_gcG`n G_ghG`oF`g E`gF`gCF`o4F`n4F_n4F_ojF_o4E`nE_nuE_oF_nhF`o F`oE_grF_g@F`n F_ghE`oFakF`kG`k>G`q4G`p3G_p4G_qG_q4F`pF_ptF_qG^pmGaq G`qF_kG_kBGap,F^kXF`qG^XLbhdeathd5J`ZJb` I``J`ZFJ`ZJ`fJ_`hJ_ZrL``7Ja` Ia`La`>J`eLae-L_e:IaeI_e|J^eyI_`L_`^JaeJ^`qH_fI_f:I_ebH`fH_eI`f I`eIH`eG_bI_b:I_`bG`bG_`I`b I``IG``I_gL_g:L_ebIagI_eLag LaeIIaeH_hI_g8I_fbG_hxH_f]I`g0I`fIH`h#G`hG_fG`fNH`fK_XCJ_XGJ^X^J^_hJ^_iJ^_J^_J^_J__$J__J__J^_K^_J^`J_XJ^XK^_7J_XJ__-JaXJ`XJaXJa_Ja_Ja_ Ka_Ja_ J`_J`_Ja_Ka_3Ja_Ja`J`XbJaXJa_KaXJJa_K`X K`XL`X>L`_ L`_,L__6K__hL__K`_K__K__K__hK`_K_`K_XL_XcK`_ K_XhK`_I`X I`XJ`X>J`_-J`_,J__6I__J__I`_I__I__I__hI`_ I``I_XJ_XcI`_ I_XhI`_Ja\I`\K`\>K`b0K`a)K_a8J_bK_bI`aI_a{J_bJ^akJabJ`bI_\K_\fJaa J^\ZJ`bG^CLbSdeathd6J`EJbL I`KJ`EFJ`EJ`RJ_KhJ_ErL`K7KaK IaKLaK>K`PLaP-L_P:IaPI_P|K^PlI_KL_KfKaPK^KaI_QJ_Q:J_PbI`QI_PJ`Q J`PII`PG_MJ_M:J_LbG`MG_LJ`M J`LIG`LJ_SL_S:L_PbJaSJ_PLaS LaPIJaPI_SJ_S:J_QbG_SxI_Q]J`S J`QII`SG`SG_QG`QNI`QK_C4K_CGK^CbK^KhK^JpJ^JhJ^KJ^KhK_J,J_JJ_KJ^JK^K4K^KJ_CJ^CXK^J4J_CK_K0JaCJ`CJaCJaK JaJ KaJ KaK4KaK J`J}K`JnKaKKaJ4JaKKaKK`CDKaCOJaJKaC4JaK}L`C K`CL`CCL`K4L`J4L_J4L_KhL_K4K`JK_JuK_K|L_JhL`KL_KK_CrL_C@L`J L_ChK`KJ`C I`CJ`CCJ`K4J`J4J_J4J_KjJ_K4I`JI_JuI_K~J_JhJ`KJ`KI_CrJ_C@J`J J_ChJ`KKaG&J`GK`GAK`M0L`L.L_L9K_MK_M1J`LJ_LtJ_MK^LkKaM K`MJ_GK_GBKaL K^G^J`MG^$Lb4deathd7J`&Jb- I`,J`&CI`&QJ`3J_,hJ_&ZL`,7Ja, Ia,La,>J`1La1-L_1:Ia1I_1|J^1yI_,L_,^Ja1J^,qH_2I_2:I_1bH`2H_1I`2 I`1IH`1G_.I_.:I_,bG`.G_,I`. I`,IG`,I_4L_4:L_1bIa4I_1La4 La1IIa1H_4I_4:I_2bG_4xH_2]I`4 I`2IH`4G`4G_2G`2NH`2K_$CJ_$GJ^$^J^+hJ^+iJ^+J^+J^+J_+$J_+J_+J^+K^+J^,J_$J^$K^+7J_$J_+-Ja$J`$Ja$Ja+Ja+Ja+ Ka+Ja+ J`+J`+Ja+Ka+3Ja+Ja,J`$bJa$Ja+Ka$JJa+K`$ K`$L`$>L`+ L`+,L_+6K_+hL_+K`+K_+K_+K_+hK`+K_,K_$L_$cK`+ K_$hK`+I`$ I`$J`$>J`+-J`+,J_+6I_+J_+I`+I_+I_+I_+hI`+ I`,I_$J_$cI`+ I_$hI`+Ja(I`(K`(>K`.0K`-)K_-8J_.K_.I`-I_-{J_.J^-kJa.J`.I_(K_(fJa- J^(ZJ`.G^Lbdeathd8J`Jb I` J`CI`QJ`J_ hJ_ZL` 7Ja Ia La >K`La-L_:IaI_|K^jI_ L_ fKaJ^ qI_J_:J_bI`I_J` J`II`G_ J_ :J_ bG` G_ J` J` IG` I_L_:L_bIaI_La LaIIaI_J_8J_bG_xI_]J`0J`II`#G`G_G`NI`K_4K_GK^bK^ K^ dJ^ hJ^ J^ K_ *J_ J_ J^ K^ K^ J_J^XK^ 4J_K_ JaJ`JaJa Ja Ka Ka Ka J` K` nKa Ka 4Ja Ja K`DKaOJa Ka4Ja K` K`L`>L` L` ,L_ 6K_ L_ K` K_ K_ K_ hK` K_ K_L_cK` K_hK` J` I`J`CJ` J` 4J_ 4J_ J_ I` I_ tI_ J_ hJ` J` I_rJ_@J` J_hI` JaJ`K`>K` 4K` 3K_ 4K_ K_ 4J` J_ J_ K^ jKa -K` J_K_BKa ,J^XJ` G^Lbdeathd9J`Jb "I` J`CI`QJ`J_ hJ_ZL` 7Ja Ia La >K`La-L_:IaI_|K^jI_ L_ fKaJ^ qI_J_:J_bI`I_J` J`II`G_ J_ :J_ bG` G_ J` J` IG` I_L_:L_bIaI_La LaIIaI_J_8J_bG_xI_]J`0J`II`#G`G_G`NI`K_4K_GK^bK^ K^ dJ^ hJ^ J^ K_ *J_ J_ J^ K^ K^ J_J^XK^ 4J_K_ JaJ`JaJa Ja Ka Ka Ka J` K` nKa Ka 4Ja Ja K`DKaOJa Ka4Ja K` K`L`>L` L` ,L_ 6K_ L_ K` K_ K_ K_ hK` K_ K_L_cK` K_hK` J` I`J`CJ` J` 4J_ 4J_ J_ I` I_ tI_ J_ hJ` J` I_rJ_@J` J_hI` JaJ`K`>K` 4K` 3K_ 4K_ K_ 4J` J_ J_ K^ jKa -K` J_K_BKa ,J^XJ` SZY`deathe1X_X`,V\X\FV\X\X[hX\sY\7W^V]Y]>W]Y]-Y[:V]V[|WZyV[Y[^W^WZqU\V\:V\bU]U\V] V]IU]S\V\:V\bS]S\V] V]IS]V[X[:X[bV]V[X] X]IV]U\V\:V\bS\xU\]V] V]IU]S]S\S]NU]X[DW\HW[[W[W[hW[W[W[W\%W\W[W[W[W[W\W[X[W[W[W]W]W^W^W^W^ W^1W^W]W]W]4X^X]2X])X\7W[jX\V]V\{W\W[hW] W\V\X\fW^!W[ZW]jZrq`deathe2n_sn`z$m\zn\sCm\sn\n[zsn\ssq\z7n^zm]zp]z>n]p]-p[:m]m[|nZym[zp[z^n^nZzql\m\:m\bl]l\m] m]Il]j\|m\|:m\zbj]|j\zm]| m]zIj]zm[o[:o[bm]m[o] o]Im]l\m\:m\bk\xl\]m] m]Il]k]k\k]Nl]o[rDn\rHn[r[n[yn[yhn[yn[yn[yn\y%n\yn[yn[yn[yn[zn\rn[ro[yn[rn[yn]rn]rn^rn^yn^yn^y n^y1n^yn]yn]yn]y4o^yo]|2o]{)o\{7n[|jo\|m]{m\{{n\|n[{hn]| n\|m\vo\vfn^{!n[vZn]|jZ`q`rdeathe3n_`n`j$m\jn\`Cm\`n\qn[jzn\`sq\j7n^jm]jp]j>n]op]o-p[o:m]om[o|nZoym[jp[j^n^onZjql\pm\p:m\obl]pl\om]p m]oIl]oj\lm\l:m\jbj]lj\jm]l m]jIj]jm[qo[q:o[obm]qm[oo]q o]oIm]ol\rm\q8m\pbk\rxl\p]m]q0m]pIl]r#k]rk\pk]pNl]po[bDn\bHn[b[n[in[ihn[in[in[in\i%n\in[in[in[in[jn\bn[bo[in[bn[in]bn]bn^bn^in^in^i n^i1n^in]in]in]i4o^io]l2o]k)o\k7n[ljo\lm]km\k{n\ln[khn]l n\lm\fo\ffn^k!n[fZn]ljZRq`cdeathe4n`Rn`Z m_Zn_RCm_RWn_`n\Zzn_Rwq_Z3n^[m][p][>n]`p]`-p[`:m]`m[`|nZ`ym[[p[[^n^`nZ[ql\am\a:m\`bl]al\`m]a m]`Il]`j\]m\]:m\\bj]]j\\m]] m]\Ij]\m[co[c:o[`bm]cm[`o]c o]`Im]`l\cm\c:m\abk\cxl\a]m]c m]aIl]ck]ck\ak]aNl]ao[SDn\SHn[S[n[[hn[Zhn[Zn[[n[[n\Z%n\Zn[[n[Zn[[n[[n\Sn[So[Z:n[Sn[[-n]Sn]Sn^Sn^[n^Zn^Z n^[5n^[n]Zn]Z8n][4o^Z5n^[n^[n]San^S&n^Zo]S_n][o]So\So\S4o\[.p\Z.p\Zno\[o\[o\Zo\Zo\[o[Zxo][o\[o\So\Spo]Zo\So\[m]Sm\Sn\SHn\[%n\Z,n\Znm\[yn\[hm\Zm\Zm\[m[Zzm][m\[m\Sn\Sim]Zm\Shm\[n]W m]Wo]W>o]]2o]\)o\\7n[]jo\]m]\m\\{n\]n[\hn]] n\]m\Wo\Wfn^\!n[WZn]]kZGq`Wdeathe5n`Gn`N m_Nn_GCm_GWn_Wn\Nsn_Gwq_N3n^Om]Op]O>o]Tp]T2p[T:m]Tm[T|oZTjm[Op[Ofo^TnZOqm\Un\U:n\Tbm]Um\Tn]U n]TIm]Tk\Qn\Q:n\Obk]Qk\On]Q n]OIk]Om[Vp[V:p[Tbm]Vm[Tp]V p]TIm]Tm\Wn\V8n\Ubk\Wxm\U]n]V0n]UIm]W#k]Wk\Uk]UNm]Uo[G4o\GIo[GZo[No[Nhn[Nhn[Nn[No\N2n\Nn[Nn[No[No[Nn\Gn[G]o[N4n[Go[Nn]Gn]G[n^Gn^Nn^No^N o^No^Nn]Nuo]Npo]No^N4n^Nn^No]Gco^GHn^No]G4n]No]Go\Gp\GHp\Np\N,p\No\Np\No\No\No\No[Nyo]No\No\Gp\Gio]No\Gho\Nn]GIm\GNn\GAn\Nn\N4n\N4n\Nn\Nm\Nm\Nm\Nn[Nln]Nn\Nm\Gsn\G4n]N,n\Ghm\Nn]J'n]Jo]J>o]P4o]P)o\P4o[Po\P4n]Pn\Pn\Po[Pho]P o\Q n\Jo\JBo^P-n[JXn]PkZ>q`Ndeathe6n`?n`G m_Fn_?Cm_?Wn_Nn\Fsn_?wq_F3n^Gm]Gp]G>o]Lp]L2p[L:m]Lm[L|oZLjm[Gp[Gfo^LnZGqm\Mn\M:n\Lbm]Mm\Ln]M n]LIm]Lk\In\I:n\Gbk]Ik\Gn]I n]GIk]Gm[Np[N:p[Lbm]Nm[Lp]N p]LIm]Lm\Nn\N:n\Mbk\Nxm\M]n]N n]MIm]Nk]Nk\Mk]MNm]Mo[>4o\>Io[>Zo[Fho[Ehn[Ehn[Fn[Fho\E/n\En[Fn[Eo[Fo[Fn\>n[>]o[E4n[>o[F/n]>n]?\n^?n^F n^Eo^E o^Ffo^?In^Eo]?4n]F|o]>o\>p\>Hp\F%p\E,p\Eno\Fyp\Fho\Eo\Eo\Fo[Ezo]Fo\Fo\>p\>io]Eo\>ho\Fn]>Lm\?n\?en\F4n\E4n\E4n\Fln\Fm\Em\Exm\Fhn[Emn]F n\Fm\?sn\?4n]E,n\?hm\Fn]B'n]Bo]B>o]H4o]H)o\H4o[Hko\H4n]Gn\Gtn\H{o[Gmo]H o\I n\Bo\BBo^Hn[BXn]HkZ,q`<deathe7n`,n`4 m_4n_,Cm_,Wn_;n\4zn_,wq_43n^4m]4p]4>o]9p]9-p[9:m]9m[9|nZ9ym[4p[4^n^9nZ4ql\:m\::m\9bl]:l\9m]: m]9Il]9k\6m\6:m\4bk]6k\4m]6 m]4Ik]4m[;p[;:p[9bm];m[9p]; p]9Im]9l\o]5o]5+o\57n[5o\5n]5n\5n\5n[5zn]5 n\6m\/o\/fn^5n[/Zn]5kZ!q`1deathe8n`!n`+ m_+n_!Cm_!Wn_1n\+zn_!wq_+3o^*m]*p]*>o].p]/2p[/;m].m[/oZ/jm[*p[*fo^/oZ*am\0n\0:n\/bm]0m\/n]0 n]/Im]/k\+n\+:n\*bk]+k\*n]+ n]*Ik]*n[1p[1:p[.bn]1n[.p]1 p].In].m\1n\1:n\/bk\1xm\/]n]1 n]/Im]1k]1k\/k]/Nm]/o[!4o\!4o[!o[)o[(o[(hn[)o[)ho\(4o\(o[)n[(o[)o[)o\!o[!Zo[(4n[!Wo[)4n]!Po]"[o^"Go^) o^(o^(o^)4o^)o](wo](4o])4o^(4n^)o^)o]!o^"4n^(o]"4o])xp]!Io\!Np\!Ap\)4p\(4p\(4p\)lp\)o\(o\(xo\)hp[(mp]) p\)o\!sp\!4p](,p\!ho\)n]!Lm\"n\"en\)4n\(4n\(4n\)ln\)m\(m\(xm\)n[(mn])n\)m\"sn\"4n](%n\"hn\)o]% n]%o]%Co]+1p]*.p\*9o[+jo\+1n]*n\*tn\+|o[*ho]+ o\+n\%o\%Bo^*!o[%^n]+kZq`"deathe9n`n` m_n_Am_Wn_"n\sn_wq_3n^m]p]>o] p] -p[ :m] m[ |nZ ym[p[^n^ nZql\!m\!:m\ bl]!l\ m]! m] Il] k\m\:m\bk]k\m] m]Ik]m["p[":p[ bm]"m[ p]" p] Im] l\"m\":m\!bk\"xl\!]m]" m]!Il]"k]"k\!k]!Nl]!o[4o\Io[Zo[ho[hn[hn[n[ho\/n\n[n[o[n[n\n[]o[4n[o[/n]n]hn^ n^ n^o^ o^n]|o]o\p\Hp\%p\,p\no\yp\ho\o\o\o[zo]o\o\p\io]o\ho\m]m\n\An\%n\,n\nm\yn\hm\m\m\m[zm]m\m\n\im]m\hm\n] m]o]>o]o]+o\6n[vo\n]n\n\n[zn] n\m\o\fn^n[Zn]MvDnailatt148 2222:-h.x2TD$=><2f5f<f)~f=e,ew,f)eDp\1\1e1n\8e1B\8e8-e8I.v--n=w.vf<<2=vIR)T(h(nR?f)fT=h=/f?IP-vR-^-nM.|r^-6R<^<2P<M=|\.z_\=|L^<,( ,*!n!x!j!g&!,,(&T&&,(!e&(J(=U8dB,DDD!?~D9q9yQ5,.--L&;&&"j""}-)S&"[,()J"o-&f)4\2o~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:"rlight2Z(d) d&Z&Z&l&0d"hZ$xd&T~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd: rrockatt1"'4 izU~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd?rrockatt2BD!BBPB#B1?kByBT~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd5?rrockatt35B:D!:B5B5BBB1:?z5B:BT~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd5?rrockatt45B:D!:B5B5BBB1:?z5B:BT~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Krrockatt5IPRP ROIOIOXO-RKhIMROV~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Krrockatt6TPZP ZOTOTObO+ZKgTM}ZOS~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:&rshotatt1-. ,,,,.&i)},J~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:!rshotatt2-2') )P))4!i&w)@~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd8Mrshotatt38m=o,=m 8mP8m>m7=la8lx=m`~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd8Mrshotatt48m=o,=m 8mP8m>m7=la8lx=m`~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd8Mrshotatt58_!=`$=_8_Q8_>_3=[e8\=_V~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd8Mrshotatt68_!=`$=_8_Q8_>_3=[e8\=_V~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxatt1PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mqraxatt2PYqP[w MYwRYqAPYqPPYRVwiPWq[TYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxatt3PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxatt4PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxatt5PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxatt6PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattb1PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mqraxattb2PYqP[w MYwRYqAPYqPPYRVwiPWq[TYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattb3PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattb4PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattb5PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattb6PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattc1PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattc2PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Moraxattc3PYoP[y MYyRYoAPYoPPYRVymPWoTYy3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattc4PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattc5PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattc6PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattd1PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattd2PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Moraxattd3PYoP[y MYyRYoAPYoPPYRVymPWoTYy3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattd4PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattd5PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"Upqd:Mmraxattd6PYmP[w MYwRYmAPYmPPYRVwmPWmTYw3~r'~j>~j2RdQjQW~RjۜQWۚQMw~Wf~W:Qr~MpH\֡H\Q\nHd֞Q\fHdQd-QdImY¡mY|Ynmhž|Yfmh|h-|hI=V=VRVn=lRVf=lRl-RlI:Yv=YIYn:YrIY6=hIh-:h:hĜIY^Ih>Ih,V Y*OnOOjOZUQO顊YYVUTUUYLOeUVJVlUfdp+r鞊rr!mrhqhyjxmm皃mfp*mTl1jf'bAb1bb \Yw\bS\Y\WWhd_\f\:fYpbf'bAb1bb \牅[w\}bN\X\ݚWhf`\f\:hYpbߝl$dAd1qdvdv\qVwq\~xdNx\Xq\xUhqlm`폧\f\:vm"UpqdQW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_rock.mdl000066400000000000000000004464441475442401000254650ustar00rootroot00000000000000IDPOw> *,>9`>Ɋ|sZBok@  rr  rr  !  rr"! ppppppp pppppp #! ppppppp ppppppp  ppppppppppp ppppppppp " pppppppppppppppppp  pppppppppp $#!! ppppppppppppppppppp pppppppp $#" ppppppppppppppppppppp  ppppppp  ppppppppppppppppppppppp pppp ppp " pppppppppppppppppppp  p pppp  $#"! pppppppppppp pppp ppppppppp $#" pppp ppppppppppppppppp ppppppppppp  pppppppppppp pppppppppppp pppppppp !! pppppppppppppppppppppppppp ##"! pppppppp ppppppppppp pppp ppppp ##" pppppppppppppppppppp  ppppppppppp ppppppppppppppp pppppppp ppppppp ! pppppp ppppppppppppppp  pp !pppppppp $#"! ppppppppppp pppp! ppppp p $#" ppp pppp pppppppp !pppp p   ppppppppppp ppp !pppp " ppp ppp ppp ppppp  ppppppp  $#"! p ppp pppppppppp  pppp ##! pppppprpp pp ppppp  rpp pppppppppp ppppppppp r! pppppppprrpppppp rpppppppp r$!! rrpppppprppppppppppp  rpppprp#  rpppppppppppppppppppp pppppppppp ppppppppprrpppppp rpppp pppppr !! rrpppppppppppppppppp  pppppppppp  #!! ppppppppppppp pppppppppp r pp pppp $! p pppppppppppppppp p ppppp  pppppppppppp p ppppppppp !! ppppppppppppppppp pppppppppp #"!! ppppppppppppp pppppp pppppp#! pp pppppppppppp pppppp ppppppppppppppp ppp pppppp$"! ppppppppprpp pppppp p pp pppppp rpp ppppppppppppppp  ppppp pp  ppppppppprrppppppp  ppppppp pp #!! rrppppppprpppppp  pppp pp #! rpppppppppppppp pp pp  pppppppprrpppppppppp pppp! rrppppppppppppppppp pppp$!! pppppppppppppppppppppp #  ppppppppppppppppppp pppp  ppppppppppppppppp pppppppppp p!! pppppppppppppppppp pppppppppppp p#!! ppppppppppppppp ppppppp $! pppppp pppppp pppppppp  p pppppppp p pppp ppp pppppp!! pp p pppprpppppppppppppp#"!! rpppppppppppppppppppppp#! pppppppppprrpp p pppppppppppp rrpp p pppp鮭rpppppppppp ppp rppppppp譮ppppppppppp p ppp#!! pppppppppprrpppppppppp pppppp$#" rrppppppppppppppppppp  pppp ppppppppp莮p pppppppppppppppp! p ppppppppppppppppp pppppppp$#"! pppppppppppppppppp ppppp##" ppppppppp pppppppppppppp p ppppppppppppppppp ppppppp! pppppppppppppppppp !ppppppp$#"! ppppppppppppppppp !pppppp$#" ppppppppppppppppppp ppppppp ppppppppppppppppppp ppppppp"! ppppppppp pppppppppp pppppp$#!! ppppppppppp ppppppppppppppp$#! p ppppppppppppppppppppp ppppppp! pppppppppppp濿pppppppppppppppp p p! pppppppppppppppppppppppp!p p p p$#"! ppppppppppp眿 pp ppp!ppppppp$#! pp ppp濿 pppppppppppppppppp ppppppppp眜 ppp ppp ppppppp" ppp ppp朿pp pp  !pppppp#""! pp pppppppp !pppppppp$#" pppppppp ppp pp  ppppppppp pp ppp ppppp ppppp" ppp ppppp ppp ppppp$""! ppp pp pppppp!  pppppp$#"! ppppppppp$#"  ppppppppp! pppppppp" p!ppppppp$#"! p!pppppppp$#!  pppppppp ppppp! pppppp$#"! ppppppp$#" p!ppppppp! ! pp p! !pp p$#"! ! ppp pp#""   ppp pp !  $#"! ##"  ! ! $#"! $#" !  "  $#"! $#" ! ! $#"!  p$#" p ! p$#"!  p$"" p! ! $""!  $#"  !  "  ##"! p$#" p!  "!  $#"!  $#" !  !  $#"!  $#" !  "  $#!! "! $"!! $#!  ! $#"!  ##" !  " $#"! p$#" p!  ! $#"!  $#"  ! !! $""! $#" ! ! #""! $#! ! " ! $#" $#!! " ! $#" $#"! !! ! ##" ##"! ! ! $#" $#"! " ! ##! $#"! ! ! $#" $#"! "! ! $#! $#"! !!  #  $#"! !!  $! $!! !! ! #! $"!! $"!   $!! #! ! ! !!! #  "!!!!! !!  $! #!r !! rr  #!  rr   rr ##" !sr #! ! srr " !! #! "!!r " "!! rs  "! ""! r  "! "!!! r " "! "!! rr """  !"!!! ""!! ""! ""! r ""!! "!! r ""!!rrrrrr "!!rrrrr """!rr """!rrr """!r r "!!sr "!!rr !! ""!r r "!s """!srr ""!rr """! sr "!!rr "!! r ""!!  "!!!  ""!! r "!! sr "!! sr ""!! r "!!!  ""!!  "!! r "!!rr """! sr ""!rr """!rr "!s ""!r r !! "!!rr "!!sr """!r  """!rrr ""!!r "!!rrrrr ""!!rrrrrr "!! r ""! r ""! r "" !""! "!!  "! ""!! rr  "! "!! r %# !! r &$! "!! rs $#"! !!r ! ! $#"! ! srr ! sr $#!! rr $#"! rr ! #rr  $#"! r ! #"! $#!! $#"#!!! $"!! ""!!  $#""! $#"! !! ! $#! $#"! " ! $#" $#"! " ! $#" $""! !! ! ##" #""! ! ! $#" $#!! " ! ##! $#"! ! ! $#" ##"! "! ! #! $#"! !! ! #"! D #$ D D  $ D $ ' *# '* *'# *  ' ' 1BC :Q ,I /Q B < AI< , 1 j 2 i D _ EaP ` " O P s m y m s zG) y3 z) m3s2@) j  |  | Z    E id  }6s ;  | 5}dsE j ; ' +# + '#                       !"#$%!#"&$'(&)#"%*&+$&*+&,))!#&"*%+*(',)'!'),!%"%$+$!',&(&$(-./012345-/425//.2467643031863-4754/68..-680.352.02321083-769:;<=9;:><?@>A;:=B>C<>BC>DAA9;>:B=CB@?DA?9?AD9=:=<C<9?D>@><@EFGHIJKLMNOPQRKSOTSPOUOIGVMWEXYZ[\P]STUKMYJR^IN\XGM_W^`SUaS`[ZVI\bHJ`L\]Q_RQ[FWX]HUIWa^`J^VZYb\L\NPIbJ]XMIONQKYY[QOUTRbKML]_FEMVYbLKQF_a]PW]a_EW^a`F[VUH`GFVaPS_^REGXRJbcdefghijkcejhkeedhjlmljifignlicjmkjelnddclnfdikhdfhihgfnicmlQ-rqaxrun1Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q-rqaxrun2Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q-rqaxrun3Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q-rqaxrun4Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q-rqaxrun5Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q-rqaxrun6Qzr Qzu QzuSzrAQzrQzzQxuhQxrSzu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Q5rockrun1S|S|,QzSzCQzWSz SxiSzsTz4[UWJJuEqI^M_*RF] b!Q9ޙ*ܐHsڞޡ#wݧayٔ{v5XGOC>l9eJ#5v9CJ==9GBC@rD:B7?aj(hiSjik2yOl}e#zv~}=9 {(={;qrWUؖ@=f@ow3x՟w B?Mک ڟ3|՘P{Qwꞓr@3}ةt pWxu}Jwu{h]*4!Q,{rockrun2S|S|,QzSzCQzWSz SxiSzsTz4xV~tR|R{VtEtxB~q|E{YBnR.EDRV#E7Ԑ)ԊH}ՙԚ-ա\ԏ}vl,:G:,m,c:%},},::>,7:1~111o0e0Z[L[[Q[[[0rOrmr^-r}r>r72+1|0iTύU0_1diFϚi111ϡ1ϖ4ϓ┝hUFϣi h{w}Vwtyr}Y.D #Q rockrun3S|S|,QzSzCQzWSz SxiSzsTz4uC'p@x=Jm5o0t1Y|'j55*d}9;/y-~mo5K2woZzrywoHs&|y|\2hom(F os%x|xnb}[8=>:V;>8z?\L2uPyI|]G79pW 4aauDhQ`U_k cm h56k8i dL8NM9_[6fx@_x@Q(|Jutszp[fyp9edw w/k~QЭrockrun5S|S|,QzSzCQzWSz SxiSzsTz4tLqIwGVo=q8ru;Y1lB55eC G%8~63HƠ/Ĩ[Ė{kw!*G{/k\'/t"{}w/&CE,!~ "ne[ELIHNG-IETņJ͈G{fe•pytnYyLyNzDzz}zs1%H6xаstand2Lw Lx HwLwCIwQLwLtmLtZOw3m]}Lh_}NoVeaVcNrhMZcSo\1hShdmd%a[icB|jus]LXQ>TɅVψG|feĔpyunYxLxNyDyyy[1/H:xӮstand3Lw Lx HwLwCIwQLwLtmLtZOw3m_}Lh`}QoWecVdPriNZdUo]1iShemd%c\TˆJ҈G|heƕpyuoTxLxNyDyyry\1%H8xϰstand4Lw Lx HwLwCIwQLwLtmLtZOw3l]}Lg_}NmWeaVcNrhMZcUm\1hSgeld/a\TDžVΈG{fe”pyunYxLxNyDyyy[1%H8y˱stand5Lw Lx HwLwCIwQLwLtmLtZOw3l]~Lg_~QmVeaVaNgMZaUm\1gSgeld%a\aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd2PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd3PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd4PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd5PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd6PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd7PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd8PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd9PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd10PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd11PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{O-qaxstnd12PzP|,OxQxDPxPPxjPwhPxsQx7dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain1Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain2Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain3Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain4Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain5Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-qaxpain6Lz Lz IzLzCIzRLz2Lx8LxZLz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{OEpain1P|P|$OzPz?PzPzPxhPzQz4ws&qpymAoeq_wa^u_}m1{a8up{s-se0>񤞖-XaG|y}oJXRKsXGtJy}EbwX-ePgP~h]R4Ek]oRsQĂqQyNÊ{LpxMZs=yxtV{xxyt1XKGyb-tw~x4{ .kSqNwR_ByJe{Ll:訕tPlS}Iapain25|5| 5z7z>5z5z7xm5zs7z.PrMmQTpLP`[U_cXeCOZOkQ_}HN\X/`L;EJKEMEjPH]TIćXJ9WJeLp%DmKpHAk@jHoD_I(@M=mO7885~x4G2K;0 (#MHUL^?z8VA>1=]P4[NK1!ز1AzQHLGz)'$/ )ݱV#O뵝M=?1/{ս{epain35|5| 4z7zC5zP5z5xh5zr7z4QuOoPWt+TdXXbc[iCSXPj U_xLN_X-cL;IIPCuQDjTG^XH\J:[JDMo#EjLoGDhChIkE_H'@M=~mO789~[7yx4E2K;0߿!QHYM^@xW7V?L,ܼ+`Q?_PL~1Ҷ0WCwUGQEz$ ) $׵VM⺜O=<1-{{=t{3ÄH}V31P8L5];c=B4l3 7<+-0w/>lpain4@|@|*?z@z??z@z<@xi@zw@z4YrWkP_oLY`X_]cadC[X[j]]}QMgV/kH;PJWDuXDjYG]_HćcH9aHeYo%PmWpIOjLjUnP`X&MMLm\7HDrC}@U/Y;?4/<-WG_I^KzGVP>C=gM4eMX14ں@Oz\GWEz='8A ;޶V7M0[>O1={3ĒIx{DńS}VDģAQI£LDXIcMBElE H<=@@vEI~upain5G|~G|%EzGz~4Gz~Gz GxmGz~rHz4iseooo>ebi_Zobfh_lo2lb:dohsdb{t:t/tL`h_i]tbiG`hj_iI]uWLiWgIkuIdgW]I]I|]WtW0tI\WcNdNdN[kNÊmM8lMbmx*dxlxJdxcxkxi]uLiGgkudg]\|]t0t\gcp/aNhM[chTsBsCqMEpNpeiZofhlǰ2l:dǰh˰d{EE~pain6G|~G|%EzGz~4Gz~Gz GxmGz~rHz4ws&qpymAoeq_wa^u_}m1{a8up{s-se0>񤞖-XaG|y}oJXRKsXGtJy}EbwX-ePgP~h]R4Ek]oRsQĂqQyNÊ{LpxMZs=yxtV{xxyt1XKGyb-tw~x4{ .kSqNwR_ByJe{Ll:訕tPlS}IaG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{G-{qaxdeth2G|{G|$GzHz{CGz{GzHxhGz{wHz3dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{G-{qaxdeth3G|{G|$GzHz{CGz{GzHxhGz{wHz3dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{G-Wqaxdeth4G|WG|\$Gz\HzWCGzWGzbHx\iGzWrHz\3dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{E-%qaxdeth5E|%E|) Ez)Gz%>Ez%Ez/Gx)iEz%sGz).dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{D-qaxdeth6E|E|$DzEzCDzEz ExzEzwGz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{D-qaxdeth7E|E|$DzEzCDzEz ExzEzwGz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{D-qaxdeth8E|E|$DzEzCDzEz ExzEzwGz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{D-qaxdeth9E|E|$DzEzCDzEz ExzEzwGz4dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{AvD|deatha1C|C|$AzDzCCzPCz CxhCzsDz4CvYBvuCvdBv}CvCvnCyCy(Cy.ByCyOByDz/DzLDyeByCzGBzCxjDyCx\By|Cz BzCxjDyfCx]C|Dy:C|OAy|A{AyD{?D{/A{B|B|B{C|-C|0C{C|AB{C{aB|B|C|&CxjDycCx[C| Dy:C|OAy|A{AyD{?D{/A{C{BzCzABzCyBytCyhDyoDy6Cy:Cz2C{)BytBytC{ C|BzCy^C{ D{+CyhCyqByCy6D{)B{B{B{C{ CyhCvYBvuCveBv}CvCvnCz CzICz.BzCzOBzAvI|deatha2H|H|,GzHzCGzHzHxhHzwIz4CvYBvuCvdBv}CvCvnCyCy(Cy.ByCyOByDz/DzLDyeByCzGBzCxjDyCx\By|Cz BzCxjDyfCx]C|Dy:C|OAy|A{AyD{?D{/A{B|B|B{C|-C|0C{C|AB{C{aB|B|C|&CxjDycCx[C| Dy:C|OAy|A{AyD{?D{/A{C{BzCzABzCyBytCyhDyoDy6Cy:Cz2C{)BytBytC{ C|BzCy^C{ D{+CyhCyqByCy6D{)B{B{B{C{ CyhCvYBvuCveBv}CvCvnCz CzICz.BzCzOBzAvP|deatha3O|O|,LzOz4OzOz1OxiOzrPz4CvYBvuCvdBv}CvCvnCyCy(Cy.ByCyOByDz/DzLDyeByCzGBzCxjDyCx\By|Cz BzCxjDyfCx]C|Dy:C|OAy|A{AyD{?D{/A{B|B|B{C|-C|0C{C|AB{C{aB|B|C|&CxjDycCx[C| Dy:C|OAy|A{AyD{?D{/A{C{BzCzABzCyBytCyhDyoDy6Cy:Cz2C{)BytBytC{ C|BzCy^C{ D{+CyhCyqByCy6D{)B{B{B{C{ CyhCvYBvuCveBv}CvCvnCz CzICz.BzCzOBzAvxS}deatha4Q|zQ|~ Pz~SzzCQzzPQzQx~hQzzrSz~4CvYBvuCvdBv}CvCvnCzCz(Cz.BzCzOBzDz~/DzyLDyyeByyC{yGBzyCy~jDy~Cyy\By~|C{~ Bz~CxjDyfCy]C|Dy:C|OAy|A{AyD{?D{/A{B|B}B{C}-C|0C{C|AB{C{aB}B|C}&CyjDycCy[C| Dy:C|OAy|A{AyD{?D{/A{C{xB{xC{xABzCyBztCy~hDy~oDzy6Cz:C{2C{)BzytBy~tC| C|B{Czx^C|y D{y+CyyhCyxqBzxCz6D{~)B{~B{yB{C|~ CyhCw|YBw|uCw|eBw}}Cw}Cw}nCz} Cz|ICz}.Bz|Cz|OBz}AvhS}vdeatha5Q|iQ|n PznSziCQziPQztQxnhQzirSzn4CvsYBvsuCvsdBvt}CvtCvtnCztCzs(Czt.BzsCzsOBztDzn/DziLDyieByiC{iGBziCynjDynCyi\Byn|C{n BznCxvjDyufCyu]C|vDyv:C|uOAyv|A{vAyuD{u?D{v/A{uB|uB}uB{uC}u-C|u0C{uC|rAB{rC{raB}rB|rC}r&CypjDyocCyo[C|p Dyp:C|oOAyp|A{pAyoD{o?D{p/A{oC{hB{hC{hABzuCyuBzqtCymhDymoDzi6Czu:C{u2C{q)BzitBymtC|q C|uB{uCzh^C|i D{i+CyihCyhqBzhCzq6D{m)B{mB{iB{qC|m CyqhCwlYBwluCwleBwm}CwmCwmnCzm CzlICzm.BzlCzlOBzmAvXS}fdeatha6Q|XQ|^ Pz^SzXCQzXPQzdQx^hQzXrSz^4CvcYBvcuCvcdBvd}CveCvdnCzeCzc(Czd.BzcCzcOBzdD{^/D{YLDyYeByYC{YGB{YCy^jDy^CyY\By^|C{^ B{^CyfjDzefCye]C}fDzf:C}eOAzf|A{fAzeD{e?D{f/A{eB|fB}fB{fC}f-C|f0C{fC|cAB{cC{caB}cB|cC}c&CyajDz_cCy`[C}a Dza:C}_OAza|A{aAz_D{_?D{a/A{_C{XB{XC{XABzfCzfBzbtCy^hDz^oDzZ6Czf:C{f2C{b)BzZtBz^tC|b C|fB{fCzX^C|Z D{Z+CyZhCzXqBzXCzb6D{^)B{^B{ZB{bC|^ CybhCw\YBw\uCw\eBw^}Cw^Cw^nC{^ Cz\IC{].Bz\Cz\OBz^Av+X}9deatha7W|/W|3,Uz3Wz/4Wz/Wz8 Wx3iWz/rXz34Cv6YBv6uCv6dBv7}Cv7Cv7nCz7Cz6(Cz7.Bz6Cz6OBz7Dz1/Dz,LDy,eBy,C{,GBz,Cy1jDy1Cy,\By1|C{1 Bz1Cx9jDy8fCy8]C|9Dy9:C|8OAy9|A{9Ay8D{8?D{9/A{8B|8B}8B{8C}8-C|90C{9C|5AB{5C{5aB}5B|5C}5&Cy3jDy2cCy2[C|3 Dy3:C|2OAy3|A{3Ay2D{2?D{3/A{2C{+B{+C{+ABz8Cy9Bz4tCy1hDy1oDz,6Cz9:C{82C{4)Bz,tBy1tC|4 C|8B{8Cz+^C|, D{,+Cy,hCy+qBz+Cz46D{1)B{1B{,B{4C|1 Cy4hCw/YBw/uCw/eBw0}Cw0Cw0nCz0 Cz/ICz0.Bz/Cz/OBz0AvS|"deatha8Q|Q|$PzQzCPzQz QxzQzwSz4CvYBvuCvdBv }Cv Cv nCy Cy(Cy .ByCyOBy Dz/DzLDyeByCzGBzCxjDyCx\By|Cz BzCx"jDy fCx ]C|"Dy":C| OAy"|A{"Ay D{ ?D{"/A{ B|!B|!B{!C|!-C|!0C{!C|AB{C{aB|B|C|&CxjDycCx| Dy:C|OAy|A{AyD{?D{/A{C{BzCzABz!Cy!BytCyhDyoDy6Cy!:Cz!2C{)BytBytC{ C|!Bz!Cy^C{ D{+CyhCyqByCy6D{)B{B{B{C{ CyhCvYBvuCveBv}CvCvnCz CzICz.BzCzOBzAvS|deatha9Q|Q|'PzQz?QzQzQxsQzSz?CvYBvuCvdBv}CvCvnCyCy(Cy.ByCyOByDz/DzLDyeByCzGBzCxjDyCx\By|Cz BzCxjDyfCx]C|Dy:C|OAy|A{AyD{?D{/A{B|B|B{C|-C|0C{C|AB{C{aB|B|C|&CxjDycCx[C| Dy:C|OAy|A{AyD{?D{/A{C{BzCzABzCyBytCyhDyoDy6Cy:Cz2C{)BytBytC{ C|BzCy^C{ D{+CyhCyqByCy6D{)B{B{B{C{ CyhCvYBvuCveBv}CvCvnCz CzICz.BzCzOBzAv S}deatha10Q| Q|$PzQz ?Qz QzQxzQz uSz4CvYBvuCvdBv}CvCvnCzCz(Cz.BzCzOBzDz/Dz LDy eBy C{ GBz CyjDyCy \By|C{ BzCxjDyfCy]C|Dy:C|OAy|A{AyD{?D{/A{B|B}B{C}-C|0C{C|AB{C{aB}B|C}&CyjDycCy[C| Dy:C|OAy|A{AyD{?D{/A{C{ B{ C{ ABzCyBztCyhDyoDz 6Cz:C{2C{)Bz tBytC| C|B{Cz ^C| D{ +Cy hCy qBz Cz6D{)B{B{ B{C| CyhCw YBw uCw eBw}CwCwnCz Cz ICz.Bz Cz OBzAvS}deatha11Q|Q|$PzQz4QzQzQxzQzuSz4CvYBvuCvdBv}CvCvnCzCz(Cz.BzCzOBzDz/Dz LDy eBy C{ GBz CyjDyCy \By|C{ BzCxjDyfCy]C|Dy:C|OAy|A{AyD{?D{/A{B|B}B{C}-C|0C{C|AB{C{aB}B|C}&CyjDycCy[C| Dy:C|OAy|A{AyD{?D{/A{C{ B{ C{ ABzCyBztCyhDyoDz 6Cz:C{2C{)Bz tBytC| C|B{Cz ^C| D{ +Cy hCy qBz Cz6D{)B{B{ B{C| CyhCw YBw uCw eBw}CwCwnCz Cz ICz.Bz Cz OBzQvyU}deathb1S|zS|$QzTzzCSzzPSz TxiSzzsUz3SvYRvuSvdRv}SvSvnSzSz(Sz.RzSzORzTz/TzzLTyzeRyzS{zGRzzSyjTySyz\Ry|S{ RzSxjTyfSy]S|Ty:S|ORy|R{RyT{?T{/R{R|R}R{S}-T|0S{T|AR{S{aR}R|S}&SyjTycSy[S| Ty:S|ORy|R{RyT{?T{/R{S{yR{yT{yARzSyRztSyhTyoTz{6Tz:T{2T{)Rz{tRytS| S|R{Tzy^S|{ T{{+Sy{hSyyqRzyTz6T{)R{R{{R{S| SyhSw}YRw}uSw}eRw~}Sw~Sw~nSz~ Sz}ISz~.Rz}Sz}ORz~;vyT}deathb2?|yM?|~$;z~@zyB?zyR?z ?x~h?zygAz~4SvYRvuSvdRv}SvSvnSzSz(Sz.RzSzORzTz/TzzLTyzeRyzS{zGRzzSyjTySyz\Ry|S{ RzSxjTyfSy]S|Ty:S|ORy|R{RyT{?T{/R{R|R}R{S}-T|0S{T|AR{S{aR}R|S}&SyjTycSy[S| Ty:S|ORy|R{RyT{?T{/R{S{yR{yT{yARzSyRztSyhTyoTz{6Tz:T{2T{)Rz{tRytS| S|R{Tzy^S|{ T{{+Sy{hSyyqRzyTz6T{)R{R{{R{S| SyhSw}YRw}uSw}eRw~}Sw~Sw~nSz~ Sz}ISz~.Rz}Sz}ORz~-vuT}deathb30|u0|{,-z{0zuC-zuR0z<0x{i0zus1z{4SvYRvuSvdRv}SvSvnSzSz(Sz.RzSzORzT{{/T{vLTyveRyuS{vGR{uSy{jTy{Syv\Ry{|S{{ R{{SyjTzfSy]S}Tz:S}ORz|R{RzT{?T{/R{R|R}R{S}-T|0S{T|AR{S{aR}R|S}&Sy}jTz|cSy|[S}} Tz}:S}|ORz}|R{}Rz|T{|?T{}/R{|S{uR{uT{uARzSzRz~tSyzhTzzoTzv6Tz:T{2T{~)RzvtRzztS|~ S|R{Tzu^S|v T{v+SyvhSzuqRzuTz~6T{z)R{zR{vR{~S|z Sy~hSwyYRwyuSwyeRwz}SwzSwznS{z SzyIS{z.RzySzyORzz+vST}bdeathb4-|U-|[$+z[-zUC+zUW-zb-x[h-zUs0z[4Sv^YRv^uSv^dRv_}Sv`Sv_nSz`Sz^(Sz_.Rz^Sz^ORz_T{Y/T{TLTyTeRyTS{TGR{TSyYjTyYSyT\RyY|S{Y R{YSyajTz`fSy`]S}aTza:S}`ORza|R{aRz`T{`?T{a/R{`R|aR}aR{aS}a-T|a0S{aT|^AR{^S{^aR}^R|^S}^&Sy\jTz[cSy[[S}\ Tz\:S}[ORz\|R{\Rz[T{[?T{\/R{[S{SR{ST{SARzaSzaRz]tSyYhTzYoTzU6Tza:T{a2T{])RzUtRzYtS|] S|aR{aTzS^S|U T{U+SyUhSzSqRzSTz]6T{Y)R{YR{UR{]S|Y Sy]hSwWYRwXuSwXeRwY}SwYSwYnS{Y SzXIS{Y.RzXSzWORzY+u)T|7deathb5-|+-|1 +z10z+B-z+P-z7-x1h-z+s0z15Su4YRu4uSu4dRu5}Su5Su5nSy5Sy4(Sy5.Ry4Sy4ORy5Tz//Tz*LTx*eRx*Sz*GRz*Sx/jTx/Sx*\Rx/|Sz/ Rz/Sx7jTy6fSx6]S|7Ty7:S|6ORy7|Rz7Ry6Tz6?Tz7/R{6R{7R|7R{7S|7-T{70S{7T{3AR{3S{3aR|3R{3S|3&Sx2jTy0cSx0[S|2 Ty2:S|0ORy2|R{2Ry0T{0?T{2/R{0S{)Rz)Tz)ARz7Sy7Ry2tSx/hTy/oTy+6Ty7:Tz72Tz2)Ry+tRy/tS{2 S{7Rz7Ty)^S{+ Tz++Sx+hSy)qRy)Ty26Tz/)Rz/Rz+Rz2S{/ Sx2hSv-YRv-uSv-eRv.}Sv.Sv.nSz. Sz-ISz..Rz-Sz-ORz.-vT|deathb60|0|,-z0zC-zR0z10xm0zs1z4SvYRvuSvdRv}SvSvnSySy(Sy.RySyORyTz/TzLTyeRySzGRzSxjTySx\Ry|Sz RzSxjTyfSx]S|Ty:S|ORy|R{RyT{?T{/R{R|R|R{S|-T|0S{T|AR{S{aR|R|S|&SxjTycSx[S| Ty:S|ORy|R{RyT{?T{/R{S{RzTzARzSyRytSyhTyoTy6Ty:Tz2T{)RytRytS{ S|RzTy^S{ T{+SyhSyqRyTy6T{)R{R{R{S{ SyhSvYRvuSveRv}SvSvnSz SzISz.RzSzORz-vT|deathb70|0|,-z0zC-zR0z10xm0zs1z4SvYRvuSvdRv}SvSvnSySy(Sy.RySyORyTz/TzLTyeRySzGRzSxjTySx\Ry|Sz RzSxjTyfSx]S|Ty:S|ORy|R{RyT{?T{/R{R|R|R{S|-T|0S{T|AR{S{aR|R|S|&SxjTycSx[S| Ty:S|ORy|R{RyT{?T{/R{S{RzTzARzSyRytSyhTyoTy6Ty:Tz2T{)RytRytS{ S|RzTy^S{ T{+SyhSyqRyTy6T{)R{R{R{S{ SyhSvYRvuSveRv}SvSvnSz SzISz.RzSzORz-vT|deathb80|0|,-z0zC-zR0z10xm0zs1z4SvYRvuSvdRv}SvSvnSySy(Sy.RySyORyTz/TzLTyeRySzGRzSxjTySx\Ry|Sz RzSxjTyfSx]S|Ty:S|ORy|R{RyT{?T{/R{R|R|R{S|-T|0S{T|AR{S{aR|R|S|&SxjTycSx[S| Ty:S|ORy|R{RyT{?T{/R{S{RzTzARzSyRytSyhTyoTy6Ty:Tz2T{)RytRytS{ S|RzTy^S{ T{+SyhSyqRyTy6T{)R{R{R{S{ SyhSvYRvuSveRv}SvSvnSz SzISz.RzSzORz-vT|deathb90|0|,-z0zC-zR0z10xm0zs1z4SvYRvuSvdRv}SvSvnSySy(Sy.RySyORyTz/TzLTyeRySzGRzSxjTySx\Ry|Sz RzSxjTyfSx]S|Ty:S|ORy|R{RyT{?T{/R{R|R|R{S|-T|0S{T|AR{S{aR|R|S|&SxjTycSx[S| Ty:S|ORy|R{RyT{?T{/R{S{RzTzARzSyRytSyhTyoTy6Ty:Tz2T{)RytRytS{ S|RzTy^S{ T{+SyhSyqRyTy6T{)R{R{R{S{ SyhSvYRvuSveRv}SvSvnSz SzISz.RzSzORzUt{Xzdeathc1Wz{Wz,UxWx{CUx{WWxWwhWx{sXx7WtYVtuWtdVt}WtWtnWwWw(Ww.VwWwOVwXx/Xx|LXw|eVw|Wx|GVx|WvjXwWv|\Vw|Wx VxWvjXwfWv]WzXw:WzOUw|UyUwXy?Xy/UyVzVzVyWz-Wz0WyWzAVyWyaVzVzWz&WvjXwcWv[Wz Xw:WzOUw|UyUwXy?Xy/UyWy{Vx{Wx{AVxWwVwtWwhXwoXw|6Wx:Wx2Wy)Vw|tVwtWz WzVxWx{^Wz| Xy|+Ww|hWw{qVx{Ww6Xy)VyVy|VyWz WwhWuYVuuWueVu}WtWtnWx WxIWx.VxWxOVxUtX{deathc2WzWz,UxWxCUxWWxWwhWxsXx7WtYVtuWtdVt}WtWtnWxWx(Wx.VxWxOVxXx/XxLXweVwWyGVyWwjXwWw\Vw|Wy VxWwjXwfWw]W{Xw:W{OUw|UyUwXy?Xy/UyVzV{VyW{-Wz0WyWzAVyWyaV{VzW{&WwjXwcWw[W{ Xw:W{OUw|UyUwXy?Xy/UyWyVyWyAVxWwVxtWwhXwoXx6Wx:Wy2Wy)VxtVwtWz WzVyWx^Wz Xy+WwhWwqVxWx6Xy)VyVyVyWz WwhWuYVuuWueVu}WuWunWx WxIWx.VxWxOVxUta{deathc3`z`z$_xaxD`xP`xj`wh`xsax7WtYVtuWtdVt}WtWtnWxWx(Wx.VxWxOVxXy/XyLXxeVxWyGVyWwjXwWw\Vw|Wy VyWwjXxfWw]W{Xx:W{OUx|UyUxXy?Xy/UzV{V{VzW{-W{0WzW{AVzWzaV{VzW{&WwjXxcWw[W{ Xx:W{OUx|UzUxXz?Xz/UzWzVyWyAVyWxVxtWxhXxoXx6Wx:Wy2Wy)VxtVxtWz WzVyWx^Wz Xy+WxhWxqVxWx6Xy)VyVyVyWz WxhWuYVuuWueVu}WuWunWy WyIWy.VyWyOVyUug{deathc4dzdz cxgxBdxdx|dwhdxsgx9WuYVuuWudVu}WuWunWxWx(Wx.VxWxOVxXy/XyLXxeVxWyGVyWwjXxWw\Vx|Wy VyWwjXxfWw]W{Xx:W{OUx|UzUxXz?Xz/UzV{V{VzW{-W{0WzW{AVzWzaV{V{W{&WwjXxcWw[W{ Xx:W{OUx|UzUxXz?Xz/UzWzVyWyAVyWxVxtWxhXxoXx6Wx:Wy2Wz)VxtVxtWz W{VyWx^Wz Xz+WxhWxqVxWx6Xz)VzVzVzWz WxhWuYVuuWueVu}WuWunWy WyIWy.VyWyOVyUtxg{deathc5dzydz~ cx~gxyBdxyPdx|dw~hdxysgx~9WtYVtuWtdVt}WtWtnWxWx(Wx.VxWxOVxXy~/XyyLXxyeVxyWyyGVyyWw~jXw~Wwy\Vw~|Wy~ Vy~WwjXxfWw]W{Xx:W{OUx|UyUxXy?Xy/UzV{V{VzW{-W{0WzW{AVzWzaV{VzW{&WwjXxcWw[W{ Xx:W{OUx|UzUxXz?Xz/UzWzxVyxWyxAVyWxVxtWx~hXx~oXxz6Wx:Wy2Wy)VxztVx~tWz WzVyWxx^Wzz Xyz+WxzhWxxqVxxWx6Xy~)Vy~VyzVyWz~ WxhWu|YVu}uWu}eVu~}Wu~Wu~nWy~ Wy}IWy~.Vy}Wy|OVy~Utag{pdeathc6dzbdzi cxigxbBdxbPdxp|dwihdxbsgxi9WtlYVtluWtldVtm}WtnWtmnWxnWxl(Wxm.VxlWxlOVxmXxg/XxbLXwbeVwbWybGVybWwgjXwgWwb\Vwg|Wyg VxgWwojXwnfWwn]W{oXwo:W{nOUwo|UyoUwnXyn?Xyo/UynVzoV{oVyoW{o-Wzo0WyoWzlAVylWylaV{lVzlW{l&WwjjXwhcWwi[W{j Xwj:W{hOUwj|UyjUwhXyh?Xyj/UyhWyaVyaWyaAVxoWwoVxktWwghXwgoXxc6Wxo:Wyo2Wyk)VxctVwgtWzk WzoVyoWxa^Wzc Xyc+WwchWwaqVxaWxk6Xyg)VygVycVykWzg WwkhWueYVueuWueeVug}WugWugnWxg WxeIWxf.VxeWxeOVxgUtMg{\deathc7dzNdzV cxVgxNBdxNdx\|dwVhdxNsgxV9WtXYVtXuWtXdVtY}WtZWtYnWxZWxX(WxY.VxXWxXOVxYXyS/XyOLXxOeVxNWyOGVyNWwSjXwSWwO\VwS|WyS VySWw[jXxZfWwZ]W{[Xx[:W{ZOUx[|Uy[UxZXyZ?Xy[/UzZV{[V{[Vz[W{[-W{[0Wz[W{XAVzXWzXaV{XVzXW{X&WwVjXxUcWwU[W{V XxV:W{UOUxV|UzVUxUXzU?XzV/UzUWzMVyMWyMAVy[Wx[VxWtWxShXxSoXxO6Wx[:Wy[2WyW)VxOtVxStWzW Wz[Vy[WxM^WzO XyO+WxOhWxMqVxMWxW6XyS)VySVyOVyWWzS WxWhWuQYVuRuWuReVuS}WuSWuSnWyS WyRIWyS.VyRWyQOVySUt8g{Hdeathc8dz8dz@ cx@gx8Bdx8dxH|dw@hdx8sgx@9WtCYVtCuWtCdVtD}WtEWtDnWxEWxC(WxD.VxCWxCOVxDXy>/Xy9LXx9eVx9Wy9GVy9Ww>jXw>Ww9\Vw>|Wy> Vy>WwFjXxEfWwE]W{FXxF:W{EOUxF|UyFUxEXyE?XyF/UzEV{FV{FVzFW{F-W{F0WzFW{CAVzCWzCaV{CVzCW{C&WwAjXx@cWw@[W{A XxA:W{@OUxA|UzAUx@Xz@?XzA/Uz@Wz8Vy8Wy8AVyFWxFVxBtWx>hXx>oXx:6WxF:WyF2WyB)Vx:tVx>tWzB WzFVyFWx8^Wz: Xy:+Wx:hWx8qVx8WxB6Xy>)Vy>Vy:VyBWz> WxBhWu}Wu>Wu>nWy> Wy=IWy>.Vy=WyUt$g{2deathc9dz%dz, cx,gx%Bdx%Pdx2|dw,hdx%sgx,9Wt/YVt/uWt/dVt0}Wt0Wt0nWx0Wx/(Wx0.Vx/Wx/OVx0Xy*/Xy%LXx%eVx%Wy%GVy%Ww*jXw*Ww%\Vw*|Wy* Vy*Ww2jXx1fWw1]W{2Xx2:W{1OUx2|Uy2Ux1Xy1?Xy2/Uz1V{2V{2Vz2W{2-W{20Wz2W{.AVz.Wz.aV{.Vz.W{.&Ww-jXx+cWw+[W{- Xx-:W{+OUx-|Uz-Ux+Xz+?Xz-/Uz+Wz$Vy$Wy$AVy2Wx2Vx-tWx*hXx*oXx%6Wx2:Wy22Wy-)Vx%tVx*tWz- Wz2Vy2Wx$^Wz% Xy%+Wx%hWx$qVx$Wx-6Xy*)Vy*Vy%Vy-Wz* Wx-hWu(YVu(uWu(eVu)}Wu)Wu)nWy) Wy(IWy).Vy(Wy(OVy)Utg{)deathc10dzdz cx gxBdxPdx)|dw hdxsgx 9Wt#YVt$uWt$dVt%}Wt%Wt%nWx%Wx$(Wx%.Vx$Wx#OVx%Xy/XyLXxeVxWyGVyWwjXwWw\Vw|Wy VyWw'jXx&fWw&]W{'Xx':W{&OUx'|Uy'Ux&Xy&?Xy'/Uz&V{&V{&Vz&W{&-W{&0Wz&W{#AVz#Wz#aV{#Vz#W{#&Ww!jXx cWw [W{! Xx!:W{ OUx!|Uz!Ux Xz ?Xz!/Uz WzVyWyAVy&Wx&Vx"tWxhXxoXx6Wx&:Wy&2Wy")VxtVxtWz" Wz&Vy&Wx^Wz Xy+WxhWxqVxWx"6Xy)VyVyVy"Wz Wx"hWuYVuuWueVu}WuWunWy WyIWy.VyWyOVyUug{deathc11dzdz cxgxBdxPdx|dwhdxsgx9WuYVuuWudVu}WuWunWxWx(Wx.VxWxOVxXy/XyLXxeVxWyGVyWwjXxWw\Vx|Wy VyWwjXxfWw]W{Xx:W{OUx|UzUxXz?Xz/UzV{V{VzW{-W{0WzW{AVzWzaV{V{W{&WwjXxcWw[W{ Xx:W{OUx|UzUxXz?Xz/UzWzVyWyAVyWxVxtWxhXxoXx6Wx:Wy2Wz)VxtVxtWz W{VyWx^Wz Xz+WxhWxqVxWx6Xz)VzVzVzWz WxhWuYVuuWueVu}WuWunWy WyIWy.VyWyOVyUug|deathc12dzdz cx gxBdxPdx|dw hdxsgx 9WuYVuuWudVu}WuWunWyWy(Wy.VyWyOVyXy /XyLXxeVxWzGVyWx jXx Wx\Vx |Wz Vy WwjXxfWx]W{Xx:W{OUx|UzUxXz?Xz/UzV{V|VzW|-W{0WzW{AVzWzaV|V{W|&WxjXx cWx [W{ Xx:W{ OUx|UzUx Xz ?Xz/Uz WzVzWzAVyWxVytWx hXx oXy6Wy:Wz2Wz)VytVx tW{ W{VzWy^W{ Xz+WxhWxqVyWy6Xz )Vz VzVzW{ WxhWv YVv uWv eVv }Wv Wv nWy Wy IWy .Vy Wy OVy Uug|deathc13dzdz cx gxBdxPdx|dw hdxsgx 9WuYVuuWudVu}WuWunWyWy(Wy.VyWyOVyXy /XyLXxeVxWzGVyWx jXx Wx\Vx |Wz Vy WwjXxfWx]W{Xx:W{OUx|UzUxXz?Xz/UzV{V|VzW|-W{0WzW{AVzWzaV|V{W|&WxjXx cWx [W{ Xx:W{ OUx|UzUx Xz ?Xz/Uz WzVzWzAVyWxVytWx hXx oXy6Wy:Wz2Wz)VytVx tW{ W{VzWy^W{ Xz+WxhWxqVyWy6Xz )Vz VzVzW{ WxhWv YVv uWv eVv }Wv Wv nWy Wy IWy .Vy Wy OVy Uug|deathc14dzdz cx gxBdxPdx|dw hdxsgx 9WuYVuuWudVu}WuWunWyWy(Wy.VyWyOVyXy /XyLXxeVxWzGVyWx jXx Wx\Vx |Wz Vy WwjXxfWx]W{Xx:W{OUx|UzUxXz?Xz/UzV{V|VzW|-W{0WzW{AVzWzaV|V{W|&WxjXx cWx [W{ Xx:W{ OUx|UzUx Xz ?Xz/Uz WzVzWzAVyWxVytWx hXx oXy6Wy:Wz2Wz)VytVx tW{ W{VzWy^W{ Xz+WxhWxqVyWy6Xz )Vz VzVzW{ WxhWv YVv uWv eVv }Wv Wv nWy Wy IWy .Vy Wy OVy Uug|deathc15dzdz cx gxBdxPdx|dw hdxsgx 9WuYVuuWudVu}WuWunWyWy(Wy.VyWyOVyXy /XyLXxeVxWzGVyWx jXx Wx\Vx |Wz Vy WwjXxfWx]W{Xx:W{OUx|UzUxXz?Xz/UzV{V|VzW|-W{0WzW{AVzWzaV|V{W|&WxjXx cWx [W{ Xx:W{ OUx|UzUx Xz ?Xz/Uz WzVzWzAVyWxVytWx hXx oXy6Wy:Wz2Wz)VytVx tW{ W{VzWy^W{ Xz+WxhWxqVyWy6Xz )Vz VzVzW{ WxhWv YVv uWv eVv }Wv Wv nWy Wy IWy .Vy Wy OVy AxgD~udeathd1C|hC~l'A|lD|hCC|hPC|t1CzlmCzh[D|l4BxrYBxruCxrdBxs}BxtCxsnB{tC{r(C{s.B{rB{rOB{sD|m/D|hLD{heA{hB|hGA|hBzmjD{mBzh\A{m|B|m A|mBzujD{tfBzt]B~uD{u:B~tOA{u|A}uA{tD}t?D}u/A}tB~uB~uB}uC~u-C~u0C}uC~rAB}rC}raB~rB}rC~r&BzpjD{ocBzo[B~p D{p:B~oOA{p|A}pA{oD}o?D}p/A}oB}gB|gC|gAB|uB{uB{qtB{mhC{moC{i6C{u:C|u2C|q)B{itB{mtB}q B}uB|uC{g^B}i C}i+B{ihB{gqB{gC{q6C|m)B|mB}iB|qB}m B{qhBxkYBxluCxleBxm}BxmCxmnB|m C|lIC|m.B|lB|kOB|mAxgD~udeathd2C|hC~l'A|lD|hCC|hPC|t1CzlmCzh[D|l4BxrYBxruCxrdBxs}BxtCxsnB{tC{r(C{s.B{rB{rOB{sD|m/D|hLD{heA{hB|hGA|hBzmjD{mBzh\A{m|B|m A|mBzujD{tfBzt]B~uD{u:B~tOA{u|A}uA{tD}t?D}u/A}tB~uB~uB}uC~u-C~u0C}uC~rAB}rC}raB~rB}rC~r&BzpjD{ocBzo[B~p D{p:B~oOA{p|A}pA{oD}o?D}p/A}oB}gB|gC|gAB|uB{uB{qtB{mhC{moC{i6C{u:C|u2C|q)B{itB{mtB}q B}uB|uC{g^B}i C}i+B{ihB{gqB{gC{q6C|m)B|mB}iB|qB}m B{qhBxkYBxluCxleBxm}BxmCxmnB|m C|lIC|m.B|lB|kOB|mAxgD~udeathd3C|hC~l'A|lD|hCC|hPC|t1CzlmCzh[D|l4BxrYBxruCxrdBxs}BxtCxsnB{tC{r(C{s.B{rB{rOB{sD|m/D|hLD{heA{hB|hGA|hBzmjD{mBzh\A{m|B|m A|mBzujD{tfBzt]B~uD{u:B~tOA{u|A}uA{tD}t?D}u/A}tB~uB~uB}uC~u-C~u0C}uC~rAB}rC}raB~rB}rC~r&BzpjD{ocBzo[B~p D{p:B~oOA{p|A}pA{oD}o?D}p/A}oB}gB|gC|gAB|uB{uB{qtB{mhC{moC{i6C{u:C|u2C|q)B{itB{mtB}q B}uB|uC{g^B}i C}i+B{ihB{gqB{gC{q6C|m)B|mB}iB|qB}m B{qhBxkYBxluCxleBxm}BxmCxmnB|m C|lIC|m.B|lB|kOB|mAxgD~udeathd4C|hC~l'A|lD|hCC|hPC|t1CzlmCzh[D|l4BxrYBxruCxrdBxs}BxtCxsnB{tC{r(C{s.B{rB{rOB{sD|m/D|hLD{heA{hB|hGA|hBzmjD{mBzh\A{m|B|m A|mBzujD{tfBzt]B~uD{u:B~tOA{u|A}uA{tD}t?D}u/A}tB~uB~uB}uC~u-C~u0C}uC~rAB}rC}raB~rB}rC~r&BzpjD{ocBzo[B~p D{p:B~oOA{p|A}pA{oD}o?D}p/A}oB}gB|gC|gAB|uB{uB{qtB{mhC{moC{i6C{u:C|u2C|q)B{itB{mtB}q B}uB|uC{g^B}i C}i+B{ihB{gqB{gC{q6C|m)B|mB}iB|qB}m B{qhBxkYBxluCxleBxm}BxmCxmnB|m C|lIC|m.B|lB|kOB|mAwWH~edeathd5G|WG~^$E|^G|W4G|WG|d Gz^pGzWrH|^4BwaYBwbuCwbdBwc}BwcCwcnBzcCzb(Czc.BzbBzaOBzcD{]/D{XLDzXeAzXB{XGA{XBy]jDz]ByX\Az]|B{] A{]ByejDzdfByd]B}eDze:B}dOAze|A|eAzdD|d?D|e/A|dB}dB}dB|dC}d-C}d0C|dC}aAB|aC|aaB}aB|aC}a&By_jDz^cBy^[B}_ Dz_:B}^OAz_|A|_Az^D|^?D|_/A|^B|WB{WC{WAB{dBzdBz`tBz\hCz\oCzX6Czd:C{d2C|`)BzXtBz\tB|` B|dB{dCzW^B|X C|X+BzXhBzWqBzWCz`6C|\)B|\B|XB|`B|\ Bz`hBw[YBw[uCw[eBw\}Bw\Cw\nB{\ C{[IC{\.B{[B{[OB{\AwBH~Pdeathd6G|CG~I'E|HG|C4G|CG|O;GzHpGzCrH|H4BwMYBwMuCwMdBwN}BwOCwNnB{OC{M(C{N.B{MB{MOB{ND{H/D{CLDzCeAzCB|CGA|CBzHjDzHBzC\AzH|B|H A{HBzPjD{OfBzO]B~PD{P:B~OOAzP|A|PA{OD|O?D|P/A|OB}PB~PB|PC~P-C}P0C|PC}MAB|MC|MaB~MB}MC~M&BzKjD{JcBzJ[B~K D{K:B~JOA{K|A|KA{JD|J?D|K/A|JB|BB|BC|BAB{PBzPB{LtBzHhC{HoC{D6C{P:C|P2C|L)B{DtB{HtB}L B}PB|PC{B^B}D C|D+BzDhBzBqB{BC{L6C|H)B|HB|DB|LB}H BzLhBxFYBxGuCxGeBxH}BxHCxHnB{H C{GIC{H.B{GB{FOB{HAx%H~3deathd7G|%G~,$E|+G|%CE|%QG|1Gz+pGz%ZH|+4Bx0YBx0uCx0dBx1}Bx1Cx1nB{1C{0(C{1.B{0B{0OB{1D|+/D|&LD{&eA{&B|&GA|&Bz+jDz+Bz&\Az+|B|+ A|+Bz3jD{2fBz2]B~3D{3:B~2OA{3|A}3A{2D}2?D}3/A}2B~3B~3B}3C~3-C~30C}3C~/AB}/C}/aB~/B}/C~/&Bz.jD{,cBz,[B~. D{.:B~,OA{.|A}.A{,D},?D}./A},B}%B|%C|%AB|3B{3B{.tB{+hC{+oC{'6C{3:C|32C|.)B{'tB{+tB}. B}3B|3C{%^B}' C}'+B{'hB{%qB{%C{.6C|+)B|+B}'B|.B}+ B{.hBx)YBx)uCx)eBx*}Bx*Cx*nB|* C|)IC|*.B|)B|)OB|*AwH~deathd8G|G~ E| G|CE|QG|;Gz pGzZH| 4BwYBwuCwdBw}BwCwnB{C{(C{.B{B{OB{D{ /D{LDzeAzB{GA{Bz jDz Bz\Az |B| A{ ByjDzfBz]B}Dz:B}OAz|A|AzD|?D|/A|B}B~B|C~-C}0C|C}AB|C|aB~B}C~&Bz jDz cBz [B} Dz :B} OAz |A| Az D| ?D| /A| B|B|C|AB{BzB{ tBz hCz oC{6C{:C|2C| )B{tBz tB} B}B|C{^B} C|+BzhBzqB{C{ 6C| )B| B|B| B} Bz hBxYBxuCxeBx }Bx Cx nB{ C{IC{ .B{B{OB{ AwH~deathd9G|G~ $E| G|CE|QG| Gz pGzZH| 4BwYBwuCwdBw}BwCwnB{C{(C{.B{B{OB{D{ /D{LDzeAzB{GA{Bz jDz Bz\Az |B| A{ ByjDzfBz]B}Dz:B}OAz|A|AzD|?D|/A|B}B~B|C~-C}0C|C}AB|C|aB~B}C~&Bz jDz cBz [B} Dz :B} OAz |A| Az D| ?D| /A| B|B|C|AB{BzB{ tBz hCz oC{6C{:C|2C| )B{tBz tB} B}B|C{^B} C|+BzhBzqB{C{ 6C| )B| B|B| B} Bz hBxYBxuCxeBx }Bx Cx nB{ C{IC{ .B{B{OB{ StU|deathe1TzT|,SxTxFSxTxjTwhTxsUx7TtYStuTtdSt}TtTtnTxTx(Tx.SxTxOSxUy/UyLUxeSxTyGSyTwjUwTw\Sw|Ty SyTwjUxfTw]T{Ux:T{OSx|SzSxUz?Uz/SzS{S{SzT{-U{0TzU{ASzTzaS{SzT{&TwjUxcTw[T{ Ux:T{OSx|SzSxUz?Uz/SzTzSyUyASyTxSxtTxhUxoUx6Ux:Uy2Uy)SxtSxtTz TzSyUx^Tz Uz+TxhTxqSxUx6Uy)SySzSyTz TxhTuYSuuTueSu}TuTunTy TyITy.SyTyOSySupl|~deathe2izpi|w$hxwixpChxpix~iwwsixpslxw7Tu{YSu{uTu{dSu|}Tu|Tu|nTx|Tx{(Tx|.Sx{Tx{OSx|Uyv/UyqLUxqeSxqTyqGSyqTwvjUxvTwq\Sxv|Tyv SyvTw~jUx}fTw}]T{~Ux~:T{}OSx~|Sz~Sx}Uz}?Uz~/Sz}S{}S{}Sz}T{}-U{}0Tz}U{zASzzTzzaS{zS{zT{z&TwxjUxwcTww[T{x Uxx:T{wOSxx|SzxSxwUzw?Uzx/SzwTzpSypUypASy}Tx}SxytTxuhUxuoUxq6Uy}:Uy}2Uzy)SxqtSxutTzy T{}Sy}Uyp^Tzq Uzq+TxqhTxpqSypUxy6Uzu)SzuSzqSzyTzu TxyhTvtYSvtuTvteSvu}TuuTuunTyu TytITyu.SytTytOSyuSu^l|ldeathe3iz^i|g$hxgix^Chx^ixliwgzix^slxg7TuiYSuiuTuidSuj}TujTujnTxjTxi(Txj.SxiTxiOSxjUyd/Uy_LUx_eSx_Ty_GSy_TwdjUxdTw_\Sxd|Tyd SydTwljUxkfTwk]T{lUxl:T{kOSxl|SzlSxkUzk?Uzl/SzkS{kS{kSzkT{k-U{l0TzlU{hASzhTzhaS{hS{hT{h&TwgjUxecTwe[T{g Uxg:T{eOSxg|SzgSxeUze?Uzg/SzeTz^Sy^Uy^ASykTxlSxgtTxdhUxdoUx_6Uyl:Uyk2Uzg)Sx_tSxdtTzg T{kSykUy^^Tz_ Uz_+Tx_hTx^qSy^Uxg6Uzd)SzdSz_SzgTzd TxghTvbYSvbuTvbeSvc}TucTucnTyc TybITyc.SybTybOSycSvNl}^deathe4i|Oi|W hzWizOChzOiz^ixWzizOwlzW4TvYYSvYuTvYdSvZ}TvZTvZnTzZTzY(TzZ.SzYTzYOSzZUzT/UzOLUyOeSyOT{OGSzOTyTjUyTTyO\SyT|T{T SzTTx\jUy[fTy[]T|\Uy\:T|[OSy\|S{\Sy[U{[?U{\/S{[S|\S}\S{\T}\-U|\0T{\U|YAS{YT{YaS}YS|YT}Y&TyWjUyUcTyV[T|W UyW:T|UOSyW|S{WSyUU{U?U{W/S{UT{NS{NU{NASz\Ty\SzWtTyThUyToUzP6Uz\:U{\2U{W)SzPtSyTtT|W T|\S{\UzN^T|P U{P+TyPhTyNqSzNUzX6U{T)S{TS{PS{WT|T TyXhTwRYSwRuTwReSwS}TwTTwSnTzT TzRITzS.SzRTzROSzSSuEl|Udeathe5i|Ei|L hzLizEChzEizUixLsizEwlzL4TuPYSuPuTuPdSuQ}TuRTuQnTyRTyP(TyQ.SyPTyPOSyQUzK/UzFLUxFeSxFTzFGSzFTxKjUxKTxF\SxK|TzK SzKTxSjUyRfTxR]T|SUyS:T|ROSyS|SzSSyRUzR?UzS/S{RS{SS|SS{ST|S-U{S0T{SU{PAS{PT{PaS|PS{PT|P&TxNjUyMcTxM[T|N UyN:T|MOSyN|S{NSyMU{M?U{N/S{MT{ESzEUzEASzSTySSyOtTxKhUyKoUyG6UyS:UzS2UzO)SyGtSyKtT{O T{SSzSUyE^T{G UzG+TxGhTyEqSyEUyO6UzK)SzKSzGSzOT{K TxOhTvIYSvJuTvJeSvK}TvKTvKnTzK TzJITzK.SzJTzIOSzKSv=l}Ldeathe6i|>i|E hzDiz>Chz>izLixDsiz>wlzD4TvGYSvHuTvHdSvI}TvITvInTzITzH(TzI.SzHTzGOSzIUzC/Uz>LUy>eSy>T{>GSz>TyCjUyCTy>\SyC|T{C SzCTxKjUyJfTyJ]T|KUyK:T|JOSyK|S{KSyJU{J?U{K/S{JS|JS}JS{JT}J-U|J0T{JU|GAS{GT{GaS}GS|GT}G&TyEjUyDcTyD[T|E UyE:T|DOSyE|S{ESyDU{D?U{E/S{DT{=S{=U{=ASzJTyJSzFtTyBhUyBoUz>6UzJ:U{J2U{F)Sz>tSyBtT|F T|JS{JUz=^T|> U{>+Ty>hTy=qSz=UzF6U{B)S{BS{>S{FT|B TyFhTwAYSwAuTwAeSwB}TwBTwBnTzB TzAITzB.SzATzAOSzBSv*l}8deathe7i|+i|2 hz2iz+Chz+iz8ix2ziz+wlz24Tv4YSv5uTv5dSv6}Tv6Tv6nTz6Tz5(Tz6.Sz5Tz4OSz6Uz0/Uz+LUy+eSy+T{+GSz+Ty0jUy0Ty+\Sy0|T{0 Sz0Tx8jUy6fTy6]T|8Uy8:T|6OSy8|S{8Sy6U{6?U{8/S{6S|7S}7S{7T}7-U|70T{7U|4AS{4T{4aS}4S|4T}4&Ty2jUy1cTy1[T|2 Uy2:T|1OSy2|S{2Sy1U{1?U{2/S{1T{*S{*U{*ASz7Ty7Sz3tTy/hUy/oUz+6Uz7:U{72U{3)Sz+tSy/tT|3 T|7S{7Uz*^T|+ U{++Ty+hTy*qSz*Uz36U{/)S{/S{+S{3T|/ Ty3hTw.YSw.uTw.eSw/}Tw/Tw/nTz/ Tz.ITz/.Sz.Tz.OSz/Svl}0deathe8i| i|) hz)iz Chz iz0ix)ziz wlz)4Tv*YSv*uTv*dSv+}Tv+Tv+nTz+Tz*(Tz+.Sz*Tz*OSz+U{%/U{ LUy eSy T{ GS{ Ty%jUy%Ty \Sy%|T{% S{%Ty-jUz,fTy,]T}-Uz-:T},OSz-|S{-Sz,U{,?U{-/S{,S|-S}-S{-T}--U|-0T{-U|)AS{)T{)aS})S|)T})&Ty(jUz&cTy&[T}( Uz(:T}&OSz(|S{(Sz&U{&?U{(/S{&T{S{U{ASz-Tz-Sz(tTy%hUz%oUz 6Uz-:U{-2U{()Sz tSz%tT|( T|-S{-Uz^T| U{ +Ty hTzqSzUz(6U{%)S{%S{ S{(T|% Ty(hTw#YSw#uTw#eSw$}Tw$Tw$nT{$ Tz#IT{$.Sz#Tz#OSz$Svl|"deathe9i|i| hzizChziz"ixsizwlz4TvYSvuTvdSv}TvTvnTyTy(Ty.SyTyOSyUz/UzLUyeSyTzGSzTxjUyTx\Sy|Tz SzTx jUyfTx]T| Uy :T|OSy |S{ SyU{?U{ /S{S| S| S{ T| -U| 0T{ U|AS{T{aS|S|T|&TxjUycTx[T| Uy:T|OSy|S{SyU{?U{/S{T{SzUzASz Ty SytTyhUyoUy6Uy :Uz 2U{)SytSytT{ T| Sz Uy^T{ U{+TyhTyqSyUy6U{)S{S{S{T{ TyhTvYSvuTveSv}TvTvnTz TzITz.SzTzOSzY-nailatt1EIDDDD3>g?xDTdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{W-qnailatt2W>`? `;W;W;~g;;`8kW:`;UdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Y-light1?B>>T>>7;h>>TdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{W-qlight2W>`? `;W;W;~g;;`8kW:`;UdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{QwCrockatt16;'----4!h(y-Um*xFk/wHk#yaa/w`*xa#y`0k*a*k6-m0p,^p9/p;,p/ ,We,B5w51?C?K l C$2 :)%U:T/{9M-T!Z!gT#wU%|{&9G9M{4U4U;#E4#-`/@8Ky"g#j;!=!{;!4y-T*{F/yH#|b/y(y#y0**6-0<6"yy]rockatt2[] ZZZZ;WkZyZT,9+%}K)i#%{O yP!|[%x+ % +E}mȇppt1=m& o4#L!TIt!FK1D&G4 !}`d!F(r ( 464= j} 8!0-+R#w! +?!e-20,#8!T=dA!F+(3r5( 5408@4=8-};8$t'u-/tъ / #R/-IM"_Kali qt)ym-IM-I''( 0x6e'ǵo"@y#Cy,=,gGyH0"h1!+0!E'/"_a5`%L`dX%OWPW]K%ULxU+X% M+]rockatt31[7] 7Z1Z1Z?Z17Wk1Zy7ZTH#9E*KEb=*N;#P<X/*9#1#x;0=* 30"a}·p6=+ 9#h&Ye&Fg6a+d9'&Y,d0&F-#r%- %9 ;-9=()=$!52#0S(|#v!&;#n=0?<&f922<5,9(T&T[d_&FI-PrT- S9M=]9=WK}X=$,2/֊'4'(RK2Gi'_haa%q#{Gy2Ii2ID,!-$56,т'_(C1=Iadye5!6!H5!c,K'_#4|*K{bs*Os#s]h*s#i#xs0u*1i01]rockatt41[7] 7Z1Z1Z?Z17Wk1Zy7ZTX#4U*KUbM*NK#MXC*O#E#xO0Q*1G0"xćb6>+ 9#|&Y{&C|6x+y99&R@dC&C1-5r;- 894;A9L<l3==$554270Q4(|4#v5&P#nS0=S&fP22Q5,P(g&Ypdq&C`-drk- e9a=q9Lllam=$,2/Ɋ949(P`2G'`}ag8s7{\2G2G[,5-856,Ȃ'_(C1L]g{y|5!6!]5!y,_'`#4*Kb*N#X*##x0*10"@|jrockatt5EjOj OiEiEiTi/OeiEfOiVa'4`-~H`!bW-|NT'}W!~Q-\'T'y]4 `-/1=%*R*C:/=D*YLdM*C@1CrK11D=A?M=>KlAL@$D9D6E4QD,~C'xD*a'a4>a*^`62a9,`, t*Rd*Cp1sr|11s=q@=L|lq}@$0 6*"G8G,Pl6G+`ZgE!sE"{k"j6G6Gi0D1E9!E0!+`,@5Lk g!9!:!k9!0k+`'4-H!a-N'![-''4 -<4"Pwjrockatt6PjWj WiPiPi_i*WegPf}WiSm*xFk/wHk#yaa/w`*xa#y`0k*a*k6-m0p,^p9/p;,p/ ,We,B5w51?C?K l C$2 :)%U:T/{9M-T!Z!gT#wU%|{&9G9M{4U4U;#E4#-`/@8Ky"g#j;!=!{;!4y-T*{F/yH#|b/y(y#y0**6-0<6"Y-shotatt1DE'BBBB3;a?}BJdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{Y-shotatt2DI'? ???46i;x?@dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{4-qshotatt34!9'9 4P4;F9a4w9TdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{4-qshotatt44!9'9 4P4;F9a4w9TdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{4-qshotatt54z!9|'9z4zP4z;z?9wa4xx9zTdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{4-qshotatt64z!9|'9z4zP4z;z?9wa4xx9zTdWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxatt1LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-lqaxatt2LtlLwt IttOtlALtlPLt} OptmLslPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxatt3LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxatt4LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxatt5LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxatt6LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattb1LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-lqaxattb2LtlLwt IttOtlALtlPLt} OptmLslPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattb3LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattb4LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattb5LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattb6LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattc1LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattc2LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-kqaxattc3LtkLwu ItuOtkALtkPLt~ OpumLskPtu.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattc4LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattc5LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattc6LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattd1LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattd2LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-kqaxattd3LtkLwu ItuOtkALtkPLt OpuiLskPtu3dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattd4LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattd5LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{I-jqaxattd6LtjLwt IttOtjALtjPLt} OptmLsjPtt.dWaS̙hS>aG̠dCZhGfdChS2hG9aSdWaGp:p/pL[d[d]pbdG[dj[d-]q;Id;Md-kq-dd;Y-uY-|Y;q;.q-:Y;`2a2a2h2l1oh1cl\*a\h\Ha\`\h\ds]qIdMdskqsedYsuYs|Yq.qs:Yd `m*]2d1[]jdToBoCm1Em2nmj<]]djd2]2xm(do1dTdO`miCo<]]]jddiTdaҙh>aҠdZh^dh2h:ada{QW-Group-ktx-d05d6ca/resources/example-configs/ktx/progs/w_rock2.mdl000066400000000000000000005310441475442401000255360ustar00rootroot00000000000000IDPO,>8>}I>S޲`%XBo':@r!!"!"!! !!!!!!"!!  trtr!!"!"! !!" !!"   trtr!!" !!"!! !!"!! !!  trtrtr!" " !""! !"" !! rrrt trtrtr!!!"!!""!!!"" !!  rrrrrrtr!!"!"!!!!"!!!!"  rrt rrrrrrtr !!"!"! !!" !!!"  rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr !!!!!! !!! !!!! ! rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr !! ! !!!! !!  rr rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr! ! !!! !!! !  rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr !!!! !! !! rrrrrrrrrrrrrrrr ! !   !  !   rrrr rrrrrrrrrrrrrrr !  !  ! rrrrrrrrr          rrrr !   rrrr     rrrrrrrr      rrrrrr r          rrrrr r! ! ! ! !rrrrr rr            rrrrrr rr                       rrrrrr                      rrrrss   !!  !!  !! !!  !! !! rrrrsrr !!  !!  !!  !! !!  !! rrsssrrssr          rrrssrrrsrrrrrssrssrrrssrrr rrrrsrrrrrrrrsrrtrrrrrrs rrrrsrsrr rr rrsrr rrrrsrr rrs rrrsrsrr r rrrrsrrrrrrrrsrrrrrrrrrsrtrr rrrsrr rrrrrrsrrrrrrrrrr r rrrrrrrr rrrrr rrrrrrrrr rrrr rrr魎rrsr譎rrrrr训rrrrr箭rrrrrrrrrrrrrrrrsr莮 rrr玮rrrrrrrrrrrrss rrrrrrrrrssrrssrrrrrrrrrrrrss描rrrrr rrrrr rrrsrrrrsrrrsrrrrsrrrrrrrrrrrrsrrrsrrrrsrrsrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrssrrsrrrrrrrrssrsrssrsrrsrrrsrrrrrrrrrrsrsrsrsrrsrrsrrrrrrssssrsrsssrrrrrsrsrrrrrrsrrsrsrsrrsrrsrsrsrrsrrsssrsrsrrrrrsrsssrtrtrsrsrrsrrsrrrrrrrrrrrrrrrrrrrrrrrrrrssrrrrrrrrsssrrrrrrrrrrrrrrrrrssrrssrrrrssrrrrrrrrrr D #`$ D D  $ D $ ) *n) $* ')x) '  $ $ +- ) - + ) e  g d g   z tx ufdqyh x  i rydh f u             11      ii        O P O P                   !"#$%&'()*+,-.'/+0/,+1+%#2)3!45678,9/01')5&.:%*84#);3:</1=/<762%8>$&<(89-;.-7"349$1%3=:<&:265>8(8*,%>&94)%+*-'557-+10.>')(9;"!)25>('-";=9,39=;!3:=<"721$<#"2=,/;:.!#4.&>?@ABCDEFG?AFDGAA@DFHIHFEBECJHE?FIGFAHJ@@?HJB@EGD@BDEDCBJE?IHKLMNOPQRSKMRPSMMLPRTUTRQNQOVTQKRUSRMTVLLKTVNLQSPLNPQPONVQKUTWXYZ[\]^_WY^\_YYX\^`a`^]Z][b`]W^a_^Y`bXXW`bZX]_\XZ\]\[Zb]Wa`cdefghijkcejhkeedhjlmljifignlicjmkjelnddclnfdikhdfhihgfnicml)baxrun1Qt Qt QtRt>QtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞQtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞQtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞQtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞQtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞQtQtQrmQrRt)rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞMKqkim^qkr;#4MKe`hb\ebgQպrockrun5RvRv$QtRtCQtRtRrzRtwTt4VrWl.E %L1PJ>QPLG~p^zϭ/ұϣ+Pnk`U^pJF¬nL;џ&;4ҠիLUjEmPk;N|JxI~GVv8w5uz6X1B31eCG-31>Gp^1=²Gb^<=Gp^Q(rockrun6RvRv$QtRtCQtRtRrzRtwTt4zw~Vwuzs~].F %e2ddLdddG()o(f))({-(+{+bUՑU+^+db4x֨d ++ز ֢3՗ꞞbUFضd bPY|VVV~EtCrEXEW.GFW Z$Gز2شجLְ֩֨Oo^{ֱ2ֲ֫+|֧֭֨Gof{֣2֣֛L֚֠֗Mp^{H4stand1Kq Kr HqKqCIqQKq KnmKn[Nq3LNer\1/pk jp w_9jmMpdVw]CT;UÒK˗&t`bw{ȥkmpeYmX>iZQmUe_OaKreI\bQmZ;eNi`n_/_S 9OUCi£Ǡ 9ŚMVCi 9MVCjiH6stand2Kq Kr HqKqCIqQKq KnmKn[Nq3LNeuq;/rm kr wb9kpMpgVw`CU=\7j\6bNHUBNGΤ-ҟ'ǡ3QGV?knYyceZ;bZ;UʒKј&tdez{̥kppg`m\Li^QnXeaQbNfK\bSn]1fPicnb/aVŬ 5ĥGUCji|ȣˠ ¢5ʚMŘV>i| 9MJCpH5stand3Kq Kr HqKqCIqQKq KnmKn[Nq3LND\1%rm kq xb9kpMpgVx`>U=]7j]5iNHUANEϥ-ա$ɢ5QEV>mnYzceZ;pZ±;U̓Kԙ&tde{{Ψmppg`n\>j^NnXeaQbNfK[cSn];fPjcnb/aV±ǭ 5ŨMV>jb|ɥ̡ ã5˛ǙVœ>p| 9MV>pH6stand4Kq Kr HqKqCIqQKq KnmKn[Nq3LNetvq;/rm kr wb9kpMpgVw`CT>Z8jZ6iMITCMH̤-џ$š5PHU?knYyceY;UɒKИ&tdez{˧kppg`m\Li^QnXeaRaNeK[bSn]1ePicnb/aVĬ 5åMUCiǤʠ 5ɚMĘV>i 5MJ>jbH3stand5Kq Kr HqKqCIqQKq KnmKn[Nq3LND\1/pi jm v]9jkpcJvZCR;Y5jY3iLGR?LDť-ʡ$5PCT;kjzYsceX7iX8jt`”{pfT>PC>;U”Kə&t^et{Ũkk}pc`mW=iYNmSe_NaIcG[aPmX1cLi^m]/_R 9MVCiâ$9›J?jp 5V>jp|)baxstnd1PtNPv,NrQrDPrPPrPqhPrsQr7rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞpain1PvPv,NtPt?PtPtPriPtrQt4&Bvja0o#zv}"v3t}{yOvLoBz>nx>eiE}rBщgE !*jGÏoCv{Yf߫DtBevBnw9|~y rC̉kG}L ?L4zQ6ӂM5"#N7ŸU4X=ˌHp1ԼP6WAlτR:ΉM7z#, &ٹVMƜIr=@14{ϒ=k{8҄EpVMlKgPPkLPX]RXcU\BMUlKf PWf^AΌ_C?N6zU8ӈQ8Q;ŸXAf?lĚ:U?=*+\B4ZAˌGq1P4ǠAlӄU<ΈQ:z % OϜHs==13{{=kt7քEqJMpKlQPn+Q\]T]cV`BNWlLiQY;GdŐHjLVwߍڝO'.f0ߊ23'k+߉)՟э#˝M')f+ό,3"z&҈#ǟ"؍&ӕ#M''7f:׌;32z4ڂ3ϟ'8gpain4@v@v*?t@t??t@t1@ri@tw@t4ECPH=EgGmKeC͈D E<=@@vNrHnXv%IqRvOYx'_>^f?njgBFU8z]:͉V:/*6#X<^?^KqITP>C=cA4b?ČUt1*DÚPr̈́]=ɉX;z7'3@27O2+ʜVv=N1C{'ӒKp{HфQtVXpUlPZp=Y\X\\\__BXXjXk \Z:QgTmUWv3/8-/Ԝ4O:'A^E؊G4wpain5GvGv,EtGt4GtGt GrmGtrHt4mŸioCirkhociÈm2m:fjf{gzaxrx*axjxOrx(i>\r>nr>E_>xg>ω_>ibo%b?i?\bxiToCw?n?En?nnx<\첕bixg?ˉb?xo(gt1iVjGbnxCogZjYZnZ^iZml2mZ:fljqfZ{gbm/cŞiOn(i\mΊnEbxgщcƘ_Ze/Z캞_OeI_]eeEZx_ʼnZrmv/m켜pOv(p[vÊvEmxpƁmE>pain6GvGv,EtGt4GtGt GrmGtrHt4&Bvja0o#zv}"v3t}{yOvLoBz>nx>eiE}rBщgE !*jGÏoCv{Yf߫DtBevBnw9|~y rC̉kG}L RmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞEt*Et4Gr.iEt*sGt..rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞWSt>Ts>wTt@St@Ss@|Vt@ Vs>eVs@nVt>LVt=@Vt@%Wt2?Wu2HWs2\Vu2Vt2Vs2XVt7Ws7Vs7yWu72Wt7u>t>sX>t?s>sy?u @t<>u?tB?uO?s^?u>t~>u>t>sw>rw>sy?s?sp>v>u?t4?tsX@t4?rb=t>t>uN>sw?sp?u,?v(?u,?t4>tt >se>sn>tL>t@>t%@t??uH?s\?u?t?sX?t@s?sy@u2@tv>u>uX>u?u>uy?v ?u<>v?s??sG?r\>s>s>rX>s?r>ry?s ?s<>s-r2vdeathb30v0v$/t0tC/t0t0rz0tw2t4-tR-t-sr-t-t-s0t;0se0sn0tL0t@0t%1t?0uG0s\0u/t0sX/t0s0sy0u 1t<0u0tB0uO0s^0u/t~0u/t0sw/rw0sy0s0sp/v0u0t41t<0u /sX1t40rb.t/t/uN0sw0sp0u,0v(0u,0t4/t-tW-t.sw.t-t-s|0t 0se0sn0tL0t@0t%1t?1uH1s\0u0t0sX0t1s0sy1u21t<0u0u?0vG0u\/v/u/uX/u0u0uy0v 0u<0v0s?0sG0r\/s/s/rX/s0r0ry0s 0s<0s+r]0vodeathb4/v_/vf,,tf/t_C,t_R/tn1/r8m/t0s0t84,t4R,t4,s4r,t5,t5,s5/t5;/s4e/s5n/t4L/t4@/t5%0t:?/u:G/s:\.u:.t:.s:X.t@/s@.s@y/u@ 0t@<.u@/t.B/u.O/s.^/u@.t@~.u:.t7.s7w.r0w/s@y/s@/s:p.v0.u7/t:40t@ftPdeathc8etAMetI,brIfrADerAPerOeqIherAsfrI9brDRbrDbqDrbrEbrEbqEerE;eqDeeqEnerDLerD@erE%frJ?esJGeqJ\esJdrJeqJXdrPeqPeqPyesP frPBes>Oeq>^esOdrO~esJdrGeqGwdp@weqOyeqOeqJpdt@esGfrJ4frOXfr@4fp@bcr@dr>ds>NeqJweqGpesG,ft@(esJ,frG4drJcrKWcrKcqKwcrMcrMcqM|erM eqKeeqMnerKLerK@erM%fr@?fs@Hfq@\es@er@eq@XerEfqEfqEyfsE2frEgt>gs>|it> isnit%jt0?ju0Hjs0\iu0it0is0Xit5js5js5yju52jt5RmZikji~#R~jtRtTKrFIxGIna=xӞ^6gV8w^:TrFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞ^6gV8w^:TrFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞG7Mr3I3I:&E4-`-B7>r'g':!D$r: 3r/Tk'Fj-Vj#a]-\)]#]/j)])j4-m/<]4"4:+-7K0_*e0-|*w:47= C*6AK:_4d:6}4zC=C& **)I#@d#}s*')Yrockatt2WY VVV"V SzVVTe9c"Kcb]"O\P\\M&ԎV!ۉP!xX*Y$ P*")(*1/)./=/"D,6 $R{s3(1& // . $Y,+IC$_@avi st)z5IA+G)&(.8o(p{"B"F.3+g=˃?."s:!+.!=&.$_/7."K,i%"O"Q#]$%x%( '" (o(p//o!r.=s&Cr!6P&RL!{M!qL/K(P.Ms3t8/t*w6=w/Dv*6U/RQ+ԒR*sR8P3T6Mrs!/sv=vCt6TRP{RqQ!PRYrockatt32W8Y 8V2V2V?V18Sk2Vy8VT9"Kax"Oxx]m&ێv!߉n!xv*w$n*E(H1/GʊL/=M"DIo%$W{"s!3(#1& /.%.&$YI+G_$U]ai%s"{EɃ5I^+GE&!(#.8("B"F.3HgZy\.":!H.!Z&I$_L7I"HHi?"N=?X7$A7xA(D" 7((//!.=&C!on&Wk!{m!qm/k(n.M38**6L/C*6s/Ro+ےp*qp8n3r6M!/LC6rRo{pso!npM+Yrockatt42W8Y 8V2V2V?V18Sk2Vy8VT7"Ka"N[|&!׆!y* $1*"U(V1/UNJY/LY"BX60$W,{.s.3+(/1& /.0.2$WX+Go$`mZi0s/{UƂ5In+GU&.(/.6(뉩"_"D.=Vgkyk.!:!V.!k&X$`V7U"HUaI"NHIXC$NDxP( R" D((/*!n.L&B!d&Y|!v!g|/{(.M38**6L/B*d/W+{*s836M!/劦LAER{s!M=erockatt5EeNe NdEdEdTd-N`hEbNdV"F(Ha(Q$X+Ő'Ƈ'y/-*1/"g.j6*gŠj5Kk(Bjd@*P?!|?s?8=.@6+ 5."ΌA3A*Pg1G*T!ZaA"s@$}g$;G1g+@.A3!E.ӈ(_(C3=g"g~"Â~3!?#j3!~+j*Te"Fb(HbiX(NV$XXT*_$U$x_.-c(;U.". 5*'Պ3K+B'd+W'}'s5.3M8 >*/NJ8G7Mr3I3I:&E4-`-B7>r'g':!D$r: 3r/Tk'Fj-Vj#a]-\)]#]/j)])j4-m/<]4"4:+-7K0_*e0-|*w:47= C*6AK:_4d:6}4zC=C& **)I#@d#}s*')):shotatt1BC'??P??4:i=x?@rFxGn\|x̕|t̏|n̠|t~n~nyx r<|xTt R*RgoRLRt@Rge)t)g})gr))t)t;~.ko*~*tR~jtTikZba*ms*m}Rmj&i~Rt*t*~kEtbvUtB~>RmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞRmZikji~#R~jtRtTKrFIxGIna=xӞJ>0n>I?SGwBdm5V?@11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111111111111111!111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111!1111111111111111111111111111111111111111111111111!1111111111111111111111111111111!1111111111111111111111111111111111111111111!111111111111111111111111111111!1111111111111111111111111111111111111111111111!111111111111111111111111111111!!11111111111111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!11111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!1111111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111!!1111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!1111霜1111111111111111111111111111!!1111蜜1111111111111111111111111111111111111111111111111!!1111蜜11111111111111111111111111111!1111霜1111111111111111111111111111111111111111111111111!1111蜜111111111111111111111111111111!!1111蜜11111111111111111111111111111111111111111111111!!1111眜1111111111111111111111111!1111眜11111111111111111111111111111111111111111!1111111111111111111111111111!!111111111111111111111111111111111111111!!1111111111111111111111111111!111111111111111111111111111111111111111!11111111111111111111111111111!!11111111111111111111111111111111111111!!11111111111111111111111111111!11111111111111111111111111111111111111!11111111111111111111111111111!!11111111111111111111111111111111111111!!11111111111111111111111111111!!11111111111111111111111111111111111111!!111111111111111111111111111111!11111111111111111111111111111111111111!111111111111111111111111111111!!1111111111111111111111111111111111111!!111111111111111111111111111111!1111111111111111111111111111111111111!111111111111111111111111111111!!1111111111111111111111111111111111111!!111111111111111111111111111111!1111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111!!1111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111!!111111111111111111111111111111111111!!1111111111111111111111111111111!!111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111111!111111111111111111111111111111111111!11111111111111111111111111111111!!111111111111111111111111111111111111!!1111!1111111111111111111111111111!111111111111111111111111111111111111!1111!!11111111111111111111111111111!!111111111111111111111111111111111111!!1111!11111111111111111111111111111!111111111111111111111111111111111111!1111!111111111111111111111111111!!111111111111111111111111111111111111!!1111!#!11111111111111111111111111!!111111111111111111111111111111111111!!1111!""!1111111111111111111111111111!11111111111111111111111111111111111!1111!#"!!11111111111111111111111111!!11111111111111111111111111111111111!!1111!#11111111111111111111111111!11111111111111111111111111111111111!1111!#11111111111111111111111111!11111111111111111111111111111111111!1111!11111111111111111111111111!!11111111111111111111111111111111111!!1111!!11111111111111111111111111!11111111111111111111111111111111111!1111!1111111111111111111111111!!11111111111111111111111111111111111!!1111%!1111111111111111111111!11111111111111111111111111111111111!1111!#!1111111111111111111111!1111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111!!1111##!111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111!1111#!1111111111111111111111111111111111111111111111!!11111111111111111111111111111111!!1111!#!111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111!1111!#!1111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!11111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!!11111111111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!1111111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!111111111111111111111111!111111111111111111111111111111111111111111!1111!!111111111111111111111111111111!!1111111111111111111111111111111111111111111!!1111!!111111111111111111111111111111!1111111111111111111111111111111111111111111!1111!11111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!!11111111111111111111111111111!1111111111111111111111111111111111111111111!1111!11111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!11111111111111111111111111111!11111111111111111111111111111111111111111!1111!1111111111111111111111111111!!111111111111111111111111111111111111111111!!1111!!11111111111111111111111111111!111111111111111111111111111111111111111111!1111!!11111111111111111111111111111!!11111111111111111111111111111111111111111!!1111!!1111111111111111111111111111!11111111111111111111111111111111111!1111!!11111111111111111111111111111!!11111111111111111111111111111111111111111111!!1111!1111111111111111111111111111!1111111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111!111111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111!!111111111111111111111111111111111111111111111111111111111111!!11111111111111111111111111!1111111111111111111111111111111111111111111111111111111111!11111111111111111111111111111111111!111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111!!11111111111111111111111111111111111111111111111111111111!!111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111!!1111111111111111111111111111111111111111111111!!111111111111!!11111111111111!1111111!!11111111!!1111!1111!!1111!!1111!1111!1111!1111!1111111111!!111!111111!1111!!1111111111111!!111111111111111!!111111!111111!!!111111 D #$ D D  $ D $ "  %  !  % . .C '= G ' @ @> GDY F_ -] 4cNI dJ GD[ Na da ]D\o ? ? o f fK6 6  h[l   h k            ! !"#$#"$ "!# !!#$" $ !""%&'(%)*)'(*+(,&,+'')%)*('+*+,(&%('&,-./0-121/02304.43//1-120/32340.-0/.4*Okcaxrun1UVk UVo UVoVVk>UVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NUUVkUVsUUohUUkVVo3NU.{ƛ ;|}ŐLwę{Ë{]~d ;}L{|򔙍]dU$trockrun2VXVX$UVVVCUVVVVUhVVsXV7Q.;E;KOQK>>[p.?F?pOpp>>J**c$y$o9H|8t9((b|'t]x8xx'x{ p:p}LpXpb pp}L璕pXpbU zrockrun3VXVX$UVVVCUVVVVUhVVsXV795$d'5O;"6~,)P<"6'VHSY,'@z{ax l%Kz(zI|("v{|asz]t*}o} RX|>!WWQgľ QS|ľ>SWQaUءrockrun4VXVX$UVVVCUVVVVUhVVsXV7*9b|(V.$,x!|X;9dDJ@-Jz!_r|v Zv}zk{KsIv"n|s gkXo#fz ?IyC#FW>g֞ >@؝?ӡ!ԡ@P20\5,E._O]b2/@}axn-H{.w.~}aww]w/|s| ]a>aW]aЙ ]^ЕKљѕ^W]aU)wrockrun6VXVX$UVVVCUVVVVUhVVsXV7U.?E?MSUMAA[u/DFDtOutAAJ..c)y)ooFf:k5kj0vgoAtOf5vou7'{Vm[hhČ ps7Ɖ'ÅVo[mzM0sʡstand2PRPU MRPRCNRRPRPQmPQaRR7U1vDlrG~MBX'{QNtGWwEZn1zJrRiCu$rrLxDEi;n6hf:{j5v@FtpFg9m4kk0vZpAsOg5u pv7'|Vn[ihǍ rsŊ4ʊ ƇVp]nzM0s̠stand3PRPU MRPRCNRRPRPQmPQaRR7V1vEsIOBY'{RtIPwEqo zJsRjCv$srLNzEeit>rFi:n5hm0uapBsOg5t rx4 }Vo]jkˎ rtNj4̋ ʈOp]okM/sǡstand4PRPU MRPRCNRRPRPQmPQaRR7S1tDlrG~MBW'{QMsGWwDqm1xIrQhCu$ppKNxDeg;m6he:{j5t@Ft;t>pEg9k4kk/vgoAsOf5uou7'|Vm[hhōprË4NJ'ćVo[mzM/tástand5PRPU MRPRCNRRPRPQmPQaRR7R;tBnpF|LD~V(zPMrFYvBgj1xGpPfCs$npJNwBef;k5hc:g4s?Fs:u>oDf9j3kj/vgn@tOe4vmt7'}Vj[dz noֽ7Ë'ԿVm]jz*Ocaxstnd1TVTX'RUUUCTUPTU TRhTUrUU4NU~OIzSvB{|@px?\wQNsA̫ {ɣ?Ф"̚N]i ?"N]i 5xXpain2:Xx:X~$:V~;VxC:Vx:V;U~m:Vxs;V~3Cc KOsQ@7K5hP9NP,RRIMN>rT@8XBDMOQR@3{.yr%Ķ%éN7B<6 3{0zr,  S4|@6~63xZpain3:Xx:X~$8V~;VxD:VxP:V:U~h:Vxs;V~9CaLM/C{;zr7ž%'0ıND@K6"C{@zr&%#NC|@E|6I~OIzSvB{|@px?\wQNsA̫ {ɣ?Ф"̚N]i ?"N]i*Oucaxdeth1KXuKX{ KV{tMVu>KVuKVMU{mKVusMV{.NUKVuKVMU{mKVusMV{.NUKVuKVMU{mKVusMV{.NUKVRKV\MUWmKVRsMVW.NUIV#IV+KU&pIV#sKV&.NUHV:GWGUyZGWyOFVyFV|GUHVu?HV9HWHVu\HWuOGVuGV|HVJUuNXdeatha2MX{MX,KVMV{CKV{WMVMUhMV{sNV7LVeLVlLV-KVLVOKVKVKVNUDNUpNW*LUNWHLWKWKUsLVLUMVMUKUJUXKVMKVKUJUJVJVMVy>MV:LWMUyZLWyOLVyLV|MUNVu?NV9MVMUu\MVuOMVuMV|MUOUvTXdeatha3RX{RX$PVRV{FRV{RVRUhRV{sTV7QVeQVlQV-PVQVOPVPVPVSUDSUpSW*QUSWHQWQWQUsQVQURVRUPUOUXPVMPVPUOUOVOVSVz>SV:RWRUzZRWzOQVzQV|RUSVv?SV9SVSUv\SVvORVvRV|SURUoVXdeatha4UXsUXw$TVwVVsDUVsPUV}UUwhUVssVVw7TV|eTV~lTV~-SV|TV|OSV|SV}SV}VUyDVU}pVW}*TUyVWyHTWyTW}TU}sTVTUUVUUSU~RU~XSV~MSVSURURV~RVVVs>VVy:UWyUUsZUWsOTVsTVy|UUyVVo?VVy9VVyVUo\VVoOVVoVVy|VUyRU_VXodeatha5UXdUXh$TVhVVdDUVdPUVnUUhhUVdsVVh7UVleUVmlUVm-TVlUVlOTVlTVmTVmVUiDVUmpVWm*TUiVWiHTWiTWmTUmsTVoTUoVVoVUoTUnRUnXTVnMTVoTUoRUoRVnRVoVVc>VVi:UWiUUcZUWcOTVcTVi|UUiVV_?VVi9VViVU_\VV_OVV_VVi|VUiRUPVXadeatha6UXTUXY$TVYVVTDUVTPUV^UUYhUVTsVVY9TV]eTV_lTV_-SV]TV]OSV]SV^SV^VUZDVU^pVW^*TUZVWZHTWZTW^TU^sTV`TU`UVaUUaSU_RU_XSV_MSV`SU`RU`RV_RV`VVT>VVZ:UWZUUTZUWTOTVTTVZ|UUZVVP?VVZ9VVZVUP\VVPOUVPUVZ|VUZWU(\X9deatha7ZX+ZX2$YV2ZV+FZV+ZV6ZU2hZV+u\V29YV5eYV7lYV7-XV5YV5OXV5XV6XV6[U2D[U6p[W6*YU2[W2HYW2YW6YU6sYV8YU8ZV9ZU9XU7WU7XXV7MXV8XU8WU8WV7WV8[V,>[V2:ZW2ZU,ZZW,OYV,YV2|ZU2[V(?[V29[V2[U(\[V(OZV(ZV2|[U2RUVX!deatha8UXUX,TVUVCTVUVUUhUVsVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTV TU UV!UU!SURUXSVMSV SU RU!RVRV!VV>VV:UWUUZUWOTVTV|UUVV?VV9VVVU\VVOUVUV|VURU VXdeatha9UXUX,TVUVFUVUVUUhUVuVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTVTUUVUUSURUXSVMSVSURURVRVVV>VV:UWUUZUWOTVTV|UUVV ?VV9VVVU \VV OUV UV|VURU VXdeatha10UX UX,TVUV FUV UVUUhUV uVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWSWSUsTVTUUVUUSURUXSVMSVSURURVRVUV >UV:TWUU ZTW OTV TV|UUVV ?VV9UVUU \UV OUV UV|UURUVXdeatha11UX UX,TVUV FUV UVUUhUV uVV7TVeTVlTV-SVTVOSVSVSVVUDVUpVW*TUVWHTWTWTUsTVTUUVUUSURUXSVMSVSURURVRVVV >VV:UWUU ZUW OTV TV|UUVV?VV9VVVU\VVOUVUV|VUTUpYXdeathb1VXsVXx UVxXVsCVVsPVVXUxhVVssYVx4VV|eVV~lVW~-UV}VW|OUW}UW~UV~XVzDXV~pXW~*VVzXWzHVWzUW~UV~sVWVVWWWVUV~TV~XUW~MUWUVTVTW~TWWVs>WVz:VWzWUsZVWsOVVsVVz|WUzXVp?XVz9WWzWVp\WWpOWVpWVz|WVz?UoEXdeathb2CXrMCXw$@VwDVrDCVrPCV~CUwhCVrsEVw7AV|eAV~lAW~-AV}AW|OAW}AW~AV~CVzDCV~pCW~*AVzCWzHAWzAW~AV~sAWAVCWCVAV~?V~XAW~MAWAV?V?W~?WCVs>CVz:BWzBUsZBWsOAVsAVz|BUzCVo?CVz9CWzCVo\CWoOCVoCVz|CVz1Un6X~deathb34Xo4Xu$3Vu4VoC3Vo4V|4Uuh4Vos6Vu73Vze3V|l3W|-2V{3WzO2W{2W|2V|5VxD5V|p5W|*3Vx5WxH3Wx3W|3V|s3W~3V~4W~4V~2V|1V|X2W|M2W~2V~1V~1W|1W~5Vq>5Vx:4Wx4UqZ4WqO3Vq3Vx|4Ux5Vn?5Vx95Wx5Vn\5WnO4Vn4Vx|5Vx/UM4X]deathb43XO3XV,0VV3VOC0VOW3V\:3UVm3VOh4VV71VYe1V[l1W[-0VZ1WYO0WZ0W[0V[3VWD3V[p3W[*1VW3WWH1WW1W[1V[s1W]1V]2W]2V]0V[/V[X0W[M0W]0V]/V]/W[/W]3VP>3VW:2WW2UPZ2WPO1VP1VW|2UW3VM?3VW93WW3VM\3WMO3VM3VW|3VW0U&4X7deathb53X(M3X.,0V.4V(D3V(P3V5:3U.h3V(s4V.72V3e2V5l2W5-1V32W3O1W31W41V44V0D4V4p4W4*2V04W0H2W02W42V4s2W62V63W73V71V50V5X1W5M1W61V60V60W50W64V*>4V0:3W03U*Z3W*O2V*2V0|3U04V&?4V094W04V&\4W&O3V&3V0|4V01U6Xdeathb64X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6Xdeathb74X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6Xdeathb84X4X$3V4VC3V4V4Uh4Vs6V73Ve3Vl3W-2V3WO2W2W2V5VD5Vp5W*3V5WH3W3W3Vs3W3V4W4V2V1VX2WM2W2V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO4V4V|5V1U6X deathb94X4X$3V4VC3V4V4Uh4Vs6V74Ve4Vl4W-3V4WO3W3W3V5VD5Vp5W*3V5WH3W3W3Vs3W3V5W 5V 3V1VX3WM3W3V1V1W1W5V>5V:4W4UZ4WO3V3V|4U5V?5V95W5V\5WO5V5V|5VWRs\Vdeathc1ZVtZV{ YU{ZUtCYUtWZUZR{hZUtw\U{3ZTeZTlZU-YTZUOYUYUYT\T}D\Tp\U*ZT}\U}HZU}YUYTsZUZT[U[TYTWTXYUMYUYTWTWUWU[Uw>[U}:ZV}[TwZZVwOZUwZU}|[T}\Us?\U}9[U}[Ts\[UsO[Us[U}|[T}WR\Vdeathc2ZVZV YUZUCYUWZUZRhZUw\U3YTeYTlYU-XTYUOXUXUXT[TD[Tp[U*YT[UHYUXUXTsYUYTZUZTXTWTXXUMXUXTWTWUWUZU>ZU:ZVZTZZVOYUYU|ZT[U?[U9ZUZT\ZUOZUZU|ZT`ReVdeathc3cVcV bUeUAcUcUcRhcUreU5bTebTlbU-aTbUOaUaUaTdTDdTpdU*bTdUHbUbUbTsbUbTcUcTaT`TXaUMaUaT`T`U`UdU>dU:cVcTZcVObUbU|cTdU?dU9dUdT\dUOcUcU|dTeRjVdeathc4iViV$gUjUCiUPiU-iRhiUrjU3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUgUgTshUhTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hViTZhVOhUhU|iTjU?jU9iUiT\iUOiUiU|iTfRpjVdeathc5iVriVw$gUwjUrCiUrPiU-iRwiiUrrjUw3hT}ehTlhU-gT}hU}OgU}gU~gT~jTzDjT~pjU~*hTzjUzHhUzhU~hT~shUhTiUiTgTfTXgUMgUgTfTfUfUjUt>jUz:iVziTtZiVtOhUthUz|iTzjUp?jUz9jUzjTp\jUpOiUpiUz|jTzeRZjVjdeathc6iV\iVd$gUdjU\CiU\PiUj-iRdhiU\rjUd3hTgehTilhUi-gTghUgOgUggUhgThjTdDjThpjUh*hTdjUdHhUdgUhgThshUjhTjiUjiTjgTieTiXgUiMgUjgTjeTjeUieUjiU^>iUd:hVdiT^ZhV^OhU^hUd|iTdjUZ?jUd9iUdiTZ\iUZOiUZiUd|iTdfRHjVXdeathc7iVJiVQ$gUQjUJCiUJPiUW-iRQhiUJrjUQ3hTTehTVlhUV-gTUhUTOgUUgUVgTVjTRDjTVpjUV*hTRjURHhURhUVhTVshUXhTXiUXiTXgTVfTVXgUVMgUXgTXfTXfUVfUXjUK>jUR:iVRiTKZiVKOhUKhUR|iTRjUH?jUR9jURjTH\jUHOiUHiUR|jTRfR4jVEdeathc8iV6iV=$gU=jU6CiU6PiUC-iR=hiU6rjU=3hTAehTClhUC-gTAhUAOgUAgUBgTBjT>DjTBpjUB*hT>jU>HhU>hUBhTBshUDhTDiUEiTEgTCfTCXgUCMgUDgTDfTDfUCfUDjU8>jU>:iV>iT8ZiV8OhU8hU>|iT>jU4?jU>9jU>jT4\jU4OiU4iU>|jT>fR"jV3deathc9iV#iV)$gU)jU#CiU#PiU1-iR)iiU#rjU)3hT/ehT1lhU1-gT/hU/OgU/gU0gT0jT,DjT0pjU0*hT,jU,HhU,hU0hT0shU2hT2iU3iT3gT1fT1XgU1MgU2gT2fT2fU1fU2jU&>jU,:iV,iT&ZiV&OhU&hU,|iT,jU"?jU,9jU,jT"\jU"OiU"iU,|jT,fRjV'deathc10iViV$gUjUCiUPiU&-iRiiUrjU3hT$ehT%lhU%-gT$hU$OgU$gU%gT%jT!DjT%pjU%*hT!jU!HhU!hU%hT%shU'hT'iU'iT'gT&fT&XgU&MgU'gT'fT'fU&fU'jU>jU!:iV!iTZiVOhUhU!|iT!jU?jU!9jU!jT\jUOiUiU!|jT!eR jVdeathc11iViV$gUjUCiUPiU-iRhiUrjU3hTehTlhU-gThUOgUgUgTiTDiTpiU*gTiUHgUgUgTsgUgTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hVhTZhVOgUgU|hTiU ?iU9iUiT \iU OiU iU|iTfRjVdeathc12iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU>jU:iViTZiVOhUhU|iTjU?jU9jUjT\jUOiUiU|jTfRjVdeathc13iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU >jU:iViT ZiV OhU hU|iTjU?jU9jUjT\jUOiUiU|jTeRjVdeathc14iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUgUgTshUhTiUiTgTeTXgUMgUgTeTeUeUiU>iU:hViTZhVOhUhU|iTjU?jU9iUiT\iUOiUiU|iTfRjVdeathc15iViV $gU jUCiUPiU-iR hiUrjU 3hTehTlhU-gThUOgUgUgTjTDjTpjU*hTjUHhUhUhTshUhTiUiTgTfTXgUMgUgTfTfUfUjU>jU:iViTZiVOhUhU|iTjU?jU9jUjT\jUOiUiU|jTDVaHYqdeathd1GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd2GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd3GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkDVaHYqdeathd4GXcGYg EXgHXc>GXcPGXn2GVgmGVcXHXg3FXmeFXolFXo-EXnFXmOEXnEXoEXoHWkDHWopHYo*FWkHYkHFYkEYoEWosFXqFXqGXqGXqEXoDXoXEXoMEXqEXqDXqDXoDXqGXd>GXk:GYkGWdZGYdOFXdFXk|GWkHXa?HXk9GXkGXa\GXaOGXaGXk|GXkHVPMY`deathd5KXRKYY IXYKXR?KXRKX^ KVYmKVRrMXY3JX]eJX_lJX_-IX]JX]OIX]IX^IX^LWZDLW^pLY^*JWZLYZHJYZJY^JW^sJX`JX`KX`KX`IX_HX_XIX_MIX`IX`HX`HX_HX`LXT>LXZ:KYZKWTZKYTOJXTJXZ|KWZLXP?LXZ9LXZLXP\LXPOKXPKXZ|LXZHV<MYLdeathd6KX?KYE IXDKX??KX?KXK KVDmKV?rMXD3JXIeJXKlJXK-IXIJXIOIXIIXJIXJLWFDLWJpLYJ*JWFLYFHJYFJYJJWJsJXLJXLKXLKXLIXKHXKXIXKMIXLIXLHXLHXKHXLLX@>LXF:KYFKW@ZKY@OJX@JXF|KWFLXKX):JY)JW"ZJY"OIX"IX)|JW)KX?KX)9KX)KX\KXOKXKX)|KX)HVMYdeathd8KXKY IX KXCIXQKXKV mKVZMX 3JX eJXlJX-IX JX OIX IXIXLW DLWpLY*JW LY HJY JYJWsJXJXKXKXIXHXXIXMIXIXHXHXHXLX>LX :KY KWZKYOJXJX |KW LX?LX 9LX LX\LXOKXKX |LX HVMYdeathd9KXKY IX KXCIXQKXKV mKVZMX 5JX eJXlJX-IX JX OIX IXIXLW DLWpLY*JW LY HJY JYJWsJXJXKXKXIXHXXIXMIXIXHXHXHXLX>LX :KY KWZKYOJXJX |KW LX?LX 9LX LX\LXOKXKX |LX TRxYXdeathe1XV{XX,VUXU{CVU{RXU XRhXU{sYU4VTeVTlVU-VTVUOVUVUVTXTDXTpXU*VTXUHVUVUVTsVUVTXUXTVTTTXVUMVUVTTTTUTUXU|>XU:WVWT|ZWV|OVU|VU|WTXUx?XU9XUXTx\XUxOXUxXU|XTjRgpXxdeathe2nVjnXp,kUpnUjCkUjRnUw nRphnUjspUp4mTtemTvlmUv-lTumUtOlUulUvlTvnTrDnTvpnUv*lTrnUrHlUrlUvlTvslUwlTwnUxnTxlTvjTvXlUvMlUxlTxjTxjUvjUxnUk>nUr:mVrmTkZmVkOlUklUr|mTrnUg?nUr9nUrnTg\nUgOnUgnUr|nTrjRYpXideathe3nVYnXa,kUanUYCkUYRnUg nRahnUYspUa4lTeelTgllUg-kTflUeOkUfkUgkTgnTcDnTgpnUg*lTcnUcHlUclUglTgslUilTimUimTikTgjTgXkUgMkUikTijTijUgjUinU\>nUc:mVcmT\ZmV\OlU\lUc|mTcnUY?nUc9nUcnTY\nUYOnUYnUc|nTcjUJpXZdeathe4nXKnXR$kVRnVKCkVKWnVYnURhnVKhpVR7lVVelVXllVX-kVWlVVOkVWkVXkVXnUTDnUXpnWX*lUTnWTHlWTlWXlUXslVZlVZmVZmVZkVXjVXXkVXMkVZkVZjVZjVXjVZnVM>nVT:mWTmUMZmWMOlVMlVT|mUTnVJ?nVT9nVTnVJ\nVJOnVJnVT|nVTjU@pXPdeathe5nXBnXH$kVHnVBCkVBWnVOnUHhnVBhpVH7mVMemVNlmVN-lVMmVMOlVMlVNlVNnUJDnUNpnWN*lUJnWJHlWJlWNlUNslVPlVPnVPnVPlVOjVOXlVOMlVPlVPjVPjVOjVPnVD>nVJ:mWJmUDZmWDOlVDlVJ|mUJnV@?nVJ9nVJnV@\nV@OnV@nVJ|nVJkU9pXIdeathe6nX;nXB$kVAnV;CkV;WnVHnUAhnV;hpVA7mVEemVGlmVG-lVFmVEOlVFlVGlVGoUCDoUGpoWG*mUCoWCHmWClWGlUGsmVImVInVInVIlVGkVGXlVGMlVIlVIkVIkVGkVInV<>nVC:mWCnUnV1:mW1mU*ZmW*OlV*lV1|mU1nV&?nV19nV1nV&\nV&OnV&nV1|nV1jUpX-deathe8nXnX&$kV&nVCkVWnV,nU&hnVhpV&7mV*emV+lmV+-lV*mV*OlV*lV+lV+nU'DnU+pnW+*lU'nW'HlW'lW+lU+slV-lV-nV-nV-lV,jV,XlV,MlV-lV-jV-jV,jV-nV!>nV':mW'mU!ZmW!OlV!lV'|mU'nV?nV'9nV'nV\nVOnVnV'|nV'jUpX"deathe9nXnX$kVnVCkVWnV!nUhnVhpV7lVelV llV -kVlVOkVkV kV nUDnUpnW*lUnWHlWlW lU slV!lV!mV"mV"kV jV XkV MkV!kV!jV"jV jV"nV>nV:mWmUZmWOlVlV|mUnV?nV9nVnV\nVOnVnV|nV*#cnailatt1)- ((((<#g$x(TNU :::%:9k:k:`NU;:6:6:C:;9k6:y;:YNU;:6:6:C:;9k6:y;:YNU=>in>f{&mBDt=bA1111111111111111111111111111111111111111111111111111111111111111!1111111111111111111111111111111111111111111111111111111111111111111111111!!1!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!1111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111!11111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!11111霜111111111111111111111111111111111111111111111111111111111!!11111!!11111蜜1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!11111蜜1111111111111111111111111111111111111111111111111111111111!11111!11111霜1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!11111蜜1111111111111111111111111111111111111111111111111111111111!!11111!!11111蜜11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!11111眜11111111111111111111111111111111111111111111111111111!11111!11111眜111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111111111111111111111111!!11111!!11111!1111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111111111111111111111111!11111!11111!!111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111!!11111!!11111!111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111111!11111!11111!111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111111111!!11111!!11111!#!111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111111!!11111!!11111!""!11111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111111!11111!11111!#"!!111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111111!!11111!!11111!#111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111!11111!11111!#111111111111111111111111111111111111!11111!111111111111111111111111111111111111111111111111111111111!11111!11111!111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111111111111!!11111!!11111!!111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111!11111!11111!111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111!!11111!!11111%!1111111111111111111111!11111!111111111111111111111111111111111111!11111!11111!#!1111111111111111111111!11111!11111111111111111111111111111111111!11111!11111!!11111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!!11111!!11111##!111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111!11111!11111#!1111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111!!11111!!11111!#!111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111!11111!11111!#!1111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111!!11111!!11111!11111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111!11111!11111!!11111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111!11111!11111!!11111111111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111!!11111!!11111!1111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111!!11111!!11111!111111111111111111111111!11111!1111111111111111111111111111111111111111111!11111!11111!!111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111!!11111!!11111!!111111111111111111111111111111!11111!11111111111111111111111111111111111111111111!11111!11111!11111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111!!11111!!11111!!11111111111111111111111111111!11111!11111111111111111111111111111111111111111111!11111!11111!11111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111!!11111!!11111!11111111111111111111111111111!11111!111111111111111111111111111111111111111111!11111!11111!1111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111!!11111!!11111!!11111111111111111111111111111!11111!1111111111111111111111111111111111111111111!11111!11111!!11111111111111111111111111111!!11111!!111111111111111111111111111111111111111111!!11111!!11111!!1111111111111111111111111111!11111!111111111111111111111111111111111111!11111!11111!!11111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111!!11111!!11111!1111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111111!11111!111111111111111111111111111111111111!11111!1111111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111!!11111!!111111111111111111111111111111111111111111111111111111111!!11111!!1111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111111111111111!11111!11111111111111111111111111111111111111111111!!11111!!11111111111111111111111111111111111111111111111!!11111!!1111111111111!!11111!111111111111111!11111!11111111!!11111!!111111111!!11111!!11111!11111!11111!!11111!11111!!11111!11111!11111!11111!11111!!11111!1111!!!11111!1111!11111111111111111!!111!!1111!111111!111111!1111!11111!!111111!!111111111111111111111!!111111!!!!1111111111111111111111111!!111111!!!!111111!111111!1111111!!!111111!!!!111111!!!!111111!!!!!111111!!!111111!!!!111111!!111111!!!111111!!111111!111111!111111!111111111111!111111!111111!111111!111111!111111!1111!111111!11111!111111111!11111111!11111111111 D #$ D D  $ D $ "  %  !  % . .C '= G ' @ @> GDY F_ -] 4cNI dJ GD[ Na da ]D\o o5 f, f y, 5  o+l   o r  o:k   o s            ! !"#$#"$ "!# !!#$" $ !""%&'(%)*)'(*+(,&,+'')%)*('+*+,(&%('&,-./0-121/02304.43//1-120/32340.-0/.4567859:978:;8<6<;77959:87;:;<865876<$Wkkaxrun1S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkkaxrun2S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkkaxrun3S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkkaxrun4S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkkaxrun5S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkkaxrun6S]k S]o S]oU]kAS]kS]sS\ozS\kU]o5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`tS-rockrun1U`U`,S]U]CS]U]U\hU]sV]7f*O7N[Sf[OOZ/S4SONN@78d7j8:FHCMF4x4d/c@-{/7Ozw喍~a Z;WI򔙘W]Zd~ W;W}Izz𖕑V]WbS'trockrun2U`U`,S]U]CS]U]U\hU]sV]7Z.BEBQNZQEE[.BFBOBBJ**c'k'8}2/[a<#E(fHej}.*_y|}a}} n$Kw*{Iz("u{zirz]s.}m}<_dfH#je[ú(,ĺ>*W(g ,.|?!.Y,aSԟrockrun4U`U`,S]U]CS]U]U\hU]sV]719~b{.V2$1w&{#XJ<dQJP-Yw"~_o|s Zs}wlwKq"Ls"k|q ggXm&c͒˟!˟ WgSwΜrockrun5U`U`,S]U]CS]U]U\hU]sV]7I52e2COJE77[m5.D/qOp#s32U}cxo.Hz2w.{}avwXv2}r }5meqŌGƙƖuq̗ 33̑K͗͑3W3a͚15:5͗>Μ!Ζ5W3iS*wrockrun6U`U`,S]U]CS]U]U\hU]sV]7\.EEEUN\UFFZ.FFFOEEJ.x.c*y*8>H>w>-x-e*z\~>|~*}{ߎ.EߊOߗߒZ MM}+ꏕMXMp M:M}L꒕M]MbJ3uˠstand1N[ N\ J[N[CK[RN[NYmNYZQ[4]1uKlqO~VB~` yZrOPvKq}1vMoVwC$oSNvJec@i9hb@f9rDFr@v>mJc=g8kg3wgmFuOb8w˷1y˵CÈ$ƒPvsÎwTvV7Ƌ'ˆVwS[zPzȍ sZq]Ƌ9ˊ LJVsW[vVzJ2sРstand2N[ N\ J[N[CK[RN[NYmNYZQ[4\;uKlrO~UB`'zYMsPPvKq~ vMoU{C$oQNvIEf>j9hc>{g9sDFs@u>mIe=i8ki2wgmEsOc8vɼ {ɺCNJ$ńPysǎyTvUÌ4ȌŊVyQ]{Pk̎ uYq\Ȍ4Ћ'ˇVuW]vUkJ3sѠstand3N[ N\ J[N[CK[RN[NYmNYZQ[4];vMlsPVBa'zZuPWwMq wNqV|C$qQNwJEf@j:hc@i9sEFsBu?oJf=j7ki3vZoFsVe9uɽ |lɽCȊ#ȄP{gʏyTwUƍ7̌'ȊVyQ\{PkЏ uYr\̌4ь͈VuV\wUkJ3s̠stand4N[ N\ J[N[CK[RN[NYmNYZQ[4]1uKlrO~TB~`'zZNsOWvKq}1vMoVwC$oPNvHEe?i9kb?{g9rDFr@uCmJcg9k_>{e9qCFq?v>kIb=g5kf2wgkEtOb7w̲1wl̲Cÿ$ýMPssϿwQuSѼ7'ϽVwP[yNhŏ sVqZ7Ȍ'‰VsU[uSz$Wkaxstnd1R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd2R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd3R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd4R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd5R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd6R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd7R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd8R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd9R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd10R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd11R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxstnd12R]R`'Q\S\DR\PR\jR[hR\sS\7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain1N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain2N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain3N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain4N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain5N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W{kaxpain6N]{ N]} K]}N]{CK]{RN]~0N\}8N\{aN]}4N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`tQ?zpain1R`zR`~,Q]}R]zFR]zR]jR\}hR]zuS]}7q1Zo{\jJsl{]P\a2Z8}]Ky]ZBvF{{DiwBv}?~U>{UIyVuE{zCpw@\vVrC1KZ``=`Y]h a{d?Sa]`i8zWpain27`z7`~,7]~8]zF7]z7]8\~m7]zs8]~3Bm HW;DUxFhIP;Oq%ÍO@SABS67z_pain4B`zB`}*@]}B]z?@]zB]:B\}pB]zsB]}4Nm UV:OTxRgIHkMeQWYVZeBSS{UIyVuE{zCpw@\vVrC1KZ``=`Y]h a{d?Sa]`i$Wukaxdeth1H`uH`{$H]{tJ]u?H]uH]J\{mH]usJ]{.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wukaxdeth2H`uH`{$H]{tJ]u?H]uH]J\{mH]usJ]{.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wukaxdeth3H`uH`{$H]{tJ]u?H]uH]J\{mH]usJ]{.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$WRkaxdeth4H`RH`X$H]XtJ]R?H]RH]]J\XmH]RsJ]X.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$W#kaxdeth5G`#G`'%G]'H]#FG]#G]+H\'mG]#sH]'5N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxdeth6G`G`,F]G]CF]G] jG\hG]sH]7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxdeth7G`G`,F]G]CF]G] jG\hG]sH]7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxdeth8G`G`,F]G]CF]G] jG\hG]sH]7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Wkaxdeth9G`G`,F]G]CF]G] jG\hG]sH]7N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`tA\wF`deatha1D`{D`$C]F]{DD]{PD]D\hD]{sF]9C]eC]lC^-C]C^NC^B^B]E]~DE]pE^*C]~E^~HC^~C^C]sC^C]E^E]C]A]XB^MB^C]A]A^A^E]wDE]~nE^~/D]wE^wHD^wC^~C]~E]w>E]:E]E]wZE]wOE]wE]E]E^w>E^:E_E]wZE^wOE^wE^|E]F\vK`deatha2J`{J`%H]J]{CH]{J]J\hJ]{sK]7H]eH]lH^-H]H^NH^H^H]J]~DJ]pJ^*H]~J^~HH^~H^H]sH^H]J^J]H]F]XH^MH^H]F]F^F^J]wDJ]~nJ^~/I]wJ^wHI^wH^~H]~J]v>J]:J]J]vZJ]vOJ]vJ]J]J^v>J^:J_J]vZJ^vOJ^vJ^|J]M\uR`deatha3Q`{Q`%N]Q]{FQ]{Q]Q\mQ]{sR]7O]eO]lO^-N]O^NN^N^N]Q]}DQ]pQ^*O]}Q^}HO^}O^O]sO^O]P^P]N]M]XN^MN^N]M]M^M^Q]vDQ]}nQ^}/P]vQ^vHP^vO^}O]}Q]u>Q]:Q]Q]uZQ]uOQ]uQ]Q]Q^u>Q^:Q_Q]uZQ^uOP^uP^|Q]P\oU`~deatha4S`sS`w$R]wU]sDS]sPS]}S\whS]ssU]w9R]zeR]|lR^|-Q]zR^zNQ^zQ^|Q]|T]vDT]|pT^|*R]vT^vHR^vR^|R]|sR^}R]}S^~S]~Q]|P]|XQ^|MQ^~Q]~P]~P^|P^~S]oDT]vnT^v/S]oS^oHS^oR^vR]vT]o>T]{:T]{T]oZT]oOS]oS]{T]{T^o>T^{:T_{T]oZT^oOS^oS^{|T]{P\_U`odeatha5S`cS`h$R]hU]cDS]cPS]nS\hhS]csU]h9R]jeR]llR^l-R]kR^jNR^kQ^lQ]lT]gDT]lpT^l*R]gT^gHR^gR^lR]lsR^nR]nT^oT]oR]mP]mXQ^mMQ^nR]nP]nP^mP^nT]`DT]gnT^g/S]`T^`HS^`R^gR]gT]_>T]l:T]lT]_ZT]_OT]_T]lT]lT^_>T^l:T_lT]_ZT^_OT^_T^l|T]lP\PU`_deatha6S`TS`Y$R]YU]TDS]TPS]^S\YhS]TsU]Y9S][eS]]lS^]-R][S^[NR^[R^]R]]T]WDU]]pU^]*S]WT^WHS^WS^]S]]sS^_S]_T^_T]_R]]P]]XR^]MR^_R]_P]_P^]P^_T]PDT]WnT^W/T]PT^PHT^PS^WS]WU]P>U]\:T]\T]PZT]POT]PT]\T]\U^P>U^\:T_\T]PZT^POT^PT^\|T]\U\'Z`7deatha7Y`+Y`1,W]1Y]+FY]+Y]6Y\1hY]+sZ]17X]2eX]4lX^4-W]3X^2NW^3W^4W]4Y]/DZ]4pZ^4*X]/Y^/HX^/X^4X]4sX^6X]6Y^7Y]7W]5U]5XW^5MW^6W]6U]6U^5U^6Y](DY]/nY^//Y](Y^(HY^(X^/X]/Z]'>Z]4:Y]4Y]'ZY]'OY]'Y]4Y]4Z^'>Z^4:Y_4Y]'ZY^'OY^'Y^4|Y]4O\U` deatha8S`S`$R]S]CR]S]S\hS]sU]7R]eR]lR^-Q]R^NQ^Q^Q]T]DT]pT^*R]T^HR^R^R]sR^ R] S^ S] Q]O]XQ^MQ^ Q] O] O^O^ S]DS]nS^/S]S^HS^R^R]T]>T]:T]T]ZT]OS]S]T]T^>T^:T_T]ZT^OS^S^|T]O\U` deatha9S`S`$R]S]FS]S]S\hS]uU]7R]eR]lR^-Q]R^NQ^Q^Q]T]DT]pT^*R]T^HR^R^R]sR^ R] S^ S] Q]O]XQ^MQ^ Q] O] O^O^ S]DS]nS^/S]S^HS^R^R]T]>T]:T]T]ZT]OS]S]T]T^>T^:T_T]ZT^OS^S^|T]P\U`deatha10S` S`$R]S] FS] S]S\hS] uU]7R]eR]lR^-R]R^NR^R^R]T]DT]pT^*R]T^HR^R^R]sR^R]T^T]R]P]XR^MR^R]P]P^P^T]DT]nT^/S]T^HS^R^R]T]>T]:T]T]ZT]OT]T]T]T^>T^:T_T]ZT^OT^T^|T]P\U`deatha11S`S`$R]S]FS]S]S\hS]uU]7R]eR]lR^-R]R^NR^R^R]T]DT]pT^*R]T^HR^R^R]sR^R]T^T]R]P]XR^MR^R]P]P^P^T]DT]nT^/S]T^HS^R^R]T]>T]:T]T]ZT]OT]T]T]T^>T^:T_T]ZT^OT^T^|T]Q\qW`deathb1U`sU`z$S]zV]sDU]sPU]V\zhU]ssW]z4T]|eT]~lT^~-S]}T^|NS^}S^~S]~V]yDV]~pV^~*T]yV^yHT^yT^~T]~sT^T]U^U]S]~Q]~XS^~MS^S]Q]Q^~Q^U]rDU]ynU^y/U]rU^rHU^rT^yT]yV]q>V]~:V]~V]qZV]qOU]qU]~V]~V^q>V^~:V_~V]qZV^qOU^qU^~|V]~<\pC`deathb2@`rM@`w$<]wB]rD@]rP@]~@\wh@]rsC]w7?]{e?]}l?^}->]{?^{N>^{>^|>]|@]wDA]}pA^}*?]w@^wH?^w?^}?]}s?^~?]~@^@]>]}<]}X>^}M>^>]<]<^}<^@]pD@]wn@^w/@]p@^pH@^p?^w?]wA]p>A]|:@]|@]pZ@]pO@]p@]|@]|A^p>A^|:@_|@]pZ@^pO@^p@^||@]|-\n3`}deathb32`o2`u,/]u2]oC/]oW2]|2\ui2]oh3]u70]ye0]{l0^{-/]z0^yN/^z/^{/]{2]vD2]{p2^{*0]v2^vH0^v0^{0]{s0^}0]}1^}1]}/]{-]{X/^{M/^}/]}-]}-^{-^}1]oD1]vn1^v/1]o1^oH1^o0^v0]v2]n>2]{:2]{2]nZ2]nO1]n1]{2]{2^n>2^{:2_{2]nZ2^nO1^n1^{|2]{+\N2`]deathb4/`P/`W$,]W/]PC,]PW/]]/\Wh/]Ph2]W7.]Ye.][l.^[--]Z.^YN-^Z-^[-][/]VD0][p0^[*.]V/^VH.^V-^[-][s.^].]]/^]/]]-]\+]\X-^\M-^]-]]+]]+^\+^]/]OD/]Vn/^V//]O/^OH/^O.^V.]V0]N>0][:/][/]NZ/]NO/]N/][/][0^N>0^[:/_[/]NZ/^NO/^N/^[|/][,\&2`5deathb5/`(/`/$,]/2](D/](P/]5/\/h/](s2]/9/]1e/]3l/^3-.]1/^1N.^1.^2.]20]-D1]3p1^3*/]-0^-H/^-/^3/]3s/^4/]40^50]5.]3,]3X.^3M.^5.]5,]5,^3,^50]&D0]-n0^-/0]&0^&H0^&/^-/]-1]&>1]2:0]20]&Z0]&O0]&0]20]21^&>1^2:0_20]&Z0^&O0^&0^2|0]2.\3`deathb62`2`,/]2]C/]W2]2\m2]h3]70]e0]l0^-/]0^N/^/^/]2]D2]p2^*0]2^H0^0^0]s0^0]1^1]/].]X/^M/^/].].^.^1]D2]n2^/1]1^H1^0^0]2]>2]:2]2]Z2]O1]1]2]2^>2^:2_2]Z2^O1^1^|2].\3`deathb72`2`,/]2]C/]W2]2\m2]h3]70]e0]l0^-/]0^N/^/^/]2]D2]p2^*0]2^H0^0^0]s0^0]1^1]/].]X/^M/^/].].^.^1]D2]n2^/1]1^H1^0^0]2]>2]:2]2]Z2]O1]1]2]2^>2^:2_2]Z2^O1^1^|2].\3`deathb82`2`,/]2]C/]W2]2\m2]h3]70]e0]l0^-/]0^N/^/^/]2]D2]p2^*0]2^H0^0^0]s0^0]1^1]/].]X/^M/^/].].^.^1]D2]n2^/1]1^H1^0^0]2]>2]:2]2]Z2]O1]1]2]2^>2^:2_2]Z2^O1^1^|2].\3`deathb92`2`,/]2]C/]W2]2\m2]h3]70]e0]l0^-/]0^N/^/^/]2]D2]p2^*0]2^H0^0^0]s0^0]1^1]/].]X/^M/^/].].^.^1]D2]n2^/1]1^H1^0^0]2]>2]:2]2]Z2]O1]1]2]2^>2^:2_2]Z2^O1^1^|2]U[sZ]deathc1Y]t&Y]{,W\{Y\tCW\tRY\Y[:Y\Y[sZY\sOY[sY[Y[Y\s>Y\:Y]Y\sZY]sOY\sY\|Y\U[Z]deathc2Y]&Y],W\Y\CW\RY\1Y[hY\sZ\4W[eW[lW\-W[W\NW\W\W[Y[DY[pY\*W[Y\HW\W\W[sW\W[Y\Y[W[U[XW\MW\W[U[U\U\Y[DY[nY]/X[Y]HX]W]W[Z[>Z[:Y\Y[ZY\OY[Y[Y[Z\>Z\:Y]Y\ZY]OY\Y\|Y\_[c]deathc3b]b]$a\c\Cb\b\b[hb\sc\4a[ea[la\-a[a\Na\a\a[c[Dc[pc\*a[c\Ha\a\a[sa\a[c\c[a[_[Xa\Ma\a[_[_\_\c[Dc[nc]/b[c]Hb]a]a[c[>c[:c\c[Zc\Oc[c[c[c\>c\:c]c\Zc]Oc\c\|c\d[j]deathc4g]g] f\j\@g\g\g[hg\sj\5g[eg[lg\-f[g\Nf\f\f[h[Di[pi\*g[h\Hg\g\g[sg\g[h\h[f[d[Xf\Mf\f[d[d\d\h[Dh[nh]/h[h]Hh]g]g[i[>i[:h\h[Zh\Oh[h[h[i\>i\:h]h\Zh]Oh\h\|h\d[qj]deathc5g]rg]w f\wj\r@g\rPg\g[whg\rsj\w4g[|eg[~lg\~-f[}g\|Nf\}f\~f[~h[yDi[~pi\~*g[yh\yHg\yg\~g[~sg\g[h\h[f[d[Xf\Mf\f[d[d\d\h[rDh[ynh]y/h[rh]rHh]rg]yg[yi[q>i[~:h\~h[qZh\qOh[qh[~h[~i\q>i\~:h]~h\qZh]qOh\qh\~|h\~d[[j]jdeathc6g]]g]c f\cj\]@g\]Pg\ig[chg\]sj\c5g[feg[hlg\h-f[gg\fNf\gf\hf[hh[cDi[hpi\h*g[ch\cHg\cg\hg[hsg\jg[jh\jh[jf[hd[hXf\hMf\jf[jd[jd\hd\jh[\Dh[cnh]c/h[\h]\Hh]\g]cg[ci[[>i[g:h\gh[[Zh\[Oh[[h[gh[gi\[>i\g:h]gh\[Zh][Oh\[h\g|h\ge[Ij]Xdeathc7g]Jg]Q f\Qj\J@g\Jg\Xg[Qhg\Jsj\Q5g[Teg[Vlg\V-f[Ug\TNf\Uf\Vf[Vi[QDi[Vpi\V*g[Qi\QHg\Qg\Vg[Vsg\Xg[Xh\Xh[Xf[We[WXf\WMf\Xf[Xe[Xe\We\Xh[JDi[Qni]Q/h[Jh]JHh]Jg]Qg[Qi[I>i[V:i\Vi[IZi\IOh[Ih[Vi[Vi\I>i\V:i]Vi\IZi]IOh\Ih\V|i\Ve[4j]Cdeathc8g]6g]= f\=j\6@g\6g\Cg[=hg\6sj\=5g[?eg[Alg\A-f[@g\?Nf\@f\Af[Ai[i[A:i\Ai[4Zi\4Oh[4h[Ai[Ai\4>i\A:i]Ai\4Zi]4Oh\4h\A|i\Ad[!j]0deathc9g]#g]) f\)j\#@g\#Pg\0g[)hg\#sj\)5g[,eg[.lg\.-f[-g\,Nf\-f\.f[.h[)Di[.pi\.*g[)h\)Hg\)g\.g[.sg\0g[0h\0h[0f[/d[/Xf\/Mf\0f[0d[0d\/d\0h["Dh[)nh])/h["h]"Hh]"g])g[)i[!>i[.:h\.h[!Zh\!Oh[!h[.h[.i\!>i\.:h].h\!Zh]!Oh\!h\.|h\.d[j](deathc10g]g] f\j\@g\Pg\'g[hg\sj\5g[$eg[&lg\&-f[$g\$Nf\$f\&f[&h[ Di[&pi\&*g[ h\ Hg\ g\&g[&sg\'g['h\(h[(f[&d[&Xf\&Mf\(f[(d[(d\&d\(h[Dh[ nh] /h[h]Hh]g] g[ i[>i[%:h\%h[Zh\Oh[h[%h[%i\>i\%:h]%h\Zh]Oh\h\%|h\%d[j]deathc11g]g] f\j\@g\g\g[hg\sj\5g[eg[lg\-f[g\Nf\f\f[h[Di[pi\*g[h\Hg\g\g[sg\g[h\h[f[d[Xf\Mf\f[d[d\d\h[Dh[nh]/h[h]Hh]g]g[i[>i[:h\h[Zh\Oh[h[h[i\>i\:h]h\Zh]Oh\h\|h\e[j]deathc12g]g] f\ j\@g\Pg\g[ hg\sj\ 5g[eg[lg\-f[g\Nf\f\f[i[ Di[pi\*g[ i\ Hg\ g\g[sg\g[h\h[f[e[Xf\Mf\f[e[e\e\h[Di[ ni] /h[h]Hh]g] g[ i[>i[:i\i[Zi\Oh[h[i[i\>i\:i]i\Zi]Oh\h\|i\e[j]deathc13g]g] f\ j\@g\Pg\g[ hg\sj\ 5g[eg[lg\-f[g\Nf\f\f[i[ Di[pi\*g[ i\ Hg\ g\g[sg\g[h\h[f[e[Xf\Mf\f[e[e\e\h[Di[ ni] /h[h]Hh]g] g[ i[>i[:i\i[Zi\Oh[h[i[i\>i\:i]i\Zi]Oh\h\|i\e[j]deathc14g]g] f\ j\@g\Pg\g[ hg\sj\ 5g[eg[lg\-f[g\Nf\f\f[i[ Di[pi\*g[ i\ Hg\ g\g[sg\g[h\h[f[e[Xf\Mf\f[e[e\e\h[Di[ ni] /h[h]Hh]g] g[ i[>i[:i\i[Zi\Oh[h[i[i\>i\:i]i\Zi]Oh\h\|i\e[j]deathc15g]g] f\ j\@g\Pg\g[ hg\sj\ 5g[eg[lg\-f[g\Nf\f\f[i[ Di[pi\*g[ i\ Hg\ g\g[sg\g[h\h[f[e[Xf\Mf\f[e[e\e\h[Di[ ni] /h[h]Hh]g] g[ i[>i[:i\i[Zi\Oh[h[i[i\>i\:i]i\Zi]Oh\h\|i\A]_Fandeathd1D`bDag C`gF`b>D`bPD`nD]gmD]bF`g3C_jeC_llC`l-C_kC`jNC`kB`lB_lE_gDE_lpE`l*C_gE`gHC`gC`lC_lsC`nC_nE`nE_nC_mA_mXB`mMB`nC_nA_nA`mA`nE_`DE_gnE`g/D_`E``HD``C`gC_gE__>E_l:E_lE__ZE__OE__E_lE_lE`_>E`l:EalE__ZE`_OE`_E`l|E_lA]_Fandeathd2D`bDag C`gF`b>D`bPD`nD]gmD]bF`g3C_jeC_llC`l-C_kC`jNC`kB`lB_lE_gDE_lpE`l*C_gE`gHC`gC`lC_lsC`nC_nE`nE_nC_mA_mXB`mMB`nC_nA_nA`mA`nE_`DE_gnE`g/D_`E``HD``C`gC_gE__>E_l:E_lE__ZE__OE__E_lE_lE`_>E`l:EalE__ZE`_OE`_E`l|E_lA]_Fandeathd3D`bDag C`gF`b>D`bPD`nD]gmD]bF`g3C_jeC_llC`l-C_kC`jNC`kB`lB_lE_gDE_lpE`l*C_gE`gHC`gC`lC_lsC`nC_nE`nE_nC_mA_mXB`mMB`nC_nA_nA`mA`nE_`DE_gnE`g/D_`E``HD``C`gC_gE__>E_l:E_lE__ZE__OE__E_lE_lE`_>E`l:EalE__ZE`_OE`_E`l|E_lA]_Fandeathd4D`bDag C`gF`b>D`bPD`nD]gmD]bF`g3C_jeC_llC`l-C_kC`jNC`kB`lB_lE_gDE_lpE`l*C_gE`gHC`gC`lC_lsC`nC_nE`nE_nC_mA_mXB`mMB`nC_nA_nA`mA`nE_`DE_gnE`g/D_`E``HD``C`gC_gE__>E_l:E_lE__ZE__OE__E_lE_lE`_>E`l:EalE__ZE`_OE`_E`l|E_lE]QJa`deathd5H`RHaY G`YH`R?H`RH`^H]YmH]RJ`Y3G_\eG_^lG`^-F_\G`\NF`\F`^F_^I_XDI_^pI`^*G_XI`XHG`XG`^G_^sG`_G__H``H_`F_^E_^XF`^MF``F_`E_`E`^E``H_QDI_XnI`X/H_QH`QHH`QG`XG_XI_Q>I_]:I_]I_QZI_QOH_QH_]I_]I`Q>I`]:Ia]I_QZI`QOH`QH`]|I_]E]<JaKdeathd6H`?HaE G`DH`??H`?H`KH]DmH]?J`D3G_GeG_IlG`I-G_GG`GNG`GF`IF_II_CDI_IpI`I*G_CI`CHG`CG`IG_IsG`KG_KI`KI_KG_IE_IXF`IMF`KG_KE_KE`IE`KI_I_H:I_HI_I`H:IaHI_I_,:I_,I_ZI_OH_H_,I_,I`>I`,:Ia,I_ZI`OH`H`,|I_,E]Jadeathd8H`Ha G` H`CG`H`H] mH]J` 3G_ eG_ lG` -G_ G` NG` F` F_ I_DI_ pI` *G_I`HG`G` G_ sG`G_I`I_G_E_XF`MF`G_E_E`E`I_DI_nI`/H_I`HH`G`G_I_>I_ :I_ I_ZI_OI_I_ I_ I`>I` :Ia I_ZI`OI`I` |I_ E]Jadeathd9H`Ha G` H`CG`H`H] mH]J` 3G_ eG_ lG` -G_ G` NG` F` F_ I_DI_ pI` *G_I`HG`G` G_ sG`G_I`I_G_E_XF`MF`G_E_E`E`I_DI_nI`/H_I`HH`G`G_I_>I_ :I_ I_ZI_OI_I_ I_ I`>I` :Ia I_ZI`OI`I` |I_ S[zW`deathe1V]{V`,U\V\{FU\{WV\jV[hV\{sW\7U\eU\lU]-T\U]NT]T]T\W\DW\pW]*U\W]HU]U]U\sU]U\V]V\T\S\XT]MT]T\S\S]S]V[zDW[nW]/V[zV]zHV]zU]U[W\z>W\:W\W[zZW\zOV\zV\W[W]z>W]:W]W\zZW]zOV]zV]|W\i[ho`wdeathe2m]iMm`p,k\pm\iCk\iRm\wjm[phm\iso\p7l\sel\ull]u-k\tl]sNk]tk]uk\un\pDn\upn]u*l\pn]pHl]pl]ul\usl]wl\wm]wm\wk\ui\uXk]uMk]wk\wi\wi]ui]wm[iDn[pnn]p/m[im]iHm]il]pl[pn\h>n\t:n\tn[hZn\hOm\hm\tn[tn]h>n]t:n]tn\hZn]hOm]hm]t|n\ti[Xo`gdeathe3m]YMm`a,k\am\YCk\YRm\gm[ahm\Yso\a7l\cel\ell]e-k\cl]cNk]ck]ek\em\_Dn\epn]e*l\_m]_Hl]_l]el\esl]gl\gm]gm\gk\ei\eXk]eMk]gk\gi\gi]ei]gm[XDm[_nm]_/m[Xm]XHm]Xl]_l[_n\X>n\d:m\dm[XZm\XOm\Xm\dm[dn]X>n]d:m]dm\XZm]XOm]Xm]d|m\di[Jo`Ydeathe4m`Km`R$k]Rm]KCk]Km]Ym\Rhm]Kso]R7l\Uel\Wll]W-k\Ul]UNk]Uk]Vk\Vn\QDn\Wpn]W*l\Qn]QHl]Ql]Wl\Wsl]Xl\Xm]Ym\Yk\Wi\WXk]WMk]Xk\Xi\Yi]Wi]Ym[JDn[Qnn]Q/m[Jm]JHm]Jl]Ql[Qn\J>n\V:n\Vn[JZn\JOm\Jm\Vn[Vn]J>n]V:n]Vn\JZn]JOm]Jm]V|n\Vi[Ao`Pdeathe5m`Bm`I$k]Im]BCk]Bm]Pm\Ihm]Bso]I7l\Lel\Nll]N-k\Ll]LNk]Lk]Nk\Nn\HDn\Npn]N*l\Hn]HHl]Hl]Nl\Nsl]Pl\Pm]Pm\Pk\Ni\NXk]NMk]Pk\Pi\Pi]Ni]Pm[ADn[Hnn]H/m[Am]AHm]Al]Hl[Hn\A>n\M:n\Mn[AZn\AOm\Am\Mn[Mn]A>n]M:n]Mn\AZn]AOm]Am]M|n\Mi[8o`Ideathe6m`;m`B$k]@m];Ck];m]Ijm\@hm];so]@7l\Cel\Ell]E-k\Dl]CNk]Dk]Ek\Em\@Dn\Epn]E*l\@m]@Hl]@l]El\Esl]Gl\Gm]Hm\Hk\Fi\FXk]FMk]Gk\Gi\Hi]Fi]Hm[9Dm[@nm]@/m[9m]9Hm]9l]@l[@n\8>n\E:m\Em[8Zm\8Om\8m\Em[En]8>n]E:m]Em\8Zm]8Om]8m]E|m\Ej[&o`6deathe7m`(m`0$k]0m](Ck](m]6m\0hm](so]07l\1el\3ll]3-k\2l]1Nk]2k]3k\3n\.Dn\3pn]3*l\.n].Hl].l]3l\3sl]5l\5m]6m\6k\4j\4Xk]4Mk]5k\5j\5j]4j]5n['Dn[.nn]./m['n]'Hm]'l].l[.n\&>n\3:n\3n[&Zn\&On\&n\3n[3n]&>n]3:n]3n\&Zn]&Om]&m]3|n\3i[o`.deathe8m`m`'$k]'m]Ck]m].m\'hm]so]'7l\*el\,ll],-k\+l]*Nk]+k],k\,m\'Dn\,pn],*l\'m]'Hl]'l],l\,sl].l\.m].m\.k\,i\,Xk],Mk].k\.i\.i],i].m[ Dm['nm]'/m[ m] Hm] l]'l['n\>n\,:m\,m[Zm\Om\m\,m[,n]>n],:m],m\Zm]Om]m],|m\,i[o`!deathe9m`m`$k]m]Ck]m]!m\hm]so]7k\ek\lk]-k\k]Nk]k]k\m\Dm\pm]*k\m]Hk]k]k\sk] k\ m] m\ k\i\Xk]Mk] k\ i\ i]i] m[Dm[nm]/l[m]Hl]k]k[n\>n\:m\m[Zm\Om\m\m[n]>n]:m]m\Zm]Om]m]|m\$'knailatt1.2 ----<'h)x-TN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$"knailatt2Y'b)b&Y&Y&j&>b"ZY#wb&TN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$&klight1)*''''8&h'k'`N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$"klight2Y'b)b&Y&Y&j&>b"ZY#wb&TN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$ krockatt1"'~4 ixUN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t>krockatt2BD @@@ @>k@y@`N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$>krockatt33B8D 8@3@3@@@8>k3@y8@`N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$>krockatt43B8D 8@3@3@@@8>k3@y8@`N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Jkrockatt5GPQP QNGNGNVN0QJhGMQNVN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Jkrockatt6RPYPYNRNPRNaNLYJgRM}YNTN\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`tF's<shotatt124'11113*i.}1Jo.[.x[5i/^o5)i5I^5N^/*[(k[5 .f508([:&[.aJ5J.uF5F,W.eW2sDW7+H7H.vG2sW:uIG:u''x8'f808(:N(* a*a.'b.*,Ha,Ra'5 a5a<2p:)5Ja5Xa2u>'u:shotatt238'/ ///4'i,x/@g.S.xS5a.^g5=a5IU5NU.,S,jS8,e808(S8GS,aB5B.u>5>.O.bO.uDO5+@5@.v?.uO5uH?5u((x:(e:0:(:N(. W.W2(d2).JW.RW(t3 W3W8.d7*5IW5PW.t()unshotatt36l;n,;l 6lP6l-pC)z6?5+050-u4)vD2xA42u.Æo.xo?-e?2?(s)uK2zK>2tM.y.xy?-d?2?(}9>1|Q.bS,xEQ8+C8C.vD,vU4xJD4u--x?-e?0?(=S,2U2V8.p8)1@V1YU.t< U<V?8n?)9@V9V8t$Uekaxatt1NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Ugkaxatt2NYgN[n KYnQYgKNYgPNYv QUnpNWgRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxatt3NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxatt4NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxatt5NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxatt6NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattb1NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Ugkaxattb2NYgN[n KYnQYgKNYgPNYv QUnpNWgRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattb3NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattb4NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattb5NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattb6NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattc1NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattc2NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Ufkaxattc3NYfN[o KYoQYfKNYfPNYw QUomNWfRYo.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattc4NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattc5NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattc6NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattd1NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattd2NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Ufkaxattd3NYfN[o KYoQYfKNYfPNYz-QUopNWfRYo.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattd4NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattd5NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`t$Uekaxattd6NYeN[n KYnQYeKNYePNYv QUnmNWeRYn.N\:\x:dG\^Nd=GdI;dN;\n[:[j:gn[eng0ng(:gG:[a(d(\u$d$\6\b6\D6d+'d'\v&\ѡ6dH&dWnWxnhWeh0h(nhNnW꘻\ >\>`Wp`)\J>\W>Wtd >d>k`ph)dJ>dX>`tQW-Group-ktx-d05d6ca/resources/example-configs/ktx/pwd.cfg000066400000000000000000000007631475442401000236120ustar00rootroot00000000000000sv_crypt_rcon 0 // rcon encryption (0 = off, 1 = on) rcon_password "" // rcon (disabled by "") master_rcon_password "" // master rcon (disabled by "") set k_admins 1 // allow admins on server (0 = no, 1 = yes) set k_admincode "" // ktx admin code (disabled by "") qtv_password qtv-pw // password for QTV connections (global) // change this password only if you know // what it does. otherwise leave it to // default value so QTVs can connect to // your server. QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/000077500000000000000000000000001475442401000232435ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/000077500000000000000000000000001475442401000245645ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/2bfree.route000066400000000000000000000004621475442401000270130ustar00rootroot00000000000000race_route_add_start race_add_route_node 1460 1000 72 0 90 race_add_route_node 1310 50 603 0 0 race_set_route_name "So you want to bunny?" "start\215end" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/aerowalk.route000066400000000000000000000045101475442401000274510ustar00rootroot00000000000000race_route_add_start race_add_route_node -488 624 248 0 270 race_add_route_node -688 496 248 0 0 race_add_route_node -688 -96 160 0 0 race_add_route_node -672 -496 160 0 0 race_add_route_node -272 -448 248 0 0 race_add_route_node -320 256 248 0 0 race_add_route_node -192 480 384 0 0 race_set_route_name "aerowalk: from GA+RL to RA via YA+MEGA with weapon" "GA-RL-MEGA-YA-RA with weapon" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -488 624 248 0 270 race_add_route_node -656 -96 432 0 0 race_add_route_node -272 -416 432 0 0 race_add_route_node 128 272 448 0 0 race_add_route_node -320 480 448 0 0 race_set_route_name "aerowalk: from GA+RL to RA via TELE - SNG - High RL - LG" "GA-TELE-SNG-High RL-LG-RA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -688 -96 152 0 0 race_add_route_node 32 -336 464 0 0 race_add_route_node -320 480 448 0 0 race_set_route_name "aerowalk: from MEGA to RA via High RL" "MEGA-High RL-RA with weapon" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -328 544 440 0 270 race_add_route_node 128 272 448 0 0 race_add_route_node -272 -416 432 0 0 race_add_route_node -920 -904 256 0 0 race_set_route_name "aerowalk: from RA to Quad" "RA-LG-High RL-Quad" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -920 -904 248 0 0 race_add_route_node -272 -416 432 0 0 race_add_route_node 128 272 448 0 0 race_add_route_node -320 480 448 0 0 race_set_route_name "aerowalk: from Quad to RA" "Quad-High RL-LG-RA" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/bravado.route000066400000000000000000000036641475442401000272730ustar00rootroot00000000000000race_route_add_start race_add_route_node -288 1184 152 0 -45 race_add_route_node 752 24 288 0 0 race_set_route_name "Bravado: from RA to Quad" "RA to Quad with weapon" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 240 896 24 0 180 race_add_route_node -16 1000 32 0 0 race_add_route_node -16 620 288 0 0 race_add_route_node 752 24 288 0 0 race_add_route_node -288 1184 160 0 0 race_set_route_name "Bravado: run over map" "low RL spawn - LG - Quad - RA" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -16 -208 24 0 90 race_add_route_node -416 176 256 0 0 race_add_route_node -256 832 256 0 0 race_add_route_node 640 800 176 0 0 race_add_route_node 240 128 320 0 0 race_add_route_node -16 620 288 0 0 race_add_route_node -288 1184 160 0 0 race_set_route_name "Bravado: GA to RA over map" "GA - high tele exit - near YA - LG - RA (with weapon)" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 240 896 24 0 180 race_add_route_node -16 1000 32 0 0 race_add_route_node -16 620 288 0 0 race_add_route_node 752 24 288 0 0 race_add_route_node 448 880 168 0 0 race_add_route_node -288 1184 160 0 0 race_set_route_name "Bravado: run over map (fixed)" "low RL spawn - LG - Quad - NG - RA" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/catalyst.route000066400000000000000000000041161475442401000274720ustar00rootroot00000000000000race_route_add_start race_add_route_node 588 -448 50 0 45 race_add_route_node 848 -416 48 0 0 race_add_route_node 1168 -332 256 0 0 race_add_route_node 168 224 256 0 0 race_add_route_node 656 64 264 0 0 race_set_route_name "Catalyst: LG to Mega via High YA" "LG Spawn-High YA-Stairs-Mega" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1600 304 0 0 -180 race_add_route_node 656 64 264 0 0 race_set_route_name "Catalyst: RA to Mega with weapon" "RA-Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 704 112 288 0 -135 race_add_route_node 1552 256 0 0 0 race_set_route_name "Catalyst: Mega to RAL" "Mega-RA" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 588 -448 50 0 45 race_add_route_node 848 -416 48 0 0 race_add_route_node 1024 320 32 0 0 race_add_route_node 624 224 32 0 0 race_add_route_node 224 128 96 0 0 race_set_route_name "Catalyst: LG to Healths at Low RL" "LG Spawn-Cells-Low RL-Healths" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 176 400 203 0 -90 race_add_route_node 656 64 264 0 0 race_add_route_node 144 -192 256 0 0 race_add_route_node 1072 192 224 0 0 race_add_route_node 1552 256 0 0 0 race_set_route_name "Catalyst: Mega Stairs to RA via GL and High RL" "Stairs-Mega-GL-High RL-RA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/cmt3.route000066400000000000000000000013631475442401000265150ustar00rootroot00000000000000race_route_add_start race_add_route_node 518 1192 -520 0 140 race_add_route_node 541 1692 -528 0 0 race_add_route_node 1085 1612 -688 0 0 race_add_route_node 839 713 -896 0 0 race_add_route_node 442 714 -592 0 0 race_add_route_node 1000 839 -520 0 0 race_add_route_node 1300 122 -528 0 0 race_add_route_node 988 122 -816 0 0 race_add_route_node 565 -331 -816 0 0 race_add_route_node -438 97 -344 0 0 race_add_route_node -994 53 -471 0 0 race_set_route_name "JohnNy_cz's Deutschmaschine race" "spawn \215 pent \215 lg \215 quad \215 ra \215 rl" race_set_route_timeout 40 race_set_route_weapon_mode raceWeapon2s race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm1.route000066400000000000000000000010761475442401000263310ustar00rootroot00000000000000race_route_add_start race_add_route_node -385.2 1417.6 24.0 4.1 2.7 race_add_route_node -398.8 1595.6 28.0 0 0 race_add_route_node -664.7 1104.4 67.0 0 0 race_add_route_node 83.6 630.0 51.0 0 0 race_add_route_node 939.3 1311.8 95.6 0 0 race_add_route_node 405.6 1565.6 62.2 0 0 race_add_route_node 4.1 1437.4 24.0 0 0 race_set_route_name "around dm1" "ya\215ng\215mh\215ssg\215ya" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm2.route000066400000000000000000000023631475442401000263320ustar00rootroot00000000000000race_route_add_start race_add_route_node 1309.7 -903.8 344.0 5.2 87.8 race_add_route_node 1498.8 -713.5 184.0 0 0 race_add_route_node 1896.2 -634.4 184.0 0 0 race_add_route_node 2613.7 -218.5 120.0 0 0 race_add_route_node 2714.6 -1735.3 120.0 0 0 race_add_route_node 2445.9 -1979.4 120.0 0 0 race_add_route_node 2246.4 -2473.3 200.0 0 0 race_set_route_name "ihm's quad run" "high rl\215quad\215water\215lower\215ra mh" race_set_route_timeout 35 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 2114.0 -100.9 24.0 -10.4 -109.4 race_add_route_node 2014.6 -469.5 140.7 0 0 race_add_route_node 1696.7 -1463.7 28.7 0 0 race_add_route_node 2612.7 -677.0 144.0 0 0 race_add_route_node 2304.8 -152.6 67.6 0 0 race_add_route_node 2397.6 86.0 41.2 0 0 race_add_route_node 2246.2 -194.7 -136.0 0 0 race_set_route_name "around dm2" "water\215quad low\215rl low\215ng\215stairs" race_set_route_timeout 35 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm3.route000066400000000000000000000027011475442401000263270ustar00rootroot00000000000000race_route_add_start race_add_route_node 1880.1 884.2 -213.0 8.3 -92.1 race_add_route_node 701.0 237.5 89.2 0 0 race_add_route_node 261.0 -709.0 328.0 0 0 race_set_route_name "ra fly" "pent mh\215window\215ra top" race_set_route_timeout 35 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1499.6 498.9 -88.0 18.4 -3.4 race_add_route_node 1400.3 -30.1 -168.0 0 0 race_add_route_node 581.8 0.2 -168.0 0 0 race_add_route_node 261.0 -709.0 328.0 0 0 race_set_route_name "ra run" "rl\215center\215ra top" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1520.0 432.0 -88.0 0 0 race_add_route_node 1252.7 -513.5 20.1 0 0 race_add_route_node 642.0 -511.0 88.0 0 0 race_add_route_node 590.5 125.6 96.6 0 0 race_add_route_node 202.7 593.8 56.0 0 0 race_add_route_node -711.8 95.7 206.4 0 0 race_add_route_node -221.7 -561.6 20.6 0 0 race_add_route_node 261.0 -709.0 328.0 0 0 race_set_route_name "around dm3" "rl\215hi bridge\215quad\215ya\215quad\215under lifts\215sng mh\215ra top" race_set_route_timeout 50 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm4.route000066400000000000000000000026451475442401000263370ustar00rootroot00000000000000race_route_add_start race_add_route_node 1199.9 -603.0 24.0 1.8 178.4 race_add_route_node -144.0 -227.0 -72.0 0 0 race_set_route_name "base dm4" "ya\215quad tele" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1199.9 -603.0 24.0 1.8 178.4 race_add_route_node 337.8 -673.6 36.7 0 0 race_add_route_node 296.6 -1205.2 9.5 0 0 race_add_route_node 336.2 -664.8 -104.0 0 0 race_add_route_node -68.6 611.1 -296.0 0 0 race_set_route_name "mh run" "ya\215top tele\215gl\215mh" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1199.9 -603.0 24.0 1.8 178.4 race_add_route_node 337.8 -673.6 36.7 0 0 race_add_route_node 296.6 -1205.2 9.5 0 0 race_add_route_node 336.2 -664.8 -104.0 0 0 race_add_route_node 360.2 -77.6 -60.3 0 0 race_add_route_node 200.5 -41.5 -104.0 0 0 race_add_route_node -129.3 -580.4 -72.0 0 0 race_set_route_name "quad strafe" "ya\215top tele\215gl\215lg\215quad\215quad tele" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm5.route000066400000000000000000000011451475442401000263320ustar00rootroot00000000000000race_route_add_start race_add_route_node 657.5 -296.0 120.0 11.7 -87.8 race_add_route_node 205.1 -778.5 120.0 0 0 race_add_route_node -87.4 509.4 79.5 0 0 race_add_route_node 496.0 369.6 222.4 0 0 race_add_route_node -84.3 -760.4 246.6 0 0 race_add_route_node 874.3 -210.2 232.6 0 0 race_add_route_node 141.1 -223.6 216.0 0 0 race_set_route_name "around dm5" "ya\215gl\215rl\215tele rl\215above gl\215sng" race_set_route_timeout 35 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dm6.route000066400000000000000000000016561475442401000263420ustar00rootroot00000000000000race_route_add_start race_add_route_node 55.2 -2005.1 88.0 -15.2 49.0 race_add_route_node 450.2 -1484.5 256.0 0 0 race_add_route_node 1735.0 -345.0 168.0 0 0 race_set_route_name "base dm6" "ga\215gl\215ra" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 209.8 -1247.9 112.3 3.4 43.0 race_add_route_node 1359.7 -427.7 40.0 0 0 race_add_route_node 1108.6 -1316.2 256.0 0 0 race_add_route_node 813.4 -1081.0 256.0 0 0 race_add_route_node 1015.9 -867.3 256.0 0 0 race_add_route_node 1632.2 -160.4 168.0 0 0 race_set_route_name "\360\263\247\363 tube run" "mh\215rl ra\215gl circle\215ra" race_set_route_timeout 25 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/dungeonsurf.route000066400000000000000000000012541475442401000302050ustar00rootroot00000000000000race_route_add_start race_add_route_node -128 0 -8 0 0 race_add_route_node -3340 1790 3320 0 0 race_add_route_node 3400 1800 1700 0 0 race_set_route_name "Lava surfing" "start\215finish" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -3340 1790 3320 0 0 race_add_route_node 3400 1800 1700 0 0 race_set_route_name "Room2" "start\215finish" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "tele2" RACEFLAG_TOUCH_RACEEND QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/e1m2.route000066400000000000000000000057441475442401000264220ustar00rootroot00000000000000race_route_add_start race_add_route_node 784 808 200 0 -135 race_add_route_node -96 8 488 0 0 race_set_route_name "e1m2" "RL to MEGA" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -96 8 488 0 0 race_add_route_node 680 728 200 0 0 race_set_route_name "e1m2" "MEGA to RL" race_set_route_timeout 10 race_set_route_weapon_mode raceWeapon2s race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1320 -488 400 0 -90 race_add_route_node 880 -1080 440 0 0 race_add_route_node -96 8 488 0 0 race_set_route_name "e1m2" "YA to MEGA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -96 8 488 0 0 race_add_route_node 880 -1080 440 0 0 race_add_route_node 1340 -544 400 0 0 race_set_route_name "e1m2" "MEGA to YA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1320 -600 400 0 90 race_add_route_node 1480 400 320 0 0 race_add_route_node 1112 1292 344 0 0 race_set_route_name "e1m2" "YA to Start via spikes" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 400 -1360 432 0 90 race_add_route_node 1480 400 320 0 0 race_add_route_node 1340 -544 400 0 0 race_set_route_name "e1m2" "QUAD to YA via spikes" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 400 -1360 432 0 90 race_add_route_node 680 728 200 0 0 race_set_route_name "e1m2" "QUAD to RL" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 400 -1360 432 0 90 race_add_route_node 1536 -384 320 0 0 race_add_route_node 1480 400 320 0 0 race_add_route_node -96 288 320 0 0 race_set_route_name "e1m2" "QUAD to MEGA room button via spikes" race_set_route_timeout 25 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 576 -416 320 0 -90 race_add_route_node 400 -1360 432 0 0 race_set_route_name "e1m2" "Cross to QUAD with RL" race_set_route_timeout 5 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/escape2a.route000066400000000000000000000006771475442401000273410ustar00rootroot00000000000000race_route_add_start race_add_route_node -3633 -1819 3748 0 0 race_add_route_node 1847 -2046 -3613 0 0 race_set_route_name "Space Odyssey" "start\215finish" race_set_route_timeout 90 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "t1" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "t2" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/hoppa2.route000066400000000000000000000005541475442401000270410ustar00rootroot00000000000000race_route_add_start race_add_route_node 1200 -3075 -24 0 0 race_add_route_node 1168 -1375 130 0 0 race_set_route_name "One way" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "tele_1" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/jqdf1.route000066400000000000000000000005521475442401000266530ustar00rootroot00000000000000race_route_add_start race_add_route_node -45 -1.6 24 0 0 race_add_route_node 62.5 0 424 0 0 race_set_route_name "You are not a Jedi yet" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "tele" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/jqdf3.route000066400000000000000000000004351475442401000266550ustar00rootroot00000000000000race_route_add_start race_add_route_node 540 0 88 0 180 race_add_route_node -2880 585 460 0 0 race_set_route_name "Think hard" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/monsoon.route000066400000000000000000000023321475442401000273340ustar00rootroot00000000000000race_route_add_start race_add_route_node 544 576 120 0 0 race_add_route_node -304 -552 216 0 0 race_set_route_name "Monsoon: YA to RA" "from YA to RA with weapon" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 544 832 296 0 -45 race_add_route_node 1048 -184 304 0 0 race_add_route_node 976 -792 192 0 0 race_add_route_node -304 -552 224 0 0 race_add_route_node 424 70 320 0 0 race_set_route_name "Monsoon: YA-Spawn to Quad via Mega and RA" "YA Spawn-High RL-Mega-RA-Quad" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 800 96 296 0 -45 race_add_route_node 616 -328 192 0 0 race_add_route_node 1048 -184 304 0 0 race_set_route_name "Monsoon: High RL Spawn - High Cells - High RL" "High RL Spawn-High Cells-High RL" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/mvdsv-kg.route000066400000000000000000000012211475442401000273760ustar00rootroot00000000000000race_route_add_start race_add_route_node 118.5 -1345.5 284.6 5.2 120.7 race_add_route_node -572.9 -276.8 330.9 0 0 race_add_route_node -111.9 725.3 466.0 0 0 race_add_route_node 546.5 -134.5 566.0 0 0 race_add_route_node 509.0 -1483.3 706.6 0 0 race_add_route_node -515.8 -1152.6 856.4 0 0 race_add_route_node 120.9 -829.8 889.4 0 0 race_add_route_node 0 -74.1 979.5 0 0 race_set_route_name "Bunny to the top!" "castle\215pads\215platform" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/q1q3toxicity.route000066400000000000000000000036611475442401000302340ustar00rootroot00000000000000race_route_add_start race_add_route_node 48 848 -88 0 -45 race_add_route_node 180 96 0 0 0 race_add_route_node 288 456 128 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 1386 360 112 0 0 race_add_route_node 1264 -160 128 0 0 race_add_route_node 640 128 128 0 0 race_add_route_node -108 544 64 0 0 race_set_route_name "Toxicity: around map" "Low Mega - YA-Quad - GL - RL - YA-Low Mega" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 352 80 -2 0 -90 race_add_route_node 928 -136 144 0 0 race_add_route_node 1128 608 -48 0 0 race_set_route_name "Toxicity: Tele exit stairs to Quad with weapon" "Tele exit stairs-High Mega-Quad" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 960 -64 124 0 -90 race_add_route_node 928 832 128 0 0 race_add_route_node 480 512 128 0 0 race_add_route_node 78 808 -96 0 0 race_set_route_name "Toxicity: High Mega to Low Mega over Quad" "High Mega-over Quad-Low Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -108 544 62 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 588 -512 -96 0 0 race_add_route_node -108 666 128 0 0 race_set_route_name "Toxicity: from Low Mega YA get all 3 YA" "Low Mega YA-Quad YA-Water YA-Low Mega YA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race1.route000066400000000000000000000004721475442401000266420ustar00rootroot00000000000000race_route_add_start race_add_route_node 0 0 -40 0 0 race_add_route_node 1376 382 -3700 0 0 race_set_route_name "Pillars" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race10.route000066400000000000000000000004631475442401000267220ustar00rootroot00000000000000race_route_add_start race_add_route_node -2988 0 88 0 0 race_add_route_node 1146 2300 -2448 0 0 race_set_route_name "Place of Death" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race2.route000066400000000000000000000004611475442401000266410ustar00rootroot00000000000000race_route_add_start race_add_route_node 0 8 88 0 0 race_add_route_node 1013 3486 -1240 0 0 race_set_route_name "Waste Warehouse" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race3.route000066400000000000000000000004671475442401000266500ustar00rootroot00000000000000race_route_add_start race_add_route_node -352 352 2072 0 0 race_add_route_node -353 -92 -680 0 0 race_set_route_name "The Cube" "start\215finish" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race4.route000066400000000000000000000005021475442401000266370ustar00rootroot00000000000000race_route_add_start race_add_route_node -2816 2816 2712 0 0 race_add_route_node -2918 1790 -1115 0 0 race_set_route_name "Curve Control" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race5.route000066400000000000000000000005031475442401000266410ustar00rootroot00000000000000race_route_add_start race_add_route_node -1882 2400 2840 0 -180 race_add_route_node 2463 -1793 98 0 0 race_set_route_name "Spin Cycle" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race6.route000066400000000000000000000004711475442401000266460ustar00rootroot00000000000000race_route_add_start race_add_route_node -2848 0 2872 0 0 race_add_route_node 0 965 -985 0 0 race_set_route_name "The Tube" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race7.route000066400000000000000000000004511475442401000266450ustar00rootroot00000000000000race_route_add_start race_add_route_node -2880 -768 2520 0 0 race_add_route_node -1378 794 344 0 0 race_set_route_name "Upslider" "start\215finish" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race8.route000066400000000000000000000004631475442401000266510ustar00rootroot00000000000000race_route_add_start race_add_route_node -1440 2304 1496 0 0 race_add_route_node -1479 -1788 -1000 0 0 race_set_route_name "Canyon Run" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/race9.route000066400000000000000000000004571475442401000266550ustar00rootroot00000000000000race_route_add_start race_add_route_node -2736 2568 2776 0 0 race_add_route_node -2981 688 -296 0 0 race_set_route_name "Forgotten Path" "start\215finish" race_set_route_timeout 90 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/rampcity.route000066400000000000000000000011261475442401000274740ustar00rootroot00000000000000race_route_add_start race_add_route_node -255 250 88 0 -180 race_add_route_node -255 250 856 0 0 race_set_route_name "Up you go..." "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -255 250 856 0 0 race_add_route_node -255 250 88 0 -180 race_set_route_name "... and down you fall" "start\215finish" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/rawspeed.route000066400000000000000000000004571475442401000274640ustar00rootroot00000000000000race_route_add_start race_add_route_node -126 -154 312 0 90 race_add_route_node -3195 -3422 -1432 0 0 race_set_route_name "Raw Speed" "start\215end" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/rj3.route000066400000000000000000000004611475442401000263430ustar00rootroot00000000000000race_route_add_start race_add_route_node 784 -112 48 0 0 race_add_route_node -1410 -1135 -196 0 0 race_set_route_name "So you want to rj?" "start\215finish" race_set_route_timeout 300 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/shifter.route000066400000000000000000000057141475442401000273170ustar00rootroot00000000000000race_route_add_start race_add_route_node -224 672 120 0 0 race_add_route_node 888 152 344 0 0 race_set_route_name "Shifter: from RA to Mega with weapon" "RA-Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 944 144 344 0 135 race_add_route_node -224 672 160 0 0 race_add_route_node 40 -24 168 0 0 race_add_route_node 528 152 168 0 0 race_add_route_node 864 -32 168 0 0 race_add_route_node 256 -416 -16 0 0 race_set_route_name "Shifter: from Mega to LG via RA and Quad" "Mega-RA-Quad-Rockets-LG" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 784 -208 -24 0 180 race_add_route_node -224 672 176 0 0 race_set_route_name "Shifter: from YA to RA with weapon" "YA-RA" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 792 -608 -24 0 90 race_add_route_node 784 -256 -24 0 0 race_add_route_node 888 152 336 0 0 race_add_route_node -224 672 160 0 0 race_set_route_name "Shifter: from YA Spawn to RA via Mega" "YA Spawn-YA-Mega-RA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 944 144 344 0 135 race_add_route_node 720 528 344 0 0 race_add_route_node -32 512 344 0 0 race_add_route_node 736 -512 344 0 0 race_add_route_node 40 -24 168 0 0 race_set_route_name "Shifter: from Mega to Quad over map" "Mega-Cells-Over RA-YA Tele Exit-Quad" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 224 368 24 0 90 race_add_route_node 720 528 344 0 0 race_add_route_node 888 152 344 0 0 race_add_route_node 736 -512 344 0 0 race_add_route_node -32 512 344 0 0 race_add_route_node 40 -24 168 0 0 race_set_route_name "Shifter: from Low Tele to Quad over map" "Low Tele-Cells-Mega-YA Tele Exit-Over RA-Quad" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -224 672 120 0 -135 race_add_route_node 784 -256 -24 0 0 race_set_route_name "Shifter: from RA to YA" "RA-YA" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide1.route000066400000000000000000000004541475442401000270300ustar00rootroot00000000000000race_route_add_start race_add_route_node 64 -3428 3352 0 90 race_add_route_node -896 -1152 -3840 0 0 race_set_route_name "Slide 1" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide2.route000066400000000000000000000004551475442401000270320ustar00rootroot00000000000000race_route_add_start race_add_route_node -1600 2380 2736 0 -90 race_add_route_node 1821 -714 920 0 0 race_set_route_name "Slide 2" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide3.route000066400000000000000000000006061475442401000270310ustar00rootroot00000000000000race_route_add_start race_add_route_node -1920 2208 -160 0 0 race_add_route_node 2504 2246 -160 0 0 race_add_route_node -1460 -1023 -160 0 0 race_add_route_node -2336 2203 -160 0 0 race_set_route_name "Slide 3" "start \215 end" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide4.route000066400000000000000000000004601475442401000270300ustar00rootroot00000000000000race_route_add_start race_add_route_node 3555 3547 3736 0 -180 race_add_route_node 3124 -2785 -616 0 0 race_set_route_name "Slide 4" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide5.route000066400000000000000000000006471475442401000270400ustar00rootroot00000000000000race_route_add_start race_add_route_node 2367 3364 3224 0 -90 race_add_route_node 1597 185 -1256 0 0 race_set_route_name "Slide 5" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "t1" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "t2" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide6.route000066400000000000000000000020561475442401000270350ustar00rootroot00000000000000race_route_add_start race_add_route_node 0 0 3534 0 0 race_add_route_node -1084 1958 18 0 0 race_set_route_name "Slide 6" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 0 0 3534 0 0 race_add_route_node 2605 800 3485 0 0 race_set_node_size 430 400 1030 race_add_route_node 1025 -2275 2200 0 0 race_set_node_size 500 400 400 race_add_route_node -1084 1958 18 0 0 race_set_route_name "Slide6: NO SHORTCUTS" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "tnw" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "tne" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "tsw" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "tse" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "tc" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide7.route000066400000000000000000000004501475442401000270320ustar00rootroot00000000000000race_route_add_start race_add_route_node 194 0 2072 0 0 race_add_route_node 2903 2239 -3272 0 0 race_set_route_name "Slide 7" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide8.route000066400000000000000000000022451475442401000270370ustar00rootroot00000000000000race_route_add_start race_add_route_node 0 -85 20 0 90 race_add_route_node -777 2527 -360 0 0 race_add_route_node -456 -64 -876 0 0 race_set_route_name "Slide 8" "top \215 bottom" race_set_route_timeout 40 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "h1" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d6" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d1" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d2" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d3" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d4" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "d5" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "r5" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "r4" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "r3" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "r2" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "r1" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "t5" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "t7" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slide9.route000066400000000000000000000004561475442401000270420ustar00rootroot00000000000000race_route_add_start race_add_route_node 484 -5 3602 0 180 race_add_route_node -3809 2450 -1109 0 0 race_set_route_name "Slide 9" "top \215 bottom" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slidefox.route000066400000000000000000000004551475442401000274650ustar00rootroot00000000000000race_route_add_start race_add_route_node 362 542 -1700 90 -90 race_add_route_node -271 996 -1588 0 0 race_set_route_name "Slidefox" "top \215 bottom" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/slstart.route000066400000000000000000000005611475442401000273420ustar00rootroot00000000000000race_route_add_start race_add_route_node -286 -504 3544 0 90 race_add_route_node -3024 -223 1432 0 0 race_set_route_name "Slstart" "top \215 bottom" race_set_route_timeout 25 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "teleskill" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/speedrush.route000066400000000000000000000013511475442401000276460ustar00rootroot00000000000000race_route_add_start race_add_route_node -955 -1140 2010 0 90 race_add_route_node -2675 -1155 -2984 0 0 race_set_route_name "Rush" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -955 -1140 2010 0 90 race_add_route_node -2675 -1155 -2984 0 0 race_set_route_name "Rush +weapons)" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "killer" RACEFLAG_TOUCH_RACEFAIL race_set_teleport_flags_by_name "start" RACEFLAG_TOUCH_RACEEND QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/subslide.route000066400000000000000000000004511475442401000274560ustar00rootroot00000000000000race_route_add_start race_add_route_node -1792 -320 2264 0 0 race_add_route_node -1775 545 472 0 0 race_set_route_name "Subslide" "top \215 bottom" race_set_route_timeout 25 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/toxicity_ql.route000066400000000000000000000036611475442401000302220ustar00rootroot00000000000000race_route_add_start race_add_route_node 48 848 -88 0 -45 race_add_route_node 180 96 0 0 0 race_add_route_node 288 456 128 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 1386 360 112 0 0 race_add_route_node 1264 -160 128 0 0 race_add_route_node 640 128 128 0 0 race_add_route_node -108 544 64 0 0 race_set_route_name "Toxicity: around map" "Low Mega - YA-Quad - GL - RL - YA-Low Mega" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 352 80 -2 0 -90 race_add_route_node 928 -136 144 0 0 race_add_route_node 1128 608 -48 0 0 race_set_route_name "Toxicity: Tele exit stairs to Quad with weapon" "Tele exit stairs-High Mega-Quad" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 960 -64 124 0 -90 race_add_route_node 928 832 128 0 0 race_add_route_node 480 512 128 0 0 race_add_route_node 78 808 -96 0 0 race_set_route_name "Toxicity: High Mega to Low Mega over Quad" "High Mega-over Quad-Low Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -108 544 62 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 588 -512 -96 0 0 race_add_route_node -108 666 128 0 0 race_set_route_name "Toxicity: from Low Mega YA get all 3 YA" "Low Mega YA-Quad YA-Water YA-Low Mega YA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/toxicity_test.route000066400000000000000000000036611475442401000305650ustar00rootroot00000000000000race_route_add_start race_add_route_node 48 848 -88 0 -45 race_add_route_node 180 96 0 0 0 race_add_route_node 288 456 128 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 1386 360 112 0 0 race_add_route_node 1264 -160 128 0 0 race_add_route_node 640 128 128 0 0 race_add_route_node -108 544 64 0 0 race_set_route_name "Toxicity: around map" "Low Mega - YA-Quad - GL - RL - YA-Low Mega" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 352 80 -2 0 -90 race_add_route_node 928 -136 144 0 0 race_add_route_node 1128 608 -48 0 0 race_set_route_name "Toxicity: Tele exit stairs to Quad with weapon" "Tele exit stairs-High Mega-Quad" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 960 -64 124 0 -90 race_add_route_node 928 832 128 0 0 race_add_route_node 480 512 128 0 0 race_add_route_node 78 808 -96 0 0 race_set_route_name "Toxicity: High Mega to Low Mega over Quad" "High Mega-over Quad-Low Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -108 544 62 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 588 -512 -96 0 0 race_add_route_node -108 666 128 0 0 race_set_route_name "Toxicity: from Low Mega YA get all 3 YA" "Low Mega YA-Quad YA-Water YA-Low Mega YA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/toxicity_test2.route000066400000000000000000000036611475442401000306470ustar00rootroot00000000000000race_route_add_start race_add_route_node 48 848 -88 0 -45 race_add_route_node 180 96 0 0 0 race_add_route_node 288 456 128 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 1386 360 112 0 0 race_add_route_node 1264 -160 128 0 0 race_add_route_node 640 128 128 0 0 race_add_route_node -108 544 64 0 0 race_set_route_name "Toxicity: around map" "Low Mega - YA-Quad - GL - RL - YA-Low Mega" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 352 80 -2 0 -90 race_add_route_node 928 -136 144 0 0 race_add_route_node 1128 608 -48 0 0 race_set_route_name "Toxicity: Tele exit stairs to Quad with weapon" "Tele exit stairs-High Mega-Quad" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 960 -64 124 0 -90 race_add_route_node 928 832 128 0 0 race_add_route_node 480 512 128 0 0 race_add_route_node 78 808 -96 0 0 race_set_route_name "Toxicity: High Mega to Low Mega over Quad" "High Mega-over Quad-Low Mega" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -108 544 62 0 0 race_add_route_node 1172 832 96 0 0 race_add_route_node 588 -512 -96 0 0 race_add_route_node -108 666 128 0 0 race_set_route_name "Toxicity: from Low Mega YA get all 3 YA" "Low Mega YA-Quad YA-Water YA-Low Mega YA" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/zjumps.route000066400000000000000000000005611475442401000271760ustar00rootroot00000000000000race_route_add_start race_add_route_node -3740 3950 3865 0 -90 race_add_route_node -3880 2720 3830 0 0 race_set_route_name "Zzzzzzz" "start\215finish" race_set_route_timeout 60 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_set_teleport_flags_by_name "start" RACEFLAG_TOUCH_RACEFAIL QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/ztndm3.route000066400000000000000000000035251475442401000270700ustar00rootroot00000000000000race_route_add_start race_add_route_node -688 240 280 0 270 race_add_route_node 0 -200 320 0 0 race_add_route_node -704 -480 256 0 0 race_add_route_node -168 824 352 0 0 race_set_route_name "ztndm3: from RA to Quad via YA with weapon" "RA-SSG-High RL-GL-Quad with weapon" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -320 576 216 0 0 race_add_route_node -168 824 352 0 0 race_add_route_node -656 192 280 0 0 race_add_route_node -864 -64 224 0 0 race_add_route_node -96 -888 160 0 0 race_add_route_node -224 -480 24 0 0 race_add_route_node -96 624 32 0 0 race_set_route_name "ztndm3: Quad to LG run" "Quad spawn-Quad-RA-GL-High RL-YA-LG" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -96 624 24 0 270 race_add_route_node -96 -448 48 0 0 race_add_route_node -704 -480 256 0 0 race_add_route_node -656 192 280 0 0 race_set_route_name "ztndm3: LG to RA via YA" "LG-YA-GL-RA with weapon" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -224 -480 24 0 0 race_add_route_node 0 -200 320 0 0 race_add_route_node -656 192 280 0 0 race_set_route_name "ztndm3: YA to RA via SSG with weapon" "YA-SSG-RA with weapon" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponAllowed race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/ztricks.route000066400000000000000000000070261475442401000273420ustar00rootroot00000000000000race_route_add_start race_add_route_node -1168 1632 -552 0 90 race_add_route_node 16 -736 -1024 0 0 race_add_route_node -1344 2816 -992 0 0 race_add_route_node -3424 -464 -864 0 0 race_add_route_node -2272 -688 -896 0 0 race_add_route_node -2868 3772 -480 0 0 race_add_route_node 976 -2032 -2848 0 0 race_add_route_node 3488 3504 -3104 0 0 race_add_route_node -640 1568 -544 0 0 race_set_route_name "Ztricks" "All 7 rooms" race_set_route_timeout 300 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -45 685 -743 0 -45 race_add_route_node 16 -736 -1024 0 0 race_set_route_name "Ztricks: 1st room" "1st room" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 3200 2900 -1000 0 90 race_add_route_node -1344 2816 -992 0 0 race_set_route_name "Ztricks: 2nd room" "2nd room" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -1200 3050 -1000 0 -180 race_add_route_node 3200 2945 -1000 0 0 race_add_route_node 3250 2945 -1000 0 0 race_set_route_name "Ztricks: 2nd room back" "2nd room back" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -3345 3000 -872 0 -180 race_add_route_node -3424 -464 -864 0 0 race_set_route_name "Ztricks: 3rd room" "3rd room" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -2150 2950 -904 0 180 race_add_route_node -2272 -688 -896 0 0 race_set_route_name "Ztricks: 4th room" "4th room" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -2070 -640 -904 0 90 race_add_route_node -2380 2950 -904 0 0 race_add_route_node -2416 3038 -904 0 0 race_set_route_name "Ztricks: 4th room back" "4th room back" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -2880 -2336 -2856 0 -90 race_add_route_node 976 -2032 -2848 0 0 race_set_route_name "Ztricks: 6th room" "6th room" race_set_route_timeout 15 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 900 -2540 -2856 0 0 race_add_route_node -2880 -2336 -2856 0 0 race_add_route_node -3025 -2336 -2856 0 0 race_set_route_name "Ztricks: 6th room back" "6th room back" race_set_route_timeout 30 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 3951 3951 3864 0 -135 race_add_route_node -640 1568 -544 0 0 race_set_route_name "Ztricks: 7th room" "7th room" race_set_route_timeout 10 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/race/routes/ztricks2.route000066400000000000000000000053671475442401000274320ustar00rootroot00000000000000race_route_add_start race_add_route_node 2512.0 3632.0 344.0 -0.4 116.1 race_add_route_node 113.8 2349.1 -616.0 0 0 race_add_route_node 1747.6 -606.7 -168.0 0 0 race_add_route_node 2298.9 1513.4 -264.0 0 0 race_add_route_node 961.3 1692.7 536.0 0 0 race_add_route_node -483.4 642.0 632.0 0 0 race_add_route_node -1983.2 3314.1 704.0 0 0 race_add_route_node 3032.0 3632.0 344.0 0 0 race_set_route_name "Full Map" "start\215finish" race_set_route_timeout 300 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 112.5 -634.3 24.0 12.0 90.0 race_add_route_node 113.8 2349.1 -616.0 0 0 race_set_route_name "Room 1" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 768.4 -639.5 -168.0 1.0 89.0 race_add_route_node 1747.6 -606.7 -168.0 0 0 race_set_route_name "Room 2" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 2304.0 -640.5 -232.0 1.3 90.0 race_add_route_node 2298.9 1513.4 -264.0 0 0 race_set_route_name "Room 3" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 1093.5 1725.5 728.0 0 0 race_add_route_node 961.3 1692.7 536.0 0 0 race_set_route_name "Room 4" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -1442.6 1930.9 632.0 6.7 -91.0 race_add_route_node -483.4 642.0 632.0 0 0 race_set_route_name "Room 5" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node -3743.6 600.5 952.0 6.4 90.2 race_add_route_node -1983.2 3314.1 704.0 0 0 race_set_route_name "Room 6" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end race_route_add_start race_add_route_node 2960.5 368.0 888.0 1.0 89.0 race_add_route_node 2960.5 2251.2 888.0 0 0 race_set_route_name "Room 7" "" race_set_route_timeout 20 race_set_route_weapon_mode raceWeaponNo race_set_route_falsestart_mode raceFalseStartNo race_route_add_end QW-Group-ktx-d05d6ca/resources/example-configs/ktx/server.cfg000066400000000000000000000004051475442401000243170ustar00rootroot00000000000000exec mvdsv.cfg // server settings exec ktx.cfg // mod settings exec pwd.cfg // password settings exec vip_ip.cfg // vip ip settings exec listip.cfg // BANS :) // setmaster master.quakeworld.nu qwmaster.fodquake.net master.quakeservers.net QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/000077500000000000000000000000001475442401000234615ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/misc/000077500000000000000000000000001475442401000244145ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/misc/flagcap.wav000066400000000000000000001537721475442401000265470ustar00rootroot00000000000000RIFFWAVEfmt "V"Vdata~~~~~~~~~~~~~~~}}||||||||||||||||||||||||||||{||||||||||{||||||||||||{{{{{z{{z{zzzzzzzzzzzzzzzzzzzzzzzzzyzzzzzzzzzzzzzzzz{{||||||||||||||||||||||||||||||||||||||||||||}}}}}}}}}}~~~}}}}}}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}}|||||||||||||||||||||||||||||||||||||||{|||||||||||{{{{{{{{{{zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{{|||||||||||||||||||||||||||||||||||||||||||||||}}}}}}}}}}}}}}}|}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}||||||||||||||||||||||||||||{||||||||{{{{|||||||||||{{{{{{{{{zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz{{|||||||||||||||||||||||||||||||||||||||||||}}}}~~~~~~~~~~}}}}}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}}}~}|||||||||||||||||||||{{{{{{{{{{{||||||||||||||||||||{zzzzz{{{{{{{{{z{{zzzz{zz{zzzzzyyzzyyyzzzzzzzz{{{{{{{{{{{{|||||||||}}|||||}}}}}}}}}}}}}}}}}}|||||||||}}}}|||}}|||||||}}}~~~~~~~~~~~~~~~}}}~~~~~~~~~}|}}}~~~~~~~}||{{||~~~|}}~~~~~~~}}}{{{|}}~~~~~}|{{{|}~~}}|}||zzyzz{{{|||{{zxxwxxxyyz|~~|{{zxxxxwwxxxxyz|}|zxxxxxz{{{{zyxwwxy{||}~~}{}}~~~}~}{zz{|}}{zz{|}}|{{}~~}{yxz{{ywwz}~|z{|~}~~|{{|||{yyz{{|{{|}~~~~~~{z{~~}}zyz{~~{yvsqrv|~~|||{{zzzyvqpswy|}}~|yxwwy|~}|}}}z{|vrollpqsssuwz~|yx||xvtrttxz{~zurtwz~{wsomsxysppux{}~~}xtqllqx{|zz}yvz~zustz~zsqux{|wqmotz|~{|z{~~ukimpsuxyzztjglpy}wwz}~}||{wux~unorsz~|wzyqqvy~zxw}|ojpx{{}||~~{m`\`dly}ww}}~~~umpxzxvusomnsz{zzxuoklou~scXZ`gr{|}}vpoz|sjkrx{|vlpu{|~yy~}~~vou~|xy|{qdY[`ilomhsvw}sou}yz}spty}yy~||}{tommlqnbjqnrzsnu{njb`hdeqvwwsoqt}ufcgusjg`]QOWgwu}x~zh]eos}}rccrvjd]U]mpx~ysk`gyxwotqv}wurvoljvqgWY_avmWTXed\XYjwveYNCNSbqn}vlomz}v{z~}ylaI=@IX\gqqvvsuqqnks~|{{|opx{}wrx}ty}tk_bltjYalrty~srierz~qlnknqogn~ux|rvzwg[gorzt}vs}rpp}xkdlmeillsy|tqw{pdZYUZgc\Z^szpsuvyoghp~z}xfbktgURT`[OSUfyf[acptkhcc\Ybjmfbn}~}uy~urqny{utmonkmkqnfgfc`Yfvunqs|sx~}yrnppslm}wqw~sjghf[iyqu{~{mlsystyt|yhddkqwvswtphfkspk~zooppm]dknl`[[[Uj|~~{nmiit}yvyrwyqnkiy|qnjq~ykd]ZWWddknfjkrru~y|~qmcfrvtgdijkzy}|}phnrsmgmnfm}|tt{}{{|rmx~qjprozyhjswvshgil|vgcibdmfdpw~}xsvt||wztrwsyvt|z~xqlbafjw}}||wtxsjkg[UW^inrmhlvysvphr~~{x~|q\OLT[]`_enw{okpjkx|{tvztqvyng^PNS_kloy~woolrzzv|t^\aisvy~zxz~ophjtxuornmiht|y}|ocekpvyyx|oeddoz~|xztsxo]__fov}znkehp~vc_ZZbltzyurkc^]YUZ^cfpzttyva\[`cfswyzwuhY_en{tor}zps}}|ytpdWSXdhjrngilod^giq|rkrnjrv~xusifht|y}~}qe^iw}~|~vf^hnkkqwz~}tutqqf^_o}lqxtuu{{y~xnkedklpzsrw{whcduwslgq{~yzvu}}nhgnolfWU^ivo[VRZfceebp~~xvyifjsroj`ZY_g`VWWcmheahxu|lgmiigZYfigje^gq~tqv~tqkgebakommc\m~~rmtxxxqtuvyrhihgnrptmjlhhqvppi]]fuyxx~pgjmt~~st|{tqjcelx|uqk[RSNUZbrt{|rloqnmsy}}yojpvz}yuun^QQVZejqryupqpmlkfjqqioyquwtkjikpsppxz{~~}zwpkledfl}wkYNX`ZUU^ju||vt~zqquueZZVSW`feeghknopljd\^dqv{{vihgox{~wkXT^d_VSYfz|zysuyyvuztja\]hliel{|tsxwvvpljjouy{yuux}zz~}~}xojptvpe\X_goolifjhc`]_cnvtru~xx~{{rhec`bda]\_a^emou|}~|yvwvuvwtu|wqpher|}vspkjnnnr{xphgjllostttpikjhowvrx{rZQR\fjhgp}ynkggluwv{vsuxzqkiivvuu{~wnprrry~zl_alyxqruyzthYTYes|yy|~}~~~{|ztsnjr{unt|xqyssng[PP\gtz{{vurkhdhuwou~|ps|ty|tndZZ[afjnkpqtyytq|v^U]nxz{ypvss{||wutu{zvvzzXDLavzts{wqt}zmhmuuv|zxi\^s|xsjchy{|tg]dt}o^W^kz{|~|y{u`V[m|rhkuyztmic\[bkppi^MEQfokdeq~|nhnz~umkfZWeuueXZdfb^_jvy}vomijouz{rrpgi}yuv|xvx~|n^OIO[fpkbjv}|}~zqlmv|uthbgjjg`^ckt{vmuzqoovxvvlddcbjtz}~~{~sjrvniju{mhd]Z^``^V[imjcao|vmx||lbYSV^`ZVRR_kmw{~~|zw_POLMHIOSU[cb`gmxw|}{tmfdalxeTUW]bbbgtnikrznfiqxtfm}~ogdeu~lbknqh\``lwzzjbkx~tllrzxgs~k\[bntykemxvnei{yy}o[KFQdp}~}r]`kolov}|iUP[q}n_bh|~y}k[afe`J=EVsr[LR`tz}yjr|pecp{y~kWQQ\fny{_cr}|v`UJOhrx|hX\^fuspqiebl{rbL66JUY]kzx}d]gmxzq^[cjttw~yrvuabjptyzv~kTGHRbmt}zm^V[izx{{}{S?DTfiinkojozd\fc^^]^ow`[`flw~yzzo|dasrnykcuv_GCLWj|ucgrt|}u~rbbmjZG;ER[iv}~xvhQLamnsz~tquplnu|xzrpgn}}fUIQVSORZ]k~}ia`myvv{~spuzlQOYfw{y}tyqx{yuhiztv{~xxvnijhlqgI2O\QMSQXdaduolrpk]Wdhe[ZrŴkSYry|iLKV[cfeun`M424DLMUaqvg[h}|rhhv|}yr`WW\]]hx|}~~{qm~|ijhbbicWXUF5)&4KSQ\dw~aVY^ZPF?==::HRamhn{vjh^R@.*$":F@BA\Ƽz|se`]db\cd`_UYcl|yvsou~ryth_\]c_fpr}xcWU`xul~regdafdkk`ZNPZaomaclvqga]^ZaqsccotufSQXei]SIEOYXY\VURC66E^oz{rlrw}zpYICHWcmuyvszwqkaQMVg}yjhrvq~~yxrhs|p_QTlyqomvzj]]gu~{uvp\covue_ktpls}|om}}j]p{gbsphw|nw}urgm|vdTNS`iekxusqkn{~zx~yqjV@8D[qysgdfhbdgbce^X_t||zu`UQT]eip{r[JTmwqfjqwrkecfrzllr{mqxnprfZ[ao||k^^dnt|~¹~}v[OYgjjieovtmgfjj\V[q}{vqaK;5DZcYJHWlvxstzovrknsp^MZrjL=IVZURWfnnjj|p\]n|uhelrocUQRM>77BVhmf\b|l`[feXXdy|murSFADC:9K`nywrowvbUIHFD6*+6>DII\o{uz}ud\^a[TR[ceb\WV]ehgp~|wvxsf^^]]\\`ekljltz~smi^YV`rzysf`cgi]RR`mvy{|tmd]SMLOU_bozy}vg\buohnpjaW[guqh]]hsyuqv~{y|ywvuj]OHHNSVZY^`eiemxsrn_RN\p}fRP]chdYSVXRLRct}zldbozzr{}wng^TSW\\bjszogZLFKVfopr|yx}~zor|rtz~{{}}sswxk\TScmsmc^_fh`XbmqvwtubZ^cWF;>K^cfs}~rms}~qdj~{}l]^jtk\TSPPL?15IXZPP[lzðyprwjNJ^s|scbff`Y[]boxlfhpichomZYek`QFBH_zvcRTastq|unjcS;5;KQKKYoo^G<9DZfhkp|lUO\sroz}qd\UYbdZV`xy~|oZOSXabVA:>JPJSgwm\LJN]w²|sh`kzxcI?;IhǴynlngd``ceaVQVYE.!"-D]_[W_jvvw}xtxysidbjt{_A7=N_v}wpjpw~olwzyvmbcoojihV@8BOdxxrponnaYdzzkny~y}liljdUM@I`mle]_x²slqq_HKQ^_WTS^uxlmox|zz}|cWUUN:*($8NSLGKH<*)0?_zl\^p~wgK>161/;Ts|qyйvd_caUSVhscdhfbfbftwgKL_z~wtrƳywwrYDERixpZR[r{}ysja]av~}{r^H918HL@:FIJ7#'8Wnpdivtim˪zhktdK49>?3*Klwq{yfVVc}~۽xwyeOJ_dW83,29FDCFPfnx~woh\bnux~ǿzxwsvyziPDKZRP^it}zyq\PRPQOMOIGEQWUkvtaP6/9>FFWnvy}úum}}bVRRODC?;75>@Qq}iZcwwrvȼhmy|sklkg_QPPLFFPXrqj{ôyeqq^ag_R<=MTUSSKVittp^Rgwzy¿ʱz}xhPNQRWV_v|yx{ykm}mw{e[^UH,%1?8*6BOo|jjw|fcfYJ=>=B>-?VYSYjku}}zu`Q[eioyypjfdecKBW_WN^vxrppieafzzkbUNLO?CVsxioç|q`[P=5BA=Rb_MOlw|uot}¯zY;$')%-629S_N5Hnugdchz~{|nejbH79739D@0Hvwc^kĻ|½pgusWJLXkcZ}|rqqto{ǺkXRYhY?29FTdpa]ymqqqͼvID?ISDNljeo~bQJZbQG<'(.*2@66KWatøveC0(!+#)@EJSmķvvhc_BKA8=0:WLXoη}p_G[bKRYelbWST]tslpe]h`PYPUwnpȻȼzdM?<=Rc\WMES]PTVLmr}r{q[; &+:1Hez|ndmwotePU^LB5 /1!/Mmtk_]mÿykcc}~gSWotxq[htbex}fTS`~k{ran|iafz}mq|wpUZur|ϲйkPel^htu`W]sxputl^<;YZbs|nyͽǿojblkJ0,8UoyzhUU[XTRQtz^Ye}ɼxw|uyv\=P]R]hz|WDJg~szozuhgU5E\btswaxto~}qYM^|{eqqbcS1;PRs{vceO@IKcwjUEL^gszePY[XhlUZhgɱ¸|roS86IEGXUBMYLHH*24KkvyŻ~revz{h``K@;' &,CdlwznuǾȿ|mbknj{{suje`D,/5E^a_cYOQ_vsfoyw~xsrZ>?Nbz}|}jhejokhkjlqw{~jRO^v~z[IAFS[dnh]VY\P]vtfjju{e\cz˷pWFDF;CdtlliiukP?;XĮ{r~~ma^]JAZkXE5*38/*(=[szzuuyt|vkhijVQjzobXPVR>)$Fcwypgftb_rwxwrq{}tVayztplmpqjROpƶƸ~s`B?QZc`dknr{x[X}srp_I_żȷywjdVF>:=NWB9\~znhebaXKg~xzŻzr{xxoG.ARH658=GNF2Bbt~tpvԳƸsojlz`@WxxcNE=:9( '@QKJTc}ĸv{}x}tS_vfhjkrreejffi{uf]Txujf_XSMI_xyxw|p`WZ`a^dtz|tr{yzv]Tql`YNFA<;Qm|~tu|pj[F55GRX`]E:QdcZY[`gkjjt|ȱqaa`Y\W< 7A@EINSUUOSi|~ͼƽpwok}qbSGA7.&,DZfe_kxƸzz{gYfx|zrdccaXKP[_aVURWlŴ|qhYJVikkdTW]ZPI[t|}v~|mhuz|tfY]s}w~opsvvko~}xr{}|sqfVRH:19T\eghfTTgosvkmqu|uyyrxzgY_[RM@<31J_dja]bakll|mds|tpbYM74@@A=/+$-:@Vhcafx»s`XbpgaYSVQTfjmoji^\]RSZNFFT]`qt|ysqkcZalfhqf]]ipns~z\Q^z}zy}|zsghyujlxɺ}}wt\PVkrd^]msek~w{xrfJ11@J>89Nd^]kmnspbXj}|˽ɼ}{bKO]mg^U^l[LOJ>83,2N^]`]OS_r{;x`\_fYLHR^RIUZROI=5DOLNH59Pl}|Ʒwnt}nkre^iaTRKCLbhmxpjsŸ}wgl|yurnfguuqp_O]o~{thv|bSXblb[cx|qhrsmk`UbrxrP=BGNHK]oxbS^dWVSMWsԽ{]MV^je_bgjS?ELADG=@T_^_VIVpʰkWZZ\WQWbrmetujbMFQ]``ZPb{Ƚsussolv~vZR_ZMF4-S`ZWbz˾y\NWfnfXVS`ofTCDT^UJP^yyjfny}twr^Ze_N?BRZL8:CZjjhk|v|xqshZZVG/)+8NWZZj}Ƕ|lYXjstkgecuj_ejkYOXfz{mflrqowufZP]ur\U]jraV^r|qs~zklu{i^jyysngY[^^L@K^uëxdXcrwpdXLWttYQ_lteRU`mqmb]q˻zuvbPAGfr\NYgtgLL_|{}|oyys|ohorOEBD9#%:Vnwwtӭqqvq\Tgzzod]fxWW^ifMFQevwiW]o{ns|~hW`ig[QJRjziPVeyzecsv{vv|x`Oa{|jZYeskG8?MYK?Ibśwhl}pX`yxeVXex~fX]ciV=Qhpc]pǮv\SampnhfklojP<844CPIHT^pyy{~~{supieiocY]`lwyx`VX^mud[_bcWJHRYWZ]k|tmms~t~mYY\dhiipyupgcfiunYQRXiphl{¼zy{eRZjxzogdVH68?:7Ke{xpw~zx}~sY?57BJJYkx~|}zz|}ulksr\RYeb]afqveUVZXV]eq|xdZ^mvxĽpji[LJJO]\\jz|uuwvsv{wf]_n}Dzj^dcYZ`l{u`UPI@>CITbs|q^U\fa]j~~zxzp^Y\YMHKMU[]XE1.:KOSdͳyqgbcdg[H>CORMPWcqjbjtxsru|wcahollpuztb_kvvu{|xtntzzvywsuuytfaiwwrvsa\^XMFGVd^X`gf^ZYY_iw}nbfrzut|g`baZX[en^HDHLLOZdp|{mmw¬}ldiqcOPROHDFCBCJN;,5IZ^`kzuukicabfhVHN[_UMShndgpk_htyzx|iPNX]YV]o{ppuzv{~yk^]lunmvula_fls|~ynpuzr__hle_^dx{sx{{vu{~v¾}b^ficXMHNRIFOSUUVZ^`fmgTQ^jos{Ծ|mhpvngjig`\[Zapqp}xz}q`YVOHDFDDM[YG9BR]bgir{w~~z}yz|obWS_jgcku{|{|~ve^ixxqtxslgdaer~yqutjefgekwzk^\`bWLCEVhkhjle`_\X[itn^W[grzodbfaYOGObifhnmlnnhepzpr}ȼwhXSZVIFJKKMONLVipe]`lyyri_bmof`ahqw}~}~|~via^ew~z~rhkrsspjpxvtvvw|vuz}wofgutgdea_cfdao{ros{}~xxzzqja`ovonrqpsz~vv~st|~r^UVYWPKA?MROSWQOS\_Z^ozsjls~v{}na`kibdijjklkgqunoywtqh_YVRKKXa]RNQ^m{}ojqppttsy{okjic]WXisszzjcgpyyswwljprrsv{}~uknpqtw|zrt~}unjfcecdtzpt}|okvxwĺwomkg`ZRT`c[\```bhnlnztquz}}wpxtcVQJHT[VZb_[]didafqqhfo~z~mb`[WX_fghlsn`]j|xqkiedr|yz{}|rf_b^PINZennggkhfltuy|ypog`hpmlptw|{~{tv{tposqmw}x|{tquxsnsuqtyqha`\V[`ZV[_`dkmkfgqxqlntw||wvvljgijlxuuuqrx{wpnw||rrpbW[`_dr|{pjqyrkkkmrwtquzzyhaejeciosxzvrspfgswvxx{ph_[]YZejcdp{}vjge``ioq|{xztjfaafa^fkeensps|{v{ytppv|rlnkejwwsyzzwx}{vxzsr}y|}m_]^`jonswmbhtwrpnihp||}soohdn~sorv|}{rjdco~wswuecr{xsnmtmehiddbahtusyvqrpnqps~ywtu~{rqpnqtsrqmju}zy}~xxtfan{~vfff]VTTX\]]eu|}{xvx}~jahruupf_^ZW]eecfhefnz{ocbghimnnvzss}wwogd_`ipq{zxfdmnijjkrulht}~}|yz}~zxyxxunfijinyyw{gdtxv{}zuqotmjrpjjfdlpmp{wwkabdgnielojmv|~|rust{|z||z}~qt{xqne`ila]fnstvocct~rc`hnc\\\fuxzsqniie`ktttxzxvtqger}td`hqmlnhhooowy|vvwrosxyoouod`[]kqpu{xw}|zxszzqptqmpicggcefddgpzxkjlnkjfdozwsv}ymkdemmjpzvqw}|zvos{xrsw{~zsms~}ynnvuuz}xwxuqrmlwxmimu|wz}wrkq~~{mk{{}|sg`YVdeWSWaitvng_XZY_txlginvyty~zxu}w|{mfilidc]]ijda`dmzzkfloeZY[jzuqu{}wle`jrjhnrw}sfenz|usptsmkjr}z|}}{z|x{xqij|vvwqe_`dqyqowxwyrlprvyyyusrrsv{shZRNO\fbdhktykhrmbchpy~vqngfjo|vpoqxz{y|||{kbbdmk\UXaosc`abciggy{pjimwrbXX\ismilpy~tyzvnkso]VW_iorqln{~~~{{zqb\VYksmkjkry~zpoy|uogdgiq{zzw{~yxtunb]]bgpwy|thVMQZjxqeen{|}tqquy~}tt}}i[USOR\blyuiehuzn`YZ\^cb]ex{~pe^\fmd]bqne\X]cmvrgep~yswvoheouohikpv|{uuzrsuqoneVT^l|wqka\^`i}ynnqtw|p`VLMTZcqvvyrvvgUMPZizp]SLNV]_`\SP[kzxtvy|{tv|wnkifgikonaX_qumpy}zxrdZPJCCHPPVizyty|vzocaimmmi\Vansrqmlv}vnpvrruyyrr~{yzznfn}phfmsk]TSU\chrywnjnpvl_YT\iw|tninrna_jwwa\[XTNGFGCAOey}vpqz}skjlnuxqger|l`VORROKILWo|try{stuw||{|~m[OB;>DJORV`s~sr{vssrwuojjg`\XUV`ksz}|ztyyrsx}Żym`[]iz}sg``jwzwuuw}}|}yma`itupzypos}|orzuxwmfb_ZYcq{}tpy{phcfihhhjstqolnoh^XYaiomhgp}snc]WU[bhp~~pc`gnsrjbbl|}iQ?63;@EMQT[k|unnx}tg^TSRTZ_abj{ztqsuqlicZTYgw~thaXQPOPYgw|uqlu}wttmhbZUV_lx~|nfgx|vutnljghkotw|}vop}zkffmonryvqsvssnhegmqos{zww|nb[^\XZakzyi_\_ciqnigl~zeWMHNQPOQXbjoruwpieg|znjxyg[UORROPQWdturywywbOC:48?HWhvsbY\wzyvple]X[iy~||zvqi_[\dy~vlhgghdaabhlkottspp|tldddhs~|qmnuwyxrmklrvzzz{z{wi_OHEGOSYet¾se]Zakou~{skcWRQPSUXanz~von{}sicrwqj_[XTRS\j{vto[F=:>HTaox~pdah}{|}|qlpu½xwx{zrlhfei|}ma_chkgcb^`cdhhb]^g{~um`UQOS_m~wko}{qlmmrsrod^ZUVcmxui]ZWW[bp}ƽthUKNQ\how|xskguvsnhcYSUYdlo{~yzxrmf^[Zbzxm^QG==EQfywrsq]PNLQW\lw|xnghlt}wqlcaefmv{|z}ypjkkirz}yxt{xtspsxtjhfnxztkhlp{}tf]]cnvskbixwvytopppdPINXix~z|mbb_Z^blyƸvlfXMR\dqxvn`ZVZl|jaZVVSXerĹ~ulbafjxrdSB;77DVksl`bv}~oifiwml}~xVGTj}|jSJMP]_QILZrz{hcivb^ew~y}reZ[aj}nbW`zscUUc{yt{}h[TPW\eqbas{{|~hPILXa`VOTZhnjkil}{|piqumb\Z_{q]]suigiqhSIISgrqmfZalg^SMQ`vob^_jqkd\Zccj}rf[Y`xyc_l}xeSIM]ecb]_nzlbn~xqeeuvdNAGWTD==L_d}ugZZxtinzqfgoj~wb\j{^G@Wuzh\^lvkdn}{xleizwuxxzlaq{}ucXev^OGB@85;@M\`|ɼh`vvf[av}ocdhr~viig_n|yx}v|tdRDAJcok]LHOY[NILQcv~zmmy~vphPFFOP@57=IS[t{ojyyx{t~}{md\[^c}|usr]J?Pp|rc\Y[chhjlw}}fZOJJINTW_esupxytni||l_X^u}uoh_]\i|ucWTXhrmeTEGKOJCELYo|ygRLJH>2.124Ia{vnfnzkyvi]M?65DVjyvyp^aouyi^Znuif_\agxv{whfgmuwrv~nWY^WUQKDCIYj|whgbn}oYE735BWs}t{|uy{k\OJ[sxkfYMXYUTNPU\l|w~uszvpqlXURJLC4("*?Wu|f^QC6+5G\y{o\NPRUay}}qmk|wvxr{ih^ZVSd{|n\gkb`QC5.A^uwmv{{}vptugdejuhYSJESctwv|~uh^Wfk\ONMRhcWURN??Vq|pm}upstlZ_T>2# +D^wvy}yzwxcTEEC@JYk}sozz|sj`Xj~{taIB=40:\yzz{xlnxw}ztg_S=9>Oo}iaY`okjlkh]]u|wt~}kMEEK`rvzqsuyulg_`wzmZMFDAB@*$)6Vu{mb`\[X<,),DXamnhqx}z||vssk_V9& ;Ynth^gztu}ž|~spZRPTm~g_Xbwwkcdgli`hd^lmu¹raO656?`xwqsquueZXboelrefcPNGLev}|m^VQjynecbs|mXH=@QRPF05>Hi~vr~yo~laf^QJ0##"9Tjzyosqnƾ{lurmiOB@=NapwgRLEH`u}~ʵiwnnrL77Fhz~xtqa]nvnoe_hk~̳vwcTK739Jkyyïrlgowttndfjfx|h`ct{wm^W^_iv}|bVUUgu_RCDUUJ<( *Iu}wxvugNIQG. ';M[\POY_r¬z}zxvttnyxgI/)9OangWOKK[www¸ufZ[sughslT>(!,Eetmbbq|ynmwvgcnŴumpjTL?.1@Wp}j[^ex~wysbZVYtmRMVgz}zx~zbTQUl{`I>?LRLO>(;aø{x~z}`Z\acP5' 8QUKJSf{px}x{fY8 1NiqfWQRHLhzxŲ~y{}ndbekZ?9*2IfiYRSPWkqecq|tlj[fȷseI05Jhtkost|u`]cgmk]TU]ht}cLMO_|ud\bem}|uvz~t]``dng_^QHHKh{iejks}yoz|}k^J=8& +Iluqef|Ƹzr~jZP?3/2IegV?8EPbqptĿ{we^RGBGl~[JVdrpYK\xpffu¼v_OGFIOYp{qgYXdn}ialvw|~vukjx{h[PE;15P^a]Ygy}|nXN_ru{pbUWcfjwtz|tm~zwmhr{qoo_M?0'%,29BWcb[R`sȳ~fNE=,,1BW\SFNcswmfs̾rueL>@IGGWkwwcPVgtmdiuy~vrvqgXMKS[WVajeZJI\tnmtcizt_YWE?Tiwwkiv|hcy~sxvfI>DLMScruwk_hlt{gZPNOG5-!!6Mi}virufo||zzs]D2.7H_wswfT90//9?KT\ifSI>-)8TxtYO>6?Nfxndmyzlbkz˻x`IEDJXbedp|h`g|{`PXcrwnc_l}hG<:?L`qu~n\Vb{|bQN\nxlUNGBCERdw]CD]xojgmzz}bM5$/AQ`|wvyxŲ÷nc[UVQY]cv{ql`QII_z~yzgM92('9KZfp}}wq^F4,5Ibmgdb`_hɭm`[SVjvz|ynlvoZNHQ`geevzrz~dT>5@HUdz{cUZl{xjen|wh^UKNaq{yaRXl~wŰk]RC2+5BP`ssljuyxYG3',.ASbxs`ULN_}w}meWECJOXguvy{bH>9;Kdtxrlh^T]tʪ~lidR<9@72AYno`V_yn]YPIXq}xryİnZF44BNUkxu~raXPIGTglkmkkv|rf_[ZnubW^wsd]hvsXMC5'%17=Yt|w~}roptþlS7 &:@;GXl|j^SJQaq~noļdULE=;EB7;Rhtchonpwz~ry\EAC559/0EQHRjvznqlgyyzž}w{_OUXWgund[[O@LSLKH@M^~s]VPCIK=Eapo}gKOPA<>AMO^vxuxͲxj`lxvtfpzyxz}pmhy|rkq_KQ\hwk]\K?8;M_|}~w~wdR>:AJV^UQg}xujoǼwodPNVM@@;=DQgponxws|t^E8:IbwhkypXNL\]Zr|o[OB>Sd^LOgžķ~yhf|jbbWVSC2-04DesirŴqm{|yrYDFEJ[vrin}ymul`YLDCOdzmgo|h`h~uzrvx~ncdgq~yiZW^oidb\DALC>Tuwpxn_dtzzsmVGJPVarx`[jol|td^MBJc|{yrYMOZ`aWF?@JMS[I.)E\^jlcckxi_`ixeYZYSQ>-1P`XRC5ES[OKWet}st~zv}omskejgfjo_HB?=CIRYgeOYo~{snvuvzj_fm[N`t~ydNIJNWsvo}|{~zucmqm|vxzw|okokjjYE=FZixhUNY^Zjqg_ff]gw}laagmxta\XPH[yzkdcZcu|~}zcNGA24QYJJRE=QbqxyǶ|st{unu{riupYIJIGR]gifijhlndhsǾ|ghuzyu}|rv~rg^`[OIKQYRWhis}tzxrupadq{twtc]jofj|{vsy|yjYUW^or[WTWO[suv}~|}wndSGIRajU:47DPYmsormekttpuufrnTE:@EJULEKRT`zɿxzj\Y`bY`^TOH>?MZ\bcTJIZq~rx~xz{pinz|urjfq}~rkchrrojZUb}xqm_euvhd[epkfhvrhmofn}~vnopnowvhXP_l{|zqkptww}xvgafdVNO[kvxukemw{eY`lryɾ}yzx`J5&%7MN92@[pnojc`TU]iwznc^jvwlT;16=?HYbg_]aj~]JXz|qt}zhPAH[fovtp]FA@Pjxzkcw¼y}lW]vwryo]cotWISkswvpv{~mm}saYZVNGRct}}|md\XSLDJRW]\WO@:HSftv}pozz}qXJRijY^glzaSWpyjWBGehuj`bkqrlnnhkkw~VGUpziW?@Ztyvumn¹uh`\V]ime^m{|aVNUgvynjsquz´vmgr{WDBSV@/*>c{zu~vwxs[QCDUdh`VPEEN]qzzk[c|{vjejyqrbSbwfgpooryqdjs}~rgdcerukd^ekhhbVSOUiyytispfdcrqfhjpjM;;Neirtnnryotxl`]Z_aixwnefuxhPH^rudm|̽¸{{{smrspncPCJ\_pb:6Lbir|v{}zuwfVji\\o~o]_fm{zse^`em{~y}|_C5Jgvzmpqikkm{qcnyj\bm~ofkqvtlb\ej^f}ŵԿqYHFFN``PIRahcM*,@JRX]_dp~z{|oq{vswy{qXE0&*:FRdwuZ?:PXT_mzŻn^jzbNJUahmriULP[dkzuks|\?69O^e^WKHCEYuζȭyw~ndN:=MdutbXUOUdraNcs}~ltjF8BJSbcQKZbWTepy}`ctq^[ZXfov}{}we`oyuvje`]h|xoxss}zpkvyu}}yzohYS`c[^fm}pvtnrwtjmkoyzxsurvvkmuf@/9KVhxw}xj_p˹xwnXLSYL15AFE:99E[lu}ywiXQSQJOVa[JHPjyz~{y{{fYSK:3?KUXPGHewtm_WXr~pc^dghmlo`@41<_ssitmgrwhcqzsrvz{h[KQbtykemzywz{y\QJ=82,/ISQUE;ANYby̽vndm~|oU?AE96968?MdshYA?JP_d]cifbiplv̸{jahuzrJ5AFCR[QNPLPrcUXY`sîp[Zbb\UO_~|xfXPPOOSa}gQ=9M`ou{~||v~tic_gx{ujg_U^pu^MNQTPRPGIK_oe`elqx}zwqxnL3&'3M___ovxnWHKXhqyztZ5'7?JZ`]`v~]^ivxiU>367497*#2Icl_^vtgljpɟ~zT8.5DYe^VYet|t[Ydhh~zdTZkx|{x|ŪmVNMO[`R>=Tgjwud^PEMXaspm}vx|cNFCN`lf[`{xv|uij}ydQ^i{o]POcvǸѬtjZRY`bsѩyguy~qN.#+9B>=HVfvuȽĶ|lQ37G7$!?ZSESr{i`qܻynylebUCAX~n`]paOZcp{eZTS^utfY=-7NO7.5NuzutfP;1=Y\_~ʲpWRhzqjdcp}tcV^qxlfl|km~v_OGPenle]RA9I`uslxgRQYj¯uopj[G/!!2EB:Lewwnhhqr{¾oUFCLB'(;KQXcjvols}||xpcTQVnt^Yao|wk_RMQ[hsokyĺhNB@DT\QLO^}~yT0$BHSsuijf^ft{wxpsqd][dz{f`ed_dd\^e`WTTWe}}~uZThp^G@E?44BF@LZVSWevw~kdn~|xy]F968;>2+4Bbnm|²sf_bgi_QR]kqpjdgVB>HNMT\bskRVetyyij{mjrscLMjrisrpfWNF;9Ce{qaUP^kfezxbgutzs_^VL]{pZIFJNYchiqtiqxs~wyqmʮ~|wgOBA?@Oktl^NNXUYrzsyhQ@=4+.36:47RhbTP_msü|gcejqqrn]V\M6261'*H`mpurjhszvpghļ~yosj]]]^k{|~xmikkptp_Zeotvtx̵~vs{|lrvfhw~}jQh~mRA@GTneWa}j\gmqtqv|~ont`QKGFOZ``SC=I\r|rnkɽrX=269DJB93?RXSS^dZgxs}ujz̾nflwjJ@:8=JL@8K`^ahnaM]zzþ]\xtlnmtvn[VhtdYhhekeVQ]lywih{lPLlvoqmc^iy~ngy|z|ztsfGFCDM]mqrtzvloõqdciyu^aqtx~rjadqbHCMVT[qye`hyȻ{eZezjhqcW^mzpmei}sl{pf_M>Kcryx~ypo}}h`}xemtvvpxzszsfZcifg_VGCJVdmz~{}||wmxmP21Keor|yfba]_^cqrrc}wtrnunQB6,4LeqfZj{sadpɵs]`}rqxlaS>9BXdcVQhya[yrir{xrfjtylkvyphcmupsztqudX[u~n\]x~qbZTeqrn\UcuzsiM:Iftctkf{yz}p_TNIIOWgprvfRRQJ\rp^bgz|}~wyqdk|iI807JS[cRAPdm~|sx{fbd]\VLZn|sm{wy|udbeq|}}t|vtx~hbhprio|z~umikhkphtaV_cggkvufdntz{vno~{iX_pulwvrlee_V[hl^[enupg_YVYaq|{~|w|zfdiw|wfZ[TAHbrvn`^k{txwysb`\XY\WNSkups~mn|no|vjfbo|g^ly|tv~yj[]jy|wrnfjz}|yjYXj{x~rwypi]Y^dit~xg`qxi]]jw~yszrp{|cUetw}udcj}w{sxrqkkv}q]KLauyspmm}z~~pzu{ynTHUhkf[\iytqot|xrzoZ\httgTMXhfhoe][amwuopqkq}}{ko~~zquztiahrqs~zu{{u{}vmgm{wu~{yvkigdgif]eytcdulekz}{ztu~vryjbaao~ynvyz}rhr{uefn\GAN_b^]l}zcbtr^mredxolr~}tifn{w|~utooz|||w{~||}~bD@UlurnjerzdSixnms~}f[gyz{nj}{njv|{zzuktxppwtz|{vkqxp|~p]Y\`grwgTMQerleaZR^u{zg[h~yz~zt}uw{~mcm}wzxutje]Y]liemoqwhjxyr~qdm}yv~}yuy~vrg`{}jcmxv||z~vjp{vz}}~wxzvtrj\\ZZfjlfeprj[Zcektz}|xvrohcp}z|{}zxpjnnml`Xevwphksw}ps{|{z}}ohljeaenvxz{obellmowzx|~|}z|zy|}xpnxzzypkdht}}|zsy~|}~~wmmpdXdyy]Vn}}tpttx||ps}|tsx}wrqy~|{tkktyuxkq~~~ts}w}i]ota]py|uiotu}zy~yw}uyut{}tm{~rm_UZda]h~xifmryz~~w|p]_jjgipupjgjgehyuyrgu|qsygszuu|w}wsssnnlpw{~z}smz}uz{~~skku~{qkknmsww{n}|vz{wyy|ms}}zmv|uc`isyspv|sylnphhr{|vsmkrusqurt}umkpz~}{{y{~zsehw{tyqhe__ksmceuuu{qikvsedw|uu{~su{|wtw~tgtww~tfcfmskjtwqtvtvoq|{rjv~te[al{zojrytsy}vgey{vu|{{}{uyurrvury~}v~y{{yms}~wyqifmsy~s^S]m{{sls{{uskl|{{}||zvo{wss|~uqqxzps~x~|tnvxoliilt~~uuv{~wpnswniowwskvsns~timvz|~~{{}n^UZm}~vmgiozzzusto`]gstmmw~z}|stw~~ot|w}whsshk}uhmvshn|v|~v}~{{{kt~~tnfdpy|{~ynn~}jnwy|{xpkiaft|jkppquunir~uop|}|~~{y|~xvw|ww{|~uy~~|yxwwwohhkwwoqvuou|vwuwqhkpmip~~yw~up}ypuvuop~|qjn{wjdkw|wmmquw~y~vq|{{|rnlq{}wnw}nifhlr}y|{rx}roqqlkqvr~vdix|{xrrrs{{rpsrprv|x~}xwroorqpojlr}}yx|wjfloy{x}}{~}~}qkv|{xv{herrhedhlx{yszqnkqzwz}|~qqzxxwqzswz|qv}yrw}|}qqz~xq}vssqkjrzyvzyy}vnpmjjs}|}}|m`bj|zsyv|xr|}tvrkvyttvrkrx}}yyt`\gkx~|zzxqqf`nz|z~sy}}vnqqxx}xv||mcbbs~||}|xy|tohnmix}}x|}ysrx|yvx~yxtz~smoot|}x}yyz|~zvor}~~rz~}|~vvxxsrorxz|~}~~|zyvsv|sjdjz|uis|x||urqszxtqq~y~|uru~~|tlryrggu}}~|zz|zy~yuusrrzztzts~~zzz||ytx~~yy~x||trnhlu|zyx}srtsiejjir~}ulr|}wsz}mjrtyyy}~~|spzysz~}w~ztzwkkz|~|~~wzzsrzyztpnkw~|wpnwuuy~~y}~|w||pw~}}tpwwnrsy~|zypy}umichw|}z~~}umwz}~zz}}urrrkmz~~v}}zzzvqolnnlsz}{}{~}{zt}xtxz{xtqnx~{z~~~vvx}xxzz}}~{}~}zz}{zqs}zv{}x{~}zzvot{}{~xvxsux~~z{vu~}{}}~{{x}}vx~}~}xusosxx~}xqx~z{~vtxz{{zzxokqrmxz}{}}{vu}{z{}}zxummvzt}}xuuuvz{zxurttvtu}~}{z}{vttx}r{{}~}zurtz~~}}}{~}~zzxvvzzvxxx{xzv{}~~z}}vw}}wv~}{uptvv{~zz}{z}{w}zptwwuvvu{~}}yy~yyvv{~{wv{{wwv}yywtnlt{wtt}~{~wv~{{yy}yupu~}~}{~}{{uqy~vwy~wtqy~}}}}wyy~~{y~}}ywwww~}usv{~}yvw~~{}~{ywu{~~~~~~yw~{y~}yw{~}{}}y}}ywvy{~~~{ywuw}~}vu{~{yywusvvw~}}yy{{}~}}}yy}~~{y{{wwyy~~~}wyvqswyy}}}~{}~}y{~}{yuv{{}~~~~yuv~~ww~}{y~{yrqw}}}~~~{~~~~~{}~~~~~~~~~|{{{wrorvvv{~|~~~xvx|~~~~~xprx~|~||~~||~~~~{x|~||~|~xtrtx|{|~~~xx{~xx|xx||{{|x||||{|{{~|||~|~{{wwx{~|||{~~~~~~|||{~|~|{{{~~||~~~~~|~~~||~~{x{{~|z|~|~~~~zx|~~~~|~~|||~~~~~~~~~~|~~~~~~|~~|~~~~~~~|~|z~|~||~~~~~~~~~|zz|zz||||~~||~~zz~~||~~|~~~~~~~|~~|~~~~~|~~~~||~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~~~LIST,INFOISFTGoldWave v2.10 (C) Chris CraigQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/misc/flagtk.wav000066400000000000000000001426461475442401000264200ustar00rootroot00000000000000RIFFWAVEfmt "V"VdataE~}~}||}}~~~~~~}|}~~}||}~~}}}~~~{{zyz{}~{xx{~}}}}}|~~}|||}~~zxz{{|~}yxz{z{}|}~~~}~~~}~}|{yy{~~{wxyz{~}~~wqqsvuxz{}wsuvuuz~~~~~}}}{{|~~}}~~{wxz}}~{vusrru{~~~|yxvuvz~{~}{|~~}}}}{vvvz~}~~~ywy}~uqtwz||}}}~~vqrtvz~~}|ytnjmy|{}~~~{z~ytwy}vruz~~~||~vrv~}yz~yxwqlijnsvv~}{{~~{zzxrry|x{{~~yvzzvu}~~{xjkzwsvywrv~~z|}~}~~xzwii{zxz}~xy{~xjgo}~z|}~}{ob[NP^o~ytsy|}~~|vrpqrt{zz}~}}}}mt}ytj_fij{||vw{qldSLXt|y}|z|}}}~cPTS\gpp~vlfltwsszumu~zsrt{|}~zvzpu{vbgssdp~{rv}{{}~vqmlnt}mZJFL`t~}wnwxcXcw~omvv~{shYVSSSSb}}~vtx~zuqqrxtmlpnwѸwVNn}toosy|~~{{zvmhnz~zzZOO?3Bi}}pS1Z~|zrls~}`C-8EHZ}rhgddnu{{oh_QKlsyʭyrqotyuoopv~}xrqx|yw}گRA<9!@_tzqmz}zob[dtqM=K_x||vi^PC3=Tokf̲ѲmYgpwtxxwux}zvu{}xidjt}[B?KW`bir|{~}xưc=SZb[fhdSWlvW9/:IQKJbww}srx~yqstvsvunacvyvebcipsqu~}vtuwsorįpYmZ<:Tg]\|vzhMDSeXENz|{{|}sr~v^R[ojS^Ǽra]]^hu~vsvyrjko[SFJW^_t~{ygPA78Klunn{}y}wg]PP[^Zwx{Y\js{}}~~ztpqwxmo]Ziytiillnuz}}||`"'FZnprs{vzwigs|sme^Y`lu}zqnu}~tglrvxwz~ŭt^_prZVcmqt||yxz{~lV[qvqqwvihyuwyaNOZa`h}xtvx|~{wy|xtuzpa{ҵsWFGWm}{|}|{z{~mRQUYbmpp|zfPCJ]v}iauvuzuomhjnspptvLTgrv{}~~wpsjY]ytmdadlux}|H1HV_mz}~{uv~z{~}vsy}woffjqvtjcn~~|z~}}|yzz|~~niuhUW]ckszqeRSjwozmkƸ}ztqry~}~zg]Z\bgrpilnry~~~}vx|vm~ıy_?*1Le|}wyz^C=?Kd}uz{yj\U^lgTTxztqwzxy}zytkmuy{}kzW1Ncmpz~zwxfR[v~vhUZdoo~||~sQZfos{şrddqumnptz|{{ndgnqtr_bu|tv|sqxpt`?0;FZhy~uhfq|uwrkھur_Yaox}~rf_`ksw~¯pWHJQ`q~~|~}^2?crrmjorWMDDP_cuxlXcpx~xpihllo}ujg~ū~meo{qefmuw|~{yz|{~k 1MR`m||qmgGBZf[^z}tuj]chkoqryeVW\hw~~~ysvyxx~mgv~_Vaecw~y}kG:Jazwz|tjx~xy|||zqgj`Wkմz~~tceiorw~{{~~{xz~}|jox_Xadl{~}qmw}xvuvse`doqz}ux{|yqmpx}lSBTr|rYit~|sizswticly}|}ztrt{|yzgLartjoz~{{}}~}|~}tlemzeXousy~}}yl^eox{jh_]m{ss|ynkyyu||~znegnnlnu|}~~}zxlhwcGRk}zzy~zr]NQQ>,7Qm~~zpt|wtu{~xoe_m~{pr}wx}~{yunhjo{|dhz~jgxyx{~~zxrfeqgQ\nI\pyx|~ypvujovjeyqlc_i}{w~omvǽv]\gglplnujny~|||rcQKf{wx}{vttrqokoi[j{rkx}{xxz~~~~sTIT`]OGTcw~~puqf]cl{wssr|}~ynhnmbVRYj|{fgwyz~}ywx}yn^S\rZ_xjQetmXavxlwa[o{ss{~~zw}wjqrOQdw}y}yzvporsw|||wlis`BSfflwxw{{ytbPOCFZpto|~}tmxtqrzvdn£yichebhpw{~|yukip|u_hgIXdrs~}~~~rc\YB8FZaqx}{y}}}~p_ajnr}WQe~x\fs|~xuvy{~|zroyq\\ypnpsx}{hgw|~M .Ur~~yyvik~egiequaw~ulox~qflqy~x~h`VMWn~|~{{~wd{|fXVnj{wtzyy{z}~zuoYIMfq`oyvppv{~~||yswsʹmik`DDWpz~y{qlwxwaWYhx{ylr~~ywyn^Zgu~rkqyx|qt|~~~}zuy~yrYayybRcjy}y}vwq^gixtggx}y{zY_nqwöwxpq|z|xsu|~{|u{xoo|oaxpt}t~zzunp}zw`MNepnrzw~xuz|slg|vsywgeoz|wqos~g\\{np{uz~vuyvutjPGUm~yiu~~~{{~rrvnsvcipyooz~yuw{xloyqpuqk~zy{x|}prsxKHfq{|zy|~zwyxtxno_o}x{{xzspz|{onbly{uszz~{{xztwuaa|~yck}~|}y{|~wrmx|sqxz|z|}~zx{{_Xwiyq`_u}~qr|{ijlv|u{xuz}}zuzrb]s~}qzvyvxx}tklN\ztwhkzqkt_m||vu~~tt~|yl^ot~vy}{{unrvvpxpnw~~}y}vsx~{zzz}~~||}~~}zyvtqrnlqnr|~yvpmjmvwjbdqsku~~}~|su|}|zz}}|~zrspegou|{z|~~~}~}{ysgionnyyrmjq}{yutt{~~~|{|xvuvz~}yxz{|~~{z{}ofjs{}zqks{}{yuvw|xvrstuw|~}~}|~{uoouy}x{}||vy|~~~}~~}|us{|wsw}vnx{zmVdry}}~~zuu{|~~vms~yxy}~zz{}}}wtuwz}~ywz}}}}{rntz|{~~~}~{urqty}|wy|~}{yuuslmswrpt|~|zsxwtuz}zxux}~~}~~}{vonv|zy}zy}~|uiir{xrz}zolqw~||~zuuvwy~|z~}}~~~zz~{nptrr{~|~}}~|wv}zpuwzru|~|}~wqv~{{{z|~~|yy{~~rpqv}|}~|{}vosz|{||{}}{~}wqoy{~~}{w{{|{z||}}{~~~zuvz}z}}zuzv|~|~~~~|{}{{{~z}~~x|}||~qrx}||z~~{w}~yz}okrx|~yyz~~}~~}~~~|x{vw||~|zwssw}~~~}~wupvy~~}|zyy~}x~}{~~~}y|}|~{w||}~|ts{}z~y}zxww{z~zwx}|}|}}y||y}~{~}x{rnrtsw}~~zz}}~~~|{w|zw~wpuzt|~z|yzy~~yrqyx~~~~}{~~zxzwz}z~}|~{y{||}~~|}y{}|~}~wtxyu}|~~~}|y|~z|z{~zz{zvtw}~~}}}}~|{~~|zx}~~~~||~~|{~~||}{}~}{}|{}}}}~}}}~zy{{z}}~~yvy}}{{|~~~~}{{~~~~|}}}~~~}zy}xux|}}~}{}}|~{xwwwx|}~~{{}{||{{zz|{~~~yyuuww||}~}~~{}~yzwuvx|ywyy}}}~xy|~}}{}~{||zyvswyux}~~~}|}{x{}}~|yxvxuvwwxy~~}~~}~~}}{vw~~~~~~~~~~|yyy|}|}|~~}||~}unv}{yz|{||~~~~|{zz}~{vtx{|{z}}yvy~}}~|{zzzyz~~}}|~~{}|}zywwxyzzy{~~{}}yzus|}xyyww}}{z}}~~||yxwwxx{y|~{yvss{~|twxu}~~~|}}{xwxw{{|y{~{xusy}usuou~~~}{~}zxwy}}~yzw}}~{vpy{wsolv{~~~~yvtx~~}|}}|xuxyytwvu|~}~{|~}{yvxx}|zz~~}~~~|y~wrvvv~}|}|{}~~~zz|~}vz|ystuv|~~{z}|{{{}~}}~~|}~|xxvv~~|~}~}zvxwx|~|}|zw{}~}~|z||}}}}~~~}|~}~~}}|}}~~~}{z}~|}|zy~~}}|}|~{}~{|~~}}~~~~{}~}}~}z|y{~~}~ywz{|}~~|yy}~~|}~~~~~~~~~~}~~|{{~~~}~}|{|{y||~}}{z}}}}~}}~~~}|}}~~}}~~~~~~~~}}~~~~~~~~{z{}}~~~}}}}~~~~~~~~}}}~}}}{}~~~}}~}}|~~}{~~}}~~~}}~}~~~~~~~|}}}}~}}}}~~}}}~~~~~}~}||}}~~~~~~}|}~}|}~~}}}~~~~{{zyz{}~{xx{~}}}}}|~~}|||}}}~zxz{{|~}yxz{z{}|~~}~}~~~}~}|{yy{~~{wxyz{~}~~wqqsvuxz{}wsuvuuz~~~~~}}}{{|~~}}~~{wxz}}~~~{vusrru{~~~|xwvuvz~{~}{|~~}}}}{vvvz~}~~~~ywy}~uqtwz||}}}~~vqrtvz~~}|ytnjmy|{}~~~{z~ytwy}vruz~~~||~vrv~}yz~yxwqlijnsvv~}{{~~{zzxrry|x{{~~yvzzvu}~~{xjkzwsvywrv~~z|}~}~~xzwii{zxz}~xy{~xjgo}~z|}~}{nb[NP^o~ytsy|}~~|vrpqrt{zz}~}}}}mt}ytj_fij{||vw{qldSLXt|y}|z|}}}~cPTS\gpp~vlfltwsszumu~zsrt{|}~zvzpu{vbgssdp~{rv}{{}~vqmlnt}mZJFL`t~}wnwxcXcw~omvv~{shYVSSSSb}}~vtx~zuqqrxtmlpnwѸwVNn}toosy|~~{{zvmhnz~zzZOO?3Bi}}pS1Z~|zrls~}`C-8EHZ}rhgddnu{{oh_QKlsyʭyrqotyuoopv~}xrqx|yw}گRA<9!@_tzqmz}zob[dtqM=K_x||vi^QC3=Tokf̲ѲmYgpwtxxwux}zvu{}xidjs}[B?KW`bir|{~}xưc=SZb[fhdSWlvW9/:IQKJbww}srx~yqsuvsvunacvyvebcipsqu~}vtuwsorįpYmZ<:Tg]\|vzhMDSeXENz|{{|}sr~v^R[ojS^Ǽra]]^hu~vsvyrijo[SFJW^_t~{ygPA78Klunn{}y}wg]PP[^Zwx{Y\js{}}~~ztpqwxmo]Ziytiillnuz}}||`"'FZnprs{vzwigs|sme^Y`lu}zqnu}~tglrvxwz~ŭt^_prZVcmqt||yxz{~lV[qvqqwvihyuwyaNOZa`h}xtvx|~{wy|xtuzpa{ҵsWFGWm}{|}|{z{~mRQUYbmpp|zfPCJ]v}iauvuzuolhjnspptvLTgrv{}~~wpsjY]ytmdadlux}|H1HV_mz}~{uv~z{~}vsy}woffjqvtjcn~~|z~}}|yzz|~~niuhUW]ckszqeRSjwozmkƸ}ztqry~}~zg]Z\bgrpilnry~~~}vx|vm~ıy_?*1Le|}wyz^C=?Kd}uz{yj\U^lgTTxztqwzxy}zytkmuy{}kzW1Ncmpz~zwxfR[v~vhUZdoo~||~sQZfos{şrddqumnptz|{{ndgnqtr_bu|tv|sqxpt`?0;FZhy~uhfq|uwrkھur_Yaox}~rf_`ksw~¯pWHJQ`q~~|~}^2?crrmjorWMDDP_cuxlXcpx~xpihllo}ujg~ū~meo{qefmuw|~{yz|{~k 1MR`m||qmgGBZf[^z}tuj]chkoqryeVW\hw~~~ysvyxx~mgv~_Vaecw~y}kG:Jazwz|tjx~xy|||zqgj`Wkմz~~tceiorw~{{~~{xz~}|jox_Xadl{~}qmw}xvuvse`doqz}ux{|yqmpx}lSBTr|rYit~|sizswticly}|}ztrt{|yzgLartjoz~{{}}~}|~}tlemzeXousy~}}yl^eox{jh_]m{ss|ynkyyu||~znegnnlnu|}~~}zxlhwcGRk}zzy~zr]NQQ>,7Qm~~zpt|wtu{~xoe_m~{pr}wx}~{yunhjo{|dhz~jgxyx{~~zxrfeqgQ\nI\pyx|~ypvujovjeyqlc_i}{w~omvǽv]\gglplnujny~|||rcQKf{wx}{vtsrqokoi[j{rkx}{xxz~~~~sTIT`]OGTcw~~puqf]cl{wssr|}~ynhnmbVRYj|{fgwyz~}ywx}yn^S\rZ_xjQetmXavxlwa[o{ss{~~zw}wjqrOQdw}y}yzvporsw|||wlis`BSfflwxw{{ytbPOCFZpto|~}tmxtqrzvdn£yichebhpw{~|yukip|u_hgIXdrs~}~~~rc\YB8FZaqx}{y}}}~p_ajnr}WQe~x\fs|~xuvy{~|zroyq\\ypnpsx}{hgw|~M .Ur~~yyvik~egiequaw~ulox~qflqy~x~h`VMWn~|~{{~wd{|fXVnj{wtzyy{z}~zuoYIMfq`oyvppv{~~||yswsʹmik`DDWpz~y{qlwxwaWYhx{ylr~~ywyn^Zgu~rkqyx|qt|~~~}zuy~yrYayybRcjy}y}vwq^gixtggx}y{zY_nqwöwxpq|z|xsu|~{|u{xoo|oaxpt}t~zzunp}zw`MNepnrzw~xuz|slg|vsywgeoz|wqos~g\\{np{uz~vuyvutjPGUm~yiu~~~{{~rrvnsvcipyooz~yuw{xloyqpuqk~zy{x|}prsxKHfq{|zy|~zwyxtxno_o}x{{xzspz|{onbly{uszz~{{xztwuaa|~yck}~|}y{|~wrmx|sqxz|z|}~zx{{_Xwiyq`_u}~qr|{ijlv|u{xuz}}zuzrb]s~}qzvyvxx}tklN\ztwhkzqkt_m||vu~~tt~|yl^ot~vy}{{unrvvpxpnw~~}y}vsx~{zzz}~~||}~~}zyvtqrnlqnr|~yvpmjmvwjbdqsku~~}~|su|}|zz}}|~zrspegou|{z|~~~}~}{ysgionnyyrmjq}{yutt{~~~|{|xvuvz~}yxz{|~~{z{}ofjs{}zqks{}{yuvw|xvrstuw|~}~}|~{uoouy}x{}||vy|~~~}~~}|us{|wsw}vnx{zmVdry}}~~zuu{|~~vms~yxy}~zz{}}}wtuwz}~ywz}}}}{rntz|{~~~}~{urqty}|wy|~}{yuuslmswrpt|~|zsxwtuz}zxux}~~}~~}{vonv|zy}zy}~|uiir{xrz}zolqw~||~zuuvwy~|z~}}~~~zz~{nptrr{~|~}}~|wv}zpuwzru|~|}~wqv~{{{z|~~|yy{~~rpqv}|}~|{}vosz|{||{}}{~}wqoy{~~}{w{{|{z||}}{~~~zuvz}z}}zuzv|~|~~~~|{}{{{~z}~~x|}||~qrx}||z~~{w}~yz}okrx|~yyz~~}~~}~~~|x{vw||~|zwssw}~~~}~wupvy~~}|zyy~}x~}{~~~}y|}|~{w||}~|ts{}z~y}zxww{z~zwx}|}|}}y||y}~{~}x{rnrtsw}~~zz}}~~~|{w|zw~wpuzt|~z|yzy~~yrqyx~~~~}{~~zxzwz}z~}|~{y{||}~~|}y{}|~}~wtxyu}|~~~}|y|~z|z{~zz{zvtw}~~}}}}~|{~~|zx}~~~~||~~|{~~||}{}~}{}|{}}}}~}}}~zy{{z}}~~yvy}}{{|~~~~}{{~~~~|}}}~~~}zy}xux|}}~}{}}|~{xwwwx|}~~{{}{||{{zz|{~~~yyuuww||}~}~~{}~yzwuvx|ywyy}}}~xy|~}}{}~{||zyvswyux}~~~}|}{x{}}~|yxvxuvwwxy~~}~~}~~}}{vw~~~~~~~~~~|yyy|}|}|~~}||~}unv}{yz|{||~~~~|{zz}~{vtx{|{z}}yvy~}}~|{zzzyz~~}}|~~{}|}zywwxyzzy{~~{}}yzus|}xyyww}}{z}}~~||yxwwxx{y|~{yvss{~|twxu}~~~|}}{xwxw{{|y{~{xusy}usuou~~~}{~}zxwy}}~yzw}}~{vpy{wsolv{~~~~yvtx~~}|}}|xuxyytwvu|~}~{|~}{yvxx}|zz~~}~~~|y~wrvvv~}|}|{}~~~zz|~}vz|ystuv|~~{z}|{{{}~}}~~|}~|xxvv~~|~}~}zvxwx|~|}|zw{}~}~|z||}}}}~~~}|~}~~}}|}}~~~}{z}~|}|zy~~}}|}|~{}~{|~~}}~~~~{}~}}~}z|y{~~}~ywz{|}~~|yy}~~|}~~~~~~~~~~}~~|{{~~~}~}|{|{y||~}}{z}}}}~}}~~~}|}}~~}}~~~~~~~~}}~~~~~~~~{z{}}~~~}}}}~~~~~~~~}}}~}}}{}~~~}}~}}|~~}{~~}}~~~}}~}~~~~~~~|}}}}~}}}}~~}}}~~~~~}~}||}}~~~~~~}|}~}|}~~}}}~~~~{{zyz{}~{xx{~}}}}}|~~}|||}}}~zxz{{|~}yxz{z{}|~~}~}~~~}~}|{yy{~~{wxyz{~}~~wqqsvuxz{}wsuvuuz~~~~~}}}{{|~~}}~~{wxz}}~~~{vusrru{~~~|xwvuvz~{~}{|~~}}}}{vvvz~}~~~~ywy}~uqtwz||}}}~~vqrtvz~~}|ytnjmy|{}~~~{z~ytwy}vruz~~~||~vrv~}yz~yxwqlijnsvv~}{{~~{zzxrry|x{{~~yvzzvu}~~{xjkzwsvywrv~~z|}~}~~xzwii{zxz}~xy{~xjgo}~z|}~}{nb[NP^o~ytsy|}~~|vrpqrt{zz}~}}}}mt}ytj_fij{||vw{qldSLXt|y}|z|}}}~cPTS\gpp~vlfltwsszumu~zsrt{|}~zvzpu{vbgssdp~{rv}{{}~vqmlnt}mZJFL`t~}wnwxcXcw~omvv~{shYVSSSSb}}~vtx~zuqqrxtmlpnwѸwVNn}toosy|~~{{zvmhnz~zzZOO?3Bi}}pS1Z~|zrls~}`C-8EHZ}rhgddnu{{oh_QKlsyʭyrqotyuoopv~}xrqx|yw}گRA<9!@_tzqmz}zob[dtqM=K_x||vi^QC3=Tokf̲ѲmYgpwtxxwux}zvu{}xidjs}[B?KW`bir|{~}xưc=SZb[fhdSWlvW9/:IQKJbww}srx~yqsuvsvunacvyvebcipsqu~}vtuwsorįpYmZ<:Tg]\|vzhMDSeXENz|{{|}sr~v^R[ojS^Ǽra]]^hu~vsvyrijo[SFJW^_t~{ygPA78Klunn{}y}wg]PP[^Zwx{Y\js{}}~~ztpqwxmo]Ziytiillnuz}}||`"'FZnprs{vzwigs|sme^Y`lu}zqnu}~tglrvxwz~ŭt^_prZVcmqt||yxz{~lV[qvqqwvihyuwyaNOZa`h}xtvx|~{wy|xtuzpa{ҵsWFGWm}{|}|{z{~mRQUYbmpp|zfPCJ]v}iauvuzuolhjnspptvLTgrv{}~~wpsjY]ytmdadlux}|H1HV_mz}~{uv~z{~}vsy}woffjqvtjcn~~|z~}}|yzz|~~niuhUW]ckszqeRSjwozmkƸ}ztqry~}~zg]Z\bgrpilnry~~~}vx|vm~ıy_?*1Le|}wyz^C=?Kd}uz{yj\U^lgTTxztqwzxy}zytkmuy{}kzW1Ncmpz~zwxfR[v~vhUZdoo~||~sQZfos{şrddqumnptz|{{ndgnqtr_bu|tv|sqxpt`?0;FZhy~uhfq|uwrkھur_Yaox}~rf_`ksw~¯pWHJQ`q~~|~}^2?crrmjorWMDDP_cuxlXcpx~xpihllo}ujg~ū~meo{qefmuw|~{yz|{~k 1MR`m||qmgGBZf[^z}tuj]chkoqryeVW\hw~~~ysvyxx~mgv~_Vaecw~y}kG:Jazwz|tjx~xy|||zqgj`Wkմz~~tceiorw~{{~~{xz~}|jox_Xadl{~}qmw}xvuvse`doqz}ux{|yqmpx}lSBTr|rYit~|sizswticly}|}ztrt{|yzgLartjoz~{{}}~}|~}tlemzeXousy~}}yl^eox{jh_]m{ss|ynkyyu||~znegnnlnu|}~~}zxlhwcGRk}zzy~zr]NQQ>,7Qm~~zpt|wtu{~xoe_m~{pr}wx}~{yunhjo{|dhz~jgxyx{~~zxrfeqgQ\nI\pyx|~ypvujovjeyqlc_i}{w~omvǽv]\gglplnujny~|||rcQKf{wx}{vtsrqokoi[j{rkx}{xxz~~~~sTIT`]OGTcw~~puqf]cl{wssr|}~ynhnmbVRYj|{fgwyz~}ywx}yn^S\rZ_xjQetmXavxlwa[o{ss{~~zw}wjqrOQdw}y}yzvporsw|||wlis`BSfflwxw{{ytbPOCFZpto|~}tmxtqrzvdn£yichebhpw{~|yukip|u_hgIXdrs~}~~~rc\YB8FZaqx}{y}}}~p_ajnr}WQe~x\fs|~xuvy{~|zroyq\\ypnpsx}{hgw|~M .Ur~~yyvik~egiequaw~ulox~qflqy~x~h`VMWn~|~{{~wd{|fXVnj{wtzyy{z}~zuoYIMfq`oyvppv{~~||yswsʹmik`DDWpz~y{qlwxwaWYhx{ylr~~ywyn^Zgu~rkqyx|qt|~~~}zuy~yrYayybRcjy}y}vwq^gixtggx}y{zY_nqwöwxpq|z|xsu|~{|u{xoo|oaxpt}t~zzunp}zw`MNepnrzw~xuz|slg|vsywgeoz|wqos~g\\{np{uz~vuyvutjPGUm~yiu~~~{{~rrvnsvcipyooz~yuw{xloyqpuqk~zy{x|}prsxKHfq{|zy|~zwyxtxno_o}x{{xzspz|{onbly{uszz~{{xztwuaa|~yck}~|}y{|~wrmx|sqxz|z|}~zx{{_Xwiyq`_u}~qr|{ijlv|u{xuz}}zuzrb]s~}qzvyvxx}tklN\ztwhkzqkt_m||vu~~tt~|yl^ot~vy}{{unrvvpxpnw~~}y}vsx~{zzz}~~||}~~}zyvtqrnlqnr|~yvpmjmvwjbdqsku~~}~|su|}|zz}}|~zrspegou|{z|~~~}~}{ysgionnyyrmjq}{yutt{~~~|{|xvuvz~}yxz{|~~{z{}ofjs{}zqks{}{yuvw|xvrstuw|~}~}|~{uoouy}x{}||vy|~~~}~~}|us{|wsw}vnx{zmVdry}}~~zuu{|~~vms~yxy}~zz{}}}wtuwz}~ywz}}}}{rntz|{~~~}~{urqty}|wy|~}{yuuslmswrpt|~|zsxwtuz}zxux}~~}~~}{vonv|zy}zy}~|uiir{xrz}zolqw~||~zuuvwy~|z~}}~~~zz~{nptrr{~|~}}~|wv}zpuwzru|~|}~wqv~{{{z|~~|yy{~~rpqv}|}~|{}vosz|{||{}}{~}wqoy{~~}{w{{|{z||}}{~~~zuvz}z}}zuzv|~|~~~~|{}{{{~z}~~x|}||~qrx}||z~~{w}~yz}okrx|~yyz~~}~~}~~~|x{vw||~|zwssw}~~~}~wupvy~~}|zyy~}x~}{~~~}y|}|~{w||}~|ts{}z~y}zxww{z~zwx}|}|}}y||y}~{~}x{rnrtsw}~~zz}}~~~|{w|zw~wpuzt|~z|yzy~~yrqyx~~~~}{~~zxzwz}z~}|~{y{||}~~|}y{}|~}~wtxyu}|~~~}|y|~z|z{~zz{zvtw}~~}}}}~|{~~|zx}~~~~||~~|{~~||}{}~}{}|{}}}}~}}}~zy{{z}}~~yvy}}{{|~~~~}{{~~~~|}}}~~~}zy}xux|}}~}{}}|~{xwwwx|}~~{{}{||{{zz|{~~~yyuuww||}~}~~{}~yzwuvx|ywyy}}}~xy|~}}{}~{||zyvswyux}~~~}|}{x{}}~|yxvxuvwwxy~~}~~}~~}}{vw~~~~~~~~~~|yyy|}|}|~~}||~}unv}{yz|{||~~~~|{zz}~{vtx{|{z}}yvy~}}~|{zzzyz~~}}|~~{}|}zywwxyzzy{~~{}}yzus|}xyyww}}{z}}~~||yxwwxx{y|~{yvss{~|twxu}~~~|}}{xwxw{{|y{~{xusy}usuou~~~}{~}zxwy}}~yzw}}~{vpy{wsolv{~~~~yvtx~~}|}}|xuxyytwvu|~}~{|~}{yvxx}|zz~~}~~~|y~wrvvv~}|}|{}~~~zz|~}vz|ystuv|~~{z}|{{{}~}}~~|}~|xxvv~~|~}~}zvxwx|~|}|zw{}~}~|z||}}}}~~~}|~}~~}}|}}~~~}{z}~|}|zy~~}}|}|~{}~{|~~}}~~~~{}~}}~}z|y{~~}~ywz{|}~~|yy}~~|}~~~~~~~~~~}~~|{{~~~}~}|{|{y||~}}{z}}}}~}}~~~}|}}~~}}~~~~~~~~}}~~~~~~~~{z{}}~~~}}}}~~~~~~~~}}}~}}}{}~~~}}~}}|~~}{~~}}~~~}}~}~~~~~~~|}}}}~}}}}~~}}}~~~~~}~}||}}~~~~~~}|}~}|}~~}}}~~~~{{zyz{}~{xx{~}}}}}|~~}|||}}}~zxz{{|~}yxz{z{}|~~}~}~~~}~}|{yy{~~{wxyz{~}~~wqqsvuxz{}wsuvuuz~~~~~}}}{{|~~}}~~{wxz}}~~~{vusrru{~~~|xwvuvz~{~}{|~~}}}}{vvvz~}~~~~ywy}~uqtwz||}}}~~vqrtvz~~}|ytnjmy|{}~~~{z~ytwy}vruz~~~||~vrv~}yz~yxwqlijnsvv~}{{~~{zzxrry|x{{~~yvzzvu}~~{xjkzwsvywrv~~z|}~}~~xzwii{zxz}~xy{~xjgo}~z|}~}{nb[NP^o~ytsy|}~~|vrpqrt{zz}~}}}}mt}ytj_fij{||vw{qldSLXt|y}|z|}}}~cPTS\gpp~vlfltwsszumu~zsrt{|}~zvzpu{vbgssdp~{rv}{{}~vqmlnt}mZJFL`t~}wnwxcXcw~omvv~{shYVSSSSb}}~vtx~zuqqrxtmlpnwѸwVNn}toosy|~~{{zvmhnz~zzZOO?3Bi}}pS1Z~|zrls~}`C-8EHZ}rhgddnu{{oh_QKlsyʭyrqotyuoopv~}xrqx|yw}گRA<9!@_tzqmz}zob[dtqM=K_x||vi^QC3=Tokf̲ѲmYgpwtxxwux}zvu{}xidjs}[B?KW`bir|{~}xưc=SZb[fhdSWlvW9/:IQKJbww}srx~yqsuvsvunacvyvebcipsqu~}vtuwsorįpYmZ<:Tg]\|vzhMDSeXENz|{{|}sr~v^R[ojS^Ǽra]]^hu~vsvyrijo[SFJW^_t~{ygPA78Klunn{}y}wg]PP[^Zwx{Y\js{}}~~ztpqwxmo]Ziytiillnuz}}||`"'FZnprs{vzwigs|sme^Y`lu}zqnu}~tglrvxwz~ŭt^_prZVcmqt||yxz{~lV[qvqqwvihyuwyaNOZa`h}xtvx|~{wy|xtuzpa{ҵsWFGWm}{|}|{z{~mRQUYbmpp|zfPCJ]v}iauvuzuolhjnspptvLTgrv{}~~wpsjY]ytmdadlux}|H1HV_mz}~{uv~z{~}vsy}woffjqvtjcn~~|z~}}|yzz|~~niuhUW]ckszqeRSjwozmkƸ}ztqry~}~zg]Z\bgrpilnry~~~}vx|vm~ıy_?*1Le|}wyz^C=?Kd}uz{yj\U^lgTTxztqwzxy}zytkmuy{}kzW1Ncmpz~zwxfR[v~vhUZdoo~||~sQZfos{şrddqumnptz|{{ndgnqtr_bu|tv|sqxpt`?0;FZhy~uhfq|uwrkھur_Yaox}~rf_`ksw~¯pWHJQ`q~~|~}^2?crrmjorWMDDP_cuxlXcpx~xpihllo}ujg~ū~meo{qefmuw|~{yz|{~k 1MR`m||qmgGBZf[^z}tuj]chkoqryeVW\hw~~~ysvyxx~mgv~_Vaecw~y}kG:Jazwz|tjx~xy|||zqgj`Wkմz~~tceiorw~{{~~{xz~}|jox_Xadl{~}qmw}xvuvse`doqz}ux{|yqmpx}lSBTr|rYit~|sizswticly}|}ztrt{|yzgLartjoz~{{}}~}|~}tlemzeXousy~}}yl^eox{jh_]m{ss|ynkyyu||~znegnnlnu|}~~}zxlhwcGRk}zzy~zr]NQQ>,7Qm~~zpt|wtu{~xoe_m~{pr}wx}~{yunhjo{|dhz~jgxyx{~~zxrfeqgQ\nI\pyx|~ypvujovjeyqlc_i}{w~omvǽv]\gglplnujny~|||rcQKf{wx}{vtsrqokoi[j{rkx}{xxz~~~~sTIT`]OGTcw~~puqf]cl{wssr|}~ynhnmbVRYj|{fgwyz~}ywx}yn^S\rZ_xjQetmXavxlwa[o{ss{~~zw}wjqrOQdw}y}yzvporsw|||wlis`BSfflwxw{{ytbPOCFZpto|~}tmxtqrzvdn£yichebhpw{~|yukip|u_hgIXdrs~}~~~rc\YB8FZaqx}{y}}}~p_ajnr}WQe~x\fs|~xuvy{~|zroyq\\ypnpsx}{hgw|~M .Ur~~yyvik~egiequaw~ulox~qflqy~x~h`VMWn~|~{{~wd{|fXVnj{wtzyy{z}~zuoYIMfq`oyvppv{~~||yswsʹmik`DDWpz~y{qlwxwaWYhx{ylr~~ywyn^Zgu~rkqyx|qt|~~~}zuy~yrYayybRcjy}y}vwq^gixtggx}y{zY_nqwöwxpq|z|xsu|~{|u{xoo|oaxpt}t~zzunp}zw`MNepnrzw~xuz|slg|vsywgeoz|wqos~g\\{np{uz~vuyvutjPGUm~yiu~~~{{~rrvnsvcipyooz~yuw{xloyqpuqk~zy{x|}prsxKHfq{|zy|~zwyxtxno_o}x{{xzspz|{onbly{uszz~{{xztwuaa|~yck}~|}y{|~wrmx|sqxz|z|}~zx{{_Xwiyq`_u}~qr|{ijlv|u{xuz}}zuzrb]s~}qzvyvxx}tklN\ztwhkzqkt_m||vu~~tt~|yl^ot~vy}{{unrvvpxpnw~~}y}vsx~{zzz}~~||}~~}zyvtqrnlqnr|~yvpmjmvwjbdqsku~~}~|su|}|zz}}|~zrspegou|{z|~~~}~}{ysgionnyyrmjq}{yutt{~~~|{|xvuvz~}yxz{|~~{z{}ofjs{}zqks{}{yuvw|xvrstuw|~}~}|~{uoouy}x{}||vy|~~~}~~}|us{|wsw}vnx{zmVdry}}~~zuu{|~~vms~yxy}~zz{}}}wtuwz}~ywz}}}}{rntz|{~~~}~{urqty}|wy|~}{yuuslmswrpt|~|zsxwtuz}zxux}~~}~~}{vonv|zy}zy}~|uiir{xrz}zolqw~||~zuuvwy~|z~}}~~~zz~{nptrr{~|~}}~|wv}zpuwzru|~|}~wqv~{{{z|~~|yy{~~rpqv}|}~|{}vosz|{||{}}{~}wqoy{~~}{w{{|{z||}}{~~~zuvz}z}}zuzv|~|~~~~|{}{{{~z}~~x|}||~qrx}||z~~{w}~yz}okrx|~yyz~~}~~}~~~|x{vw||~|zwssw}~~~}~wupvy~~}|zyy~}x~}{~~~}y|}|~{w||}~|ts{}z~y}zxww{z~zwx}|}|}}y||y}~{~}x{rnrtsw}~~zz}}~~~|{w|zw~wpuzt|~z|yzy~~yrqyx~~~~}{~~zxzwz}z~}|~{y{||}~~|}y{}|~}~wtxyu}|~~~}|y|~z|z{~zz{zvtw}~~}}}}~|{~~|zx}~~~~||~~|{~~||}{}~}{}|{}}}}~}}}~zy{{z}}~~yvy}}{{|~~~~}{{~~~~|}}}~~~}zy}xux|}}~}{}}|~{xwwwx|}~~{{}{||{{zz|{~~~yyuuww||}~}~~{}~yzwuvx|ywyy}}}~xy|~}}{}~{||zyvswyux}~~~}|}{x{}}~|yxvxuvwwxy~~}~~}~~}}{vw~~~~~~~~~~|yyy|}|}|~~}||~}unv}{yz|{||~~~~|{zz}~{vtx{|{z}}yvy~}}~|{zzzyz~~}}|~~{}|}zywwxyzzy{~~{}}yzus|}xyyww}}{z}}~~||yxwwxx{y|~{yvss{~|twxu}~~~|}}{xwxw{{|y{~{xusy}usuou~~~}{~}zxwy}}~yzw}}~{vpy{wsolv{~~~~yvtx~~}|}}|xuxyytwvu|~}~{|~}{yvxx}|zz~~}~~~|y~wrvvv~}|}|{}~~~zz|~}vz|ystuv|~~{z}|{{{}~}}~~|}~|xxvv~~|~}~}zvxwx|~|}|zw{}~}~|z||}}}}~~~}|~}~~}}|}}~~~}{z}~|}|zy~~}}|}|~{}~{|~~}}~~~~{}~}}~}z|y{~~}~ywz{|}~~|yy}~~|}~~~~~~~~~~}~~|{{~~~}~}|{|{y||~}}{z}}}}~}}~~~}|}}~~}}~~~~~~~~}}~~~~~~~~{z{}}~~~}}}}~~~~~~~~}}}~}}}{}~~~}}~}}|~~}{~~}}~~~}}~}~~~~~~~|}}}}~}}}}~~}}}~~~~~~~~~~~LIST,INFOISFTGoldWave v2.10 (C) Chris CraigQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/000077500000000000000000000000001475442401000240635ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/1.wav000066400000000000000000000156721475442401000247550ustar00rootroot00000000000000RIFFWAVEfmt ++factdata~~}||{{{{{||}~~~}}}|}}}}}}}}}~~~~~~~~~~~~}}}||||||||||||||}}}}}~~~~~~~~~~~~}|{yyxwwwwxxyz|~~|ywurqonllkkkkkllmnopqrsuvwxyz{|}}~~~~}}}}||{{{zzyyyyyyyyyzzz{{||}~~|zxwutssstuwy~|zxuspnljigfedccbbbbccdefghijklmopqstvxz|~}zwtqnljhgffghikmortw{~~|{{|}}|ywusqnljhfdba`____``abbbccccddeefhijkmnpqsuwy{}~{xuqmjfca_]]^_`behkorv{~zwrokhdb`][ZYXWWWWWXXXYYYYYYZ[\]^_`bcdfhiijlmnoqsvwz|}~~}{wsnic^XUQONNPSV[`elryľzrkhb^ZXVTRPPPPPRTWX[]``bbcbdbbaa`__`_abcdffhhhhhihhgfcb\XTPLHFCCCDFJOTY`gnu}½¾}xrmifcbbaaeeehkkmoqqsttttspnkhdeccbehilnprsromlgc_\XUUSPNMKGC?;95337:>DNV_hs|~~}~|{zyvxuttwvvxxwutpnmlhjkkjlmllonpopnnmkhfda][WSPMFC=943214:?FOYalu}ſwnjfdcdhllnmomjgfecddhilprux|}~{wwvvw{}}||wrjb\TOLJNRUXafgfed_[UTSVWZagmovx|vrntx~sh^TLHFEFIMQX]cfnrw}zrnda[\VVSURTNOMQOSW^elsy~vtqojhfinr{o`PG=:?FIV`imtvtupnlmlow{|||~{mg_\^eox~{wwx}{qkgb]\[YXY`]ddhdeb`ahgquywqsuujcZUNPNSQPRTTPPRW\bdkmnmmoorxþxvz{zvsnlpqllf\TMFDAGMX[dcbZVRORW[^a\RD3!(9K[abb__`fnw~Ŀȼyoihnyyke`kpxzp^M@@?M`t}kYE6+% &,9FS\dffeb^]`bks~¿¿ɻsfbablq{~ztlfegimmmfaZUJHJSXfq|zkWH6,!).8>DHLQR\dq{}xvw}ƿ}vosu~umjsqvx|tod[XY`dotyxul_PE;.)$%$'*/48;=CFLPX_eijifdehkqw~ƽ}yyxxwzssywwtvuuyvusvz~~|{xjYB957=ABDD>=?FKU]befeddhinoonmopsvx{{z|yzrnfgikkpssprmsvy{}vaOJKGGFHB=968?HNPRSUW[aflnonnpty}}zwuvvxwzx{~~ztrponqtuvvw||{{zzz|zzxx}zuurnd^^^YQKFB?<@?CCHJHKPZ`gnutyy}zwzz}~}zwtqpnrrrolkjjikknprosvxwvxyzwqnikjjedceebdcf`_\][YXTUQQMOOOSW]`dhloqux|{|}¾{{wvwxvwsronlgc_a_^[]^___cba_a`_abfgjmsttututuvx|{|zsmf]YRRQRSSWVWUZX^_fjqw|ü}~||}~~{tpfbXZVVSQRPPOLMKKJKKORVZfnsuz~zvrsmjhihhhhiijknoru{|wokefccb`_^^\]^acipx~}ywuttqpnoppsu{}|uqohd^^\YUPPLIGGIEFEHHKOTZ_ciouy~{xusssvx{zsphbYWVTTTVUVSTSSSVVXZ]`_cdhffegfeegkkkikie`a`\VSRQLHIJJJKOQRSVZ^agjrvyqmkfbZTMHCA>=:<@EGMQUVWY[_`bcgfeeeffikmmnnpooosrusuwyyy||~}}{zy{y|z}{}~~~{xxwyx{|{{yzvsqomjjfefhhhfgfecbb^^[ZXVWUVPPORPSUVYY\\^^_abfjorrutwv{|z{{~ytqlkghfggfijnouz{xtoiggeeba__]\]^]YWVYXYXYXXZZ[ZZ\[][^`begjjlklkpsx||~}{yxtussttwvy{~zvvtusrrrtuy{{ztqmjighfgdc`ba^]\^[ZWXYWWUWWVWWYZ\]_`a`cdfghjkoopsvz{~~~|ytsvvxxy{}zwqmfc^][ZZZ^bgjosx|yvqokieb^[YVTRSSSRRQRPQQUVY[]aaffjknoprrttvvvwvwvyx{y{}}~}{yxusqqrqrruux{~{yutomkjijklnprtv|}zsqnkgc`]][\\^^]`adccdfghkmlmorrrrqsrqnpoplklnmlmnlkiijiinpqrvy{}~~yvrqnmnmqpusvvwzz~~{wwvwtuvyz{~|zvutrplkhjhgdcdbddfedddeaa`b`aadcacdfbcegggjnqrsux{}zzutpomnklmoprrtvxz||wvtttsttwz{~zwrpnlheba_[ZYZZXWTUTVUWUTUVX[]bdefhkmmnorpopqqqrsrsswwxx{~}~|{wvrpokkggefgfigihjjilknlmlknkkkmnkooux{~|zxvtsponpnlmmolmmopnoqrsqsrrpqrrqqrtsrqsrqoqroppuutrvxwyz~~{yxxtplooqkkhiihkjnnlpmsoponpjlkqnoqqtrtuxzz~}{{yxwyyxuutuuuursrtwvxx{zywvzzzz{|||{~}}z~}|}}~}~}ytwurmlnlidefgghhhiillkjjlkklostwy~}}{|zyyx{z{z|zzzz|zywxy{ywxyxvuwwvttvvvuwwutswvtrrttuvxywyy{{|~~~~~|{yyyxxwxyyyyz{{}}}~}~}|zzyxwwwvvuvvvwwxxxyyzz|~~}}||||zyyyzyxyyxxwxwwvvwwvvxzzz{|}}~}|{|{zywwuutvvxwxyzzz{{|||}}}||{{|{{yyzzzz{{zyy{yzz{||{{}~~~~}~}~}}}}~~||||~}~~~~~~~~}{{zzzzyyxwwvvuuutsrrrqpqqqqqqqrqqqqppqqqrssttuuvvwxz{{|~~~~}}}}||||{{{||}}~~~}|{zzyzyxwwwvvwxwvwwxyyzz{{|}~~}||{|{zzyyyxxxyxyyyyzzzzz{|}}}~~~~~}~}}}}}||{|{{{|}}~~~}}}}}}||||}}}~~~~}}}}}}}}}}}}}}}~}~}}~~~~~~}}|||{{{{{{{||}}~~~~~~~~~~~~~~~~~QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/2.wav000066400000000000000000000137721475442401000247550ustar00rootroot00000000000000RIFFWAVEfmt ++factdata|sSRgF\SmVwJDk^`laodiVrKy{oVڝ֚u]M}tqfwzzozca]^\w]ZW_Xh[mJkGUY?tiJmjvay`jp`mrcz]c}ri}|djst~|kkvQaSZgse]}{mi}xnlxitw_nkRYQg`iufp^v{Yy|Ky?Tu[wumu]R~wkwxuOk^yo~{zxy}mkiuqzpjbWymo|ytrq|ps`V~hf}qpqxmb~txmqvy~hn}p[z{yx{uw|o~zsx{|pqk{yrnvv}{{qr~u}|ftw|zpt|v~zzpzu{~z|z}r~xzz~|{zxx}~ww|}|z{ytt{svu~z}w{p||x~wuzxy|nw{zxq}y{z{~~xtxxw}y{{ww~zzx|}~zw}lkj^YN>9AH::4E79@SPRWdaddrz~ž~u[\T@,  +7/7KWZjv{}~~zuq{|uytqfG5-%  %4&CFFI_hcj}{w}w}wrqrmlkgpnmquھpdGA7/-#!)43>IUb\_to{wq}~¼վmlYU;;0(/;/-1?<:FLY[lpquuw{vrouuur|vqlaTRE@:7*-7<3=DGJQSXZ^egjs}{|~w{|~~|}wlkgbXXVOKJE:<=94;@:?HIEDIQTU_dkkmuyz}zxqkba[QLID9460%'(##'(,+48;BENT]ahs{{|{nl_WRLHA;830%#$ "',-79CHP]gjr{~{|zwywutqnmeb\\WSSSOMJKFBBDBEILNO[^[`inox}xwpjedZTSKEFD?=A<9>>=?HNQZcmps}|zrrlmppowz~spph]XYMEA;3.//+.8:=DNRVXajlt|~~|y}xytyvqiif_VTPJDCBA=?A??AAFFMQW[dhjqwwv|zvtppplmhicb[UPKDC<:7976246347;@CJR[`glrw{}~zyyxwwrpqqmnoqnrrrnlie]VSMJEBAB?=@@>>CGJNV_fkqz~z|y|ywwtrssqpqqld][M@6/' )4:DT^gs|vpmihcbcc``baaa_``ccefinnqqrohe_XRMIEA@?@=AABDEEJLQWbfoyxuqmjgfgdgiosw}}ywuqqooononopqqqrutvxzyxyvphfaXROMIGHIGKMOOPUXX]dlpx{yytstvvx|}zwtqqnnnorqsttsvvrstrpqqmkib[UPH=71-)$$&*).37@B=>@>CBIKTOTZYcjilqyzy~zyzuv}}zvvv{~}}{zooig^YYSOHDD>>8?@CCGLQS]ceouqv}}zwyx{|yuqstw~~|}}{~}ushf]YYVUUSRORRS^dmuv}~vlifgedb`b_`chiinswy}|smih`XH61')&$" (.;ITcnu~}xtnsuttqsw|}rfceYP@0'!"  %4>FO]gou}Ļzvvtwusqqw{}wi[aej`K@>?@=/#!&+*$*+.8ELSU[bjv~z|tnxuaTQXYN@4.1:4-%+48;BFFJXgkrrw~xqqonjhjmnle^cedWMLLGA@552+*)&,+017<@FNU\clvxuqouohghdZ\[]XPTNKIGC@@B<9:8;8=AB@ELQ[Z]cgrx|||ypnhg`b\^b]X]df^bdbpd_`ee`ZZZXZWXTV[Y[^]dielpruvx}}yyrlnlh`]e^b`gcah\iqo^_qjchhebaeb]`cc`accgabghgfhjklnmlqy{wqrohhchhdjplmv}zuqzs{}qjljc\ZUPNLLGC@FLHCCFLONPTW]hjiqv|zuqtkqidkmmdnrur||ysreozjYVOPD:84'((&#"'/2+/=ELLU`ltw¾}xtnppqi^`hifbcinlkrsq}xdo|v`]of]WYTJMLFDCEGFGDOWWW^imt|~~}|zyy{us}{vuy}yuyywwtuvzv{|qo~tg^c`XQKKCCFB;;AHKFHS]]]fqv{ystwsmmrqlojsutqrohmrjY\`XNEE@>6301-+---/9<8>HQTY\douz{woihfZ\^]TT[ZVYY_a`cic__hcZS[YKFEDA::989<:::AEHKNV]bgntzytnllcYYZXUNNWUUTX^_cgikpnfrwmbgoeZY\[PMMLJHIJJFJPSTU_gjpx||yyrotwjlqnhlmplsquwxwrovpaiujX[^ZRMKIHHHEADHNLJMW[]aelrx|ztqqkh[a`ZXW^YX\da[^hnc\[mmVS\bUORPJLLDDDHGCBCNNKMU]abdkv~|qhb_YTLEHC@@<@CGENSRZailpx|~xysy{nidZXVMD@A@:89;;>DHMX`fku{wsrmec``^XTZYXV]^cdfnrst|zikys^PWYJ=>=<534677>EGHS^chmz|{||y{~}|zzythed`XQMMKDCEDEDILSW[Vfpljvztx}~vulad`RLJG=;=977<>BFMT\bir|¿|tpfc]XVSVRTVY^_glqv}{vsldec^XVVWXSV[Y[_eegmrqw{yz~tq~xb]kiXQTXPLLPQPPU\_agnsx{xtqqkigkjgmorrv~xnpof\\_XOPSTJJOQQPQW[Z[aeinnsw{|wymu{pjeadf^Y[aaadjlrz~{{ysrpmkjhfdhkddmqnnv{|}~~{{vtonkfdcd_Z`b_]edbhllopuw~w}}z{}}{{{ut~unmjiihcchkkmrs{~yyvvoqjjdb^^\SSUYNOWYYX_fkorw}|uvuplljkmieemomkoqwwwy}}}~~}{~|~x|~|y|~~zqrtmebabc^_ahglsvx{ytzstssusvxz||~}yxsuqmmknplmswvx|}wtsskffkja^ahceafhkmjptuwtx{~zvz}~uvwvuptpooqooppvwuw{{{}{{xzz{twx|uzwz|yy}zx{ztvtzuvpstsspsrwtuux|{}|~xuwtskkopfahmf\`fg``bidckmiinurnowyuqt|vr~ztv{}wrwxzxw{|||}~xwvsrqojikhgfgfgjjlkpquvty}}}}{xwzxsnqqpmkmjmlkjjlmmmpsqswyyy~~|zy{zyz{{}~~~~}yzxuqtsqopqrrqstwwvz{||~~}}y{|~{xzzzzx{}}{z~~}~~{|x}y|yx{|uptxtpptysrt{{y{}~}}}}yz}zwvzywvuvzyvuz~yw|~}z|||~~}|xz{|zw{|}|~~~~}}{xyyvttwwvvx{{}}~}|}~|z}}}{{}}||~~~~~~}|z{{zxxyywuvxwvwyxxy{{{}}~~~~}~~~~~~~~{}}{zzzxxxxvvuvvuttvvtvvvvwxxyzz{|||}~~}}~}}~~}~~~~}|||||||{}}||}}}~}}~}}|||{{zzyyyyxxxzyxxzz{zz|~}}~~~~~~~~~~~}}|{zxxwwvvvuvvwwxxxyz{{|}}}~~~~~~}}|}||{{||||||~~~~~~~~~~~~~~~~}}}}}||}|{z{|{z{zzyyyyyxyyxxyyyxyzzzz{||{|}~~~~}|||{zzzzyyyyzzzz{{|}|}~~~}~~~~~}}~~}}}}}|}|{||{{|{{{||}|}~~}}|}||||||||||}}}}~~~~~~}}|||{{|{|||}}~~~~~~~~~~~~~~~~~~~~~QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/excelent.wav000066400000000000000000000722741475442401000264250ustar00rootroot00000000000000RIFFtWAVEfmt ++datat/\vqjwɘqza@q_VhjjDRVFVmsszsXXSv|dmwҮdm[%w_4\j_.[V;üsv)&dmvՀ_JXI2+@ռɷ썜J\=IdzIz8I\@q_mmd8qM "2";D.I.=Oz;ORd|enɜáÛJMޥΘaq@\X|&)%4&"a=svIjX@ejżɳV&7RIVwhí[@X"7zwedwDMFX.nXF=."qSJіMjqjIXɖڏ@|_\sIs;[vnds|I=ae4=A+RD=M "/+OM/@|q|I7[\4S [@%7 &;4D=8nvѺѶѤsvvXd@;@AV\|m2MR=nR;[q_de[@dndsF8OO@J@4M)OFXdOsjnj[mhzz̮|swŶտڿ\))  +2"" 4) ;Mdzhnnazqsն̿ұmMq|VhnVe|a_m[_Maq_JMXVSd\J[dnnhvmwwnvjz|ss||smMdma[SI7Oa@4A /2;SIDR_nvnSq|qſqw|_FSdddI.;Oddea[j_VaVJ[SdFARRszh\hheVvȥvmwhRadh\RR\wqhmah|nmjjddnnnRXmssejv|swwvndqqszwmsvjmsmv|dRaeemn\av|||zv|wwn||v|vnsqnqw|swmjshmvsw|z||mjXRdmaS_djv||vw|wsqvswwqaeszmjsmssdje_nvmnqmzshesznjjnvw|zz|svzvzzwwvsn|hhwvmnvswqjwvsnsssjjzzqsz|wvsmnzvmnmvwwws|z|zwwz|wsjs|wvjjqvwejmwsqvqvz||sv|zwqqvz||||wqnvw|v||w|zwzzjhv)R|jhMvvvs|s|s\q|wjnnesz/d|v|msen_jsss_wXO2Xjwj[evjzvhJOhshwqRVaanɘ__;q4[|SMIwhm=jS&w7z4JV_mdFdn;J_D=\7M|;Oswv+d\JÛVXvm&Xj%Vnjdvh.@Ijw;qs_m)Mjn=A4XnR&jadqhqv\va@Vz\2@SJAVh[\Dsd|w2v\haSJSz@vXn_RXwnjIdhOaA;ҍ|nOS[;ve|d_FMwV \@=mXm|qOvA\sF)sm\qR@ |7_RA_eF4[7DnhImS\Dm&|smhXJV8R=j)MĂ v@S=+vqn|҉vJhsdvhwVzqmMz|veVeAas=jF_|sazjqnmnz\Vnv\_JvImmRJ[JeswO87wX;|evmXh[\̥nISajmdj/qevv.sOADm_eSD\q[vaI|_zmwq|haSmqva|s|\_2ɏ2FdzndjFmjhw_z2e_8;%2qzeqsJJSqwwRvs[mem@;nMM\ Avv|vv\eR|XhwjeInmdwVmw=)@qhqnnewhFhhjzz_evw\ejhS8JXaesmj|ajmmqwXnqjqJs__[d\mhq|\nM;sA|dzjaesn\mFhwjVIhMJnS\jO_q@4Iw[v[sXzdIjv|qX_qj=ejhj\Xhs|hMdVsahSns[\\|qwhw\nnnsaj|jsq|w_O_V_svz_qSjz|zmd|jm\njMzdA[Ma\I\\a[\J|aee_|zz||hw|ezjV\JF@/%8)+".278DOOMhMqnj|jêҮêűßΨȜζwzmssessnsz_hq[aeOMD4% "+);.IIMXqnv|̱̼ÍըäŨ|zv||zqh||jqvshw[vde\mheSaO_[MOO8J/2=.A@@OSF[[ajnwvåΘҨn|vszjmhmvmjeja_naV\VmRhjmdsjmssjvhzqsjmqndqha\s[[h[_eXw[mza|szqnswwvzzvzwmha_[MD;8)"%7)2.@=F\[nqwvɤ̥ñóŤvnsqwhmwMe_=ah@mdI_M@aRJ[SX[FXSD\D@\FSM8SDO\S\j[mmjssä÷̼ҺѼ̮Ⱥȱvqnmhmhndj_emsz|sjz|swjwwdasn\njShJRIA@27/%2)%+&7D/FSORawj̷ȼ|hwwwzsnvjwvmhveav[qa\w[an\zhaqhn_XeMAI8@;7);+7.7;DDFDDRMemmzî÷|zqw|znzw|wnjz\zeaj\\\DdSRdadenhhh\dae_R_RM[SSVFXDORRFXRJX_[V\nqmw|źúտѷs||eeMJVMAR[ODAFIXR\XR+7@4J=A4%/)4;;;;28AJIOFAF+FF=J2;;@J\amsq̿ñzhjXeXa\aeMh__wR[O@R8=FF=8+44I4SD)&"4I+4/)%82+/"=@D4=72==OMI@@SSMVJS_[avzsvծwqj|_ehm[ORSM\X@JADSAOA===IO=A4@J[_IRAOVDRO24=FFVOJXa\qzeVq_e[D[M\aXJIaRam\dOXdemjnnwγnsssmmmd_MXdJSDMI87A@=D4@@8=D;;;87D8JMJJFaX\_jqqdanjwnjs|||n|njqjsnnsjnvemvjswnwqmmnjqa\a_aaa_\MVXe[X_d_R[d\\[X_dX[dejanwvvq|w|nmqzdej\masj\[_\\X_JSJFRDMDAJMAIFFIJO_a_heqennmszzvv|s|||zwvsqnqmejjhehe\daad_adV\XVRRJJOM\XR__\[_aVS\[Xh[[d[hddjnqnamndmvmsqzww|wzzvw|vzvqznjshhmh\deXVj[_a[a\_eea\X_X_[SRIO[S[eR_[adhhamddahenhqvqnswzw|w|zz|zzz|snqqjhmqqhvzvv||wzvwqhseehaejensvzqdm\deejnmvvsvvwwnqhhvvzvw||mhdvqjnnvdahjh\nwqswwz|n|njnwwemwqsz|||sm\XROXS[\hhmw|vqswvaemjd[dmd[_heVV_h_\nmhejwsnw|zzv|z|wzzvsqqhadehdhhhjhqqzsz|zz|wwqvqwvvwvwwvzszzzvsq|wvq||wzwwzwmsvsqs|zz|zndzhv||dwzv_awnevwvsjVn|ssnhwnhwsnvjqvjw|zd_|ahvvwz|||vvnvzs||w||qzwmzvw_n||wvsv|Rnvdwnvaqv[zdsdvmwzhmwsMesnnwwajd\wOhIn|eX_zvzwhm|s[[e|Xqzwq|hn[Mewmqv|w|V||dwwzj|dVOw\m|qmsqzenvszweszwdsww_OvemzwdzdzhmhmsseVzvnqva[jwzjzwsvhvzzVs|mjq|z|zehsw||nvwns||vIdeJv[S_swqs|v_zvJaeOzdFM|ewdade\jvnvzvzsssmq|mzzsszhv|zsv|v|mhswsmwnv|samsvqhssdww[zmmvvde_|wzs|qn|wsvw|sn|mzXmw|qsssn|hqzvvdz|wwvzq|zvzq_jewhejsz|szd|vw|zvzjvszsvzwjzhwsvn|ws|vwvzh|nz|zw|vv|s|swqjsq||zvdswnnsvjsvwwzmjvwzvws|vqzj|mzqszssvzwzvwwvvq|vzvs||w|szdjmszwz|av|nmszwqzvqmsvsnvqsszdwshsvq|m||svwv|zwzw|zvzzzszzzszvqvzwzvzzwzn|||vz|sn||zsw|w|zw||q|||w|z||||||wz||zz|||||||QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/fight.wav000066400000000000000000000237521475442401000257140ustar00rootroot00000000000000RIFF'WAVEfmt ++fact&data&~~~~~~~~~}~}}}~}|~}~|~~{~~{~~~~~~~}}}~~~|~}~~}|~||~~}|~~}~}}}||~~z|~w|{~{}{}}~{|}~}}}~|~~}||{z~}|{y~{~~~{|z~|~~~}}|~}~~|~}~x~~z|~z|~x~~}}}~{|{~|~~{}z}}}|~z~|y}~zy}}y~|}|{|}~z}w~{w|vx|~wxz}}zyx~}~y}~{}{~yz|z}|x~~z|z~y}vv}yyz}|~z~~t}~{z|{{yxz~~~{u~~||t}~~x|~}x~vy~{x|{zxvr}~~}z}|~x~|zz}|xu~~z~y~}~~y}}}~|{v||~~~w~x~x|w~~~}z{{~x}uy}z~|~}|{z{y~||~~{~}~t|v~wzxxw}{yz{x{zyxix|}ux|{u~~zx{~x|||{{w|~v~~}}}{v{zp|{yw}{~u~{~}tw~}zyz}|~wy}}|t|{z{~}|x}x|}~{xxyvzv~}uu|{{yy|nwx|ur{~y|zrsz~|~w{v}y}wuq~y|}ow~}{}yzus|w{~~w}wy~{yxzx|yy{~{|}{~}||x|}}{}~xx~{wv~~}{~vtz~{v{qtxuy~uz|yv~w~}~~}x{~z~v}y|{}~}s}~r~{w||slzvq{v|yy{wplx|u~yw~{}y|y~}ww}~~wrrx}zz~l~}uy|p~vr{ryyzyy|{v{zy|}{~zsz}~}w}u~{{p|ztr~{w~~~y}z}yvn{zvwxxyz}|tuvs|wsk{zqhoq{|xxzxwptjuy|yz|}y}x||nplzwj}~yy{r~sv}~~ux{}zys{}|{y{xyzx~{~~~z}y|t~}uzv~~~h~uxyp|}}{z~~ow~}x~t{}vzz|x~|}v}tv}~}u~z{{}~w{|t{z|sv{~o|{rq}zpw~tz}{}vxz|z~xpxxpywuw{zx}z|~z}u{v~}t{~wrwyvxu|wujuzuuvz}}q}{y}qpwy~}{|x{txqwz||w}zst~ss|}{}{}}{~zyqzz}zvys{|zxxty|y}rt|tqu~|w}~wtyytu~~~qy{z}{xzvx{||xz||{~y|}{ws|~v{pz||u{{}xwx|}mzw{w{sz~{wx~{~w~zvx~{}~~y|||xzzw~u{{quz~~{twyrnt}}}{z}yxs|~tux|}y|~y~vy{z|}zmw}vzy~}vx|yu}sut||}{mv|~|yy|~y~x{~zv|xp~y|~usw{wu~~zy|~u|{{|xy|sx{}}zx}ypwt|usn|uv~tvsytyzs|~x{y}z}uy|wt|}x{q~~yu~tv{yw|s}x~|q}{|~z}}|}|}uxtzuw}}~{z{~x~|{~ytv{|uy~~~z~xyzzru}wvr}~t|}zymsppq|xx~yu~xyzt~um|vzz{y~||}w{{w}wyy}z{}~|z~~xzttz~xtwvrm~rz~z~v{|yz|}zwojmu|ouwz}u~~{p~{zvwjvqsx~oo~|zx}x|u}xssyvv|}~|{|o~z}|umjvx~xrywqrk|ytpvcqyyp|gwzjlhzt[vtjypro]xuiwo|t~r~{uuaahng^rdTaT^bZWaK_med]hWdtdgqppzzxwyvxsveehdllotnesth{uvkidafgsvwuqg`[OQPW_ju|иyX;$ @Qet{xm`UN<7:7>ATVSVn|ådL:%&1BTur\F;=@Oaz~x|txzw|ztgccedtqWMB@KTe~v^TP@EDOeylv~tբD,ZÜ_>')??7AJMLRT_tvizΪxm\7386_zj`TA,-3IZn|ufW_kyƺnZEGMIKiv_LSlonr|n^SQ]bjѭq@9(QxxfPJRH8543BH\~mttnuyw~{v1GL/7oӽ}os~sYKMEEPwvrw|ĎOF_a\h~xt`QQ^[G6;CQg~qe\a_^izy{~۞!->1_ݔnK,Kogi~|pqtvr^r{b''H_rwswz|teWIIQqx{~zٞ8 ZsQWnV`wr/6`p^jukvqiairpn~pE.Ophftvgh|jVF32..NjwvytimzE:fukor]Q_yvhgqdHCSj}}rn|zwty}xedcRLFLQ\qrnrz{sadZLUgnw}ys{{ox}ȿfJA<8Milfs|{}bWO<8MTVo~~vvzurx~_Xw|wldwsZ\fmtqnnh_`cinlq}tvuvxg^lo]V_hc_NDXhu}~tyxl_eqne]^v}{urlhdbclryx~{z~ypoxy}z|{sptxwyxvzrvb^myzmm{uxtuwwyzzvwwyzsrtvrqpprurogikj\\chkkm|~{yorn`Z_[\_^cfnnox|pnswppuwz~~y|~yvuttpr}y~{wzy~}|ntrnum`eijlikru{}~~ynjnqf_hkgd\^hsssv|vr{zyuttstvw~~}w{|uru||~~{uoyy{{yz~}vuvxvzvruqt{{~wsonnggkops{~w{{{zwosxz|~ywvppsu|}}~{}~}xsnkqtutrr|{~|}yt}ztpplgkljqnsuw}{yvtmqrmsvw||}|xv|||yu~{~~{}}}~}{~}~y|~}|{yysqrromnmomosw|}x|~{~}|}}~}w~||{~}{~zz~~~}zz{}z||}}}{{vtspovwvrv|zxxvsrosvz}yz}yvy~zwvwxyxx{~}|}}{xwvvyxwxyzzzxx|~~ywz}}{z|zxvvutvz~}~z}}}|~~|}|{yttuuuux|{yy|}{}~~|y~~|}|{yy{yyy{~|}~}~}~}~}}z|~~~~|}|yuw|}~~{}{}~~}|}}~}~z}zy}}zx{y{~}}yvx}}~~~}y{yz{}zu|xv|~{z|xr{~x{ovyzw~yz~|}yuxw|}}}t|{{xy{rv}sxzgxrx{t}w|x~z~yxyz~z}z|x{xy~~}ovtzxw{w||yzxz|y{z}||}}x~xtry~{huusw~}j|pbkd|cpz|~}}}}{zw|s{{{||x|ortyp}n~q~{tzmyt}rlt]|fs|sz{}rz~{w~qzzosysuuuz|uw|tm||}~ptu{w~tuwwzyg{pkscyd_za]qhuzxxy|r|y|}~{{t||xwuy~uu~xpzopsnrkwrmqukjwuwrxoszktvom{t~zu|}tz}{yu|zx{~|}~~~}}~w||yx~xxvswvyxvvzytxzsv|rxw{suyuv~uxv}{z||y~}y~}||z~~}||}~}~|y}|~~~}}zzz}~{}}x|z}~{}}~}~}}~|{}z|w|x~~z|~z}y{vz|}}~~||~}|{}}{}|{~~|{{z~|y|~{}~{}{}|}}}~z}~}~~~}}{}~|~}||{|~~|~wy{}z{{~}}|~}~}|{~y}{y~~~zy|~}~|~}{~~}~z~~y~x~|}~yz{|{}~|}~}~|}~}{}|{}|~|{~~||~{|}}~~~|~}|y||{{}~~~~~~~~~~~~~|{}|}}~~~}~~~}~~}}||~~}~~~~~~}~~z~~~~~}}}}}}||~~}}|}}}}|}~}~|~}~|}~~~~~~~|~{~|~~|}~}}||{{|{}|}{{{}{}}~~~||}~}}~~{zz}||}~|~}|~}|||~}|}}}~|~~~}|~~~}{~}~~~~~~~}~~}}~~~~~}~~~~~~~~~~~QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/ra/flawless.wav000066400000000000000000001232741475442401000264330ustar00rootroot00000000000000RIFFWAVEfmt ++data|}}}||}}}|}|}}|}z|z||}}||}}vv}z}|||}|}}|y}vw}z}|}wv}|}v}zz}}|}yt|}}}|y}sp|}yw|zzv}|}|t}vyw|y}wvyzw|yzvw|zyyyz}}|zw}}ntt}||qq|vzz||zzw}yg|wh}vSatzV}zv|ve\[Mms|}kzwqqwddgv|k}sznsqmhpnvvksv}}}}ygzqqnPa||ns}twgSeIp}}nyjzm^_z|sOgXp|_as}ha|stjt}ngO4nmXb}mpwe}kwps}ahjsYqnapqyMk_hV&YUXjzSLS4eh}_yztbhm^OnwahUnb,ÃYUDbyC|[}#syqOg\vw^e}tPhzteg|vm}z|>FyÏdsUYg&_ms[nqSFzPzwdskXnY\vYpzwPs}dvAjh|w|X|L^=wab|ktpnv^myzbkphnVg|tqv|naynqvzgtvU}pjvqjjt|ymqSet|v|Ss|thyhhs|tsqwhJvb}qssv}ggtyeS|S|mtn|pveGn|g|tzLsddhjht\VFbRLsmhkY^zdqkm|d|||hbbksnnwmyvts}}hvezvynptzqa|gymphtgj}|jppjpqjvsjwhajRqjtpj||zvsvnzzzwttzywt|wMnmw}|mt||awatev}v}yyyqwsdzU_mt|m\atv|nve|qm}_wgye}bkswk|_qhjs\V_R\MJ=MJODOJVh[msezwqv˴ɫ||}bzmyt}^spek\sOkpPvj[}gjwkh[g^SntXmqtkykdXq^nwgmpekhssj|tqnnbd|Ya[UV@ODDRIDVLVgjkŹŨ³zyys}|hzhX[UeX^\[YSI;;JLSX[Yaa[ebbgeekjhaeXFL;>7@;///)%).488RJXmjs|˼ƺpykºƳtszvzzvjbYPPGLR[RUGJJ8MDDLLX\YYOMO>:D285",("#+2>>J^Smty̹Ŵ|syyz¶y}|zt}jgk\\pddeeY[YRYR[dbV\SJC/1 ,/.8=;@RVYqy}|ztj_bYehÿ|zkhedt­|mswyzsegj_bpvv|vjykkdRA@#(4>RI[^enmw|}tmnjhkkw˽wyvwȿkpa[egqkzwzvkngY_dkgymktvtsvy}edU71 &8SXhmhhjd[[hp˿zp}}swsqm}̶}vkjqŷnYPJJUgzmeaa[k|wpjmtmytmYPS\U^pqsdwqwXJ4(4RXtz}ztjedepzz¶}y}tz¿}}km÷h^M=@IRdwXSIJY^qyda^gdbsjX\Yb^^k|jtzshjwepqywzqnkXXP;8154=MUbss}tvv˽qt|t|qktnkpvhnkekdnjU^SLV_^[aYYUPPDVVbb_tkmUdDOLP\akyswn[V\avqmbeVRO[hy·|yqtkdg[VYSMM^aYaah[Fj^[j^kdX__haqjmObed|hwzte[S=@RYjyy}zbSL55721I@AOGD[adkptvmqnv˽Ž˼}sygmm\YXOR[XVjddeRPPLILXUapqq^MF/)&:PPpyspbk_Vk_qde\JF21/.1FCFUMMMJMG[jqt}ɼ̹|}pn|vw|y||kedXYj_pq[\bMPRG=GDD7I:OU\}zzsn_D;45@:PaghtgX\PFPSOVUPSL:857=LVhtpƽɿ´|ynkksspy|smpgYDLG:@ALVJOII7:A7GS\jmdbSFFICPVYX\YOI@//1+)+&))+1=IUmt}¶Ƽ}}||ptjba\ad[^UJD852148FCGOPLOOOOOSVUYaaXbe[VXA84(# "/@DV^jpz||}ȼtng_VXaX^^d_\XSROPXU[SYVLIJGLPVbajnhb^XMD;2.(% #/AJ[kvÿ}qkjhtt}}|vswnhe[\YV[_g[aaSSSDRLOVRVSSOMOFGMJMI@>711+(+,12=>CJMS_gjt|z|z¿Ƴ}tzyt|qwwppgae^\Xd[R_SORMPSMROJJFCGFUUV\__^ee_ghabYRRFCA@>GGJIJMOPV_hjv}|y}z|se^YS^_dhgdaVYXYYa\^^UMMDMPUYa_b\\\\\[YUG>1&(2;JUetyɿzwvmqpskdnjm__dXXUa^[_VXUPGCI:77CIRPRUSORUUSUMPCD>4421.5;;LM[akpt}vsw|ƿÿyjeUU[OXXaYSU\YS_[XPJFC@>CAJJGIJPSYXYYUPGIA@=;54.41;APXbknsww}}}}Ƽzytjjkmqq^^YRUX[UPULYeeejmgggkg^UaXSPP\_V_ehhjs}|sg\VD:4%+(5CG[bwyzz´}zw}yskebba\[UPMIMPODJC=DGDILCFMLAIDGPMPLMMXPLYdaVaVjagmmpp|y}}v|tkeXPLC>AI=PLU^eq˷ynqn_bRLSLIMJLIGJMOJJOJ@C>>A74@55J:CA@;LCU=PU=GPMMRgLObXG\aX_ejkykjvn_wq}y}|jnenwyqb}qtvYqydUnRw>Xy:>gA" PgF8nSJn%wD)eIYO[>s:mbn^JUz/mz> ;X.k̘|柇}hFhV_^ɢ_úSFFϐ^+ ۭ2^zzYwUm[qzbA8\h\8v=n&>%yVAz^gsYM8ne_j\nz7RGb^+z4h7JDF8pwzyzhzɕq|^ehvbkaj|e}JY_snwphvYIOthzzhItPe/C[JS1SsR}VXRnb}vpJkkmp}dn|RVj)}a}[bhv>djebp}_pww;ȁq^>#wd7Xnqzw|OgqhgmPwJFG mjUFpAJ=^^.vF8OPhODMmvwbF\J_Rjtaeype\[w^XyOSetsX\\kk.MnmVRnezaFn>dneR}Fq\2;8e[I[vnShgn^C|ssYq|ke=_mvdqR=I5mm7hwq#FX:zaq4tky}npt|O}^awy|qtb5Uqy[^_\OMG[pRbAqqԃSh>g}vtkLÏd[gpktd|U||||dvqUm|ejzMtaY[Yzs[IRJpwJUY=j_5v>tVUkyka|v\qwkd^ne_kq\It_vtzRInnjPSv^VnkUy|jsb_pk_avwnV&e}}tvqnjV&"ak,shypmUL@z_eX[zO@SYCk8.+Dm8mhdyz@#ŏwmPzh[@kpvyMneCt|swqwX=MU^sVmmXtXMs[bFt+ahL[^vLVVGznh[OXgpzzyXaOdgjasq^J|jnyI [w}^_XVqjSqCp|t^aw|tpy[y}@Onm=@X>tzzjdvwS\Ovts\YVejabXh}vn|bRXk_tq;bshk}ztz}wthvy|ejphgpmYnhvUpM[tvvbk[^kbJLkd^Vg_qJvb[nqVj}O\shva[zVhzs}|kptbezbqqkX^gseheY|nVntpYh_sqstt|[b|}URsanej^Y\wwtMm_pajt}nkybq\sa}gq_hvvyp[|q|qAsn\X|}znsjant[t__vhhtnpqO|swsbzhdwznvmagvjzw}vh|nvz}qnv|vwps}h|bpMns_[gz|}}z}jjpvhtasy_eybhyhYh}tswykzpjgj[bwqngp}n}z|zzpt|ytvwzsk}m|X^Xzhzszvvy}s|ww}pzsn}qsy|yswadq|zn[|yzymtzytpz}wk|etd}z}t|wzpymtt}v}mytv|tjw}ys|z}zt|wntvzywsyqwwzv}|v|zwz|qqg}y|}v|vs}|y|y}y}zyyzyw}}|y|qzmvppttzhywpwvsqpzzzwpys}}}z}}z}}ynq|}|zk}||}z}yyvywn}tz}yvv}kvwt|qpwsmy}ssnw}|wqmwv|ypqv}wytvz}}}|z}}}wzn}||}|}zzk}}}|}}yny|z}}zwys}vvy}|}||}zzwy}}ywzv|}}}wz|}}v|}yy|qwytyzq|||vv}y}y|zz}z}|wy||}|}|}y}|y}z|}|ytwy}wyz}|}wz}wzswzz}|z}y|y}}z}|y}}y|}}|}|}|}||||}|t||yz|||z|yzyz|zz}|||}}}z}|}}wz}zz|}|}}||}zzz}|y}zy|y}|}|}|z|}}y}yv||z}}z}|wzzy}|}|}}|yz||y}}}}zz}}}}}}|}}|||}z|}|}vwzswzww|}||z}ywzzz|}z}}}}||||||y}z}||}}}}}|zyz}|}}}y}|}}z}y}}}}||}}|z|}}}}zz|z}z}wz|z|yz}}z}z}}z|||vyw|w|yt|svwpvnsmkjjemdegdegehjkknmsstvyw}|}|}|}wzzswqntjpnhkjhgkghgghjjmghgebeaa^_[Y^Y\\__ebngpqsv}||}}ytwwqvmmkjjk_e^^\a[Y[YY[V[[X\\^_^ag_genhnknhmhkkhjgbdgbdhbejehhppnqvwv}|||sttpkgkhbb_^[V\[SOPRJMRROJXOUPX\PR\aVbed_mhhgdjjdhadeab_aa_beaehhgppnss}zýöȽ}|y}wvwmsmdnha__XY^O\UMRRMJSMIPLSPPJ[MUVSUOVVYPOUPSVPMYUSXYRb\\adkhpqqyzż̿ƿ°y}y|ypnqpkndX_nU^e_RS\Pk^VYV\V^V\USOPJMLJCI@>@C:@CAF=OFSUURVgk^pntw}̽ȼ}sv}pssgsh__^aaXS[\OXYVVPSUMMOGAGDCA8@>;=A;AJF>MJRMVR_[[hkmqvȿªsvs|DaYghhhpb_bhaUbYLD>=/2(&  "#)44:DAJMY___dntwpѴyùŶsshgwpnskpvys|yqt|}vwqpmkke\agzvgbVLGG8# (2:@Rek|·¿vpbSV_X@44DPSLFRYnwzz|qaSD::2"" " 1@AISXXjqt|ƿyzyyzz}wqshPJOJMFG>=IJRPOP^pspkm|}vjhh\XI818=)&&(%.;IGF_qssƺȺ}z|}z|z|tytwvqppsdhngbbg_g_[[^bbabdbhgghegeeeade_db^dheeejnmqttz|}||}zy|zz}zwwyswwpnqqmmpmkggkhdab^\Y\Y[XUVY[Y[[Xaa_bhhhjhkknkjmnpnmnmwyyz|}wvqspmjhmmhhjhjhgekkeeehhhdgehhjjgdkjhmkmpqvsvwyzyzwzzz}wyyz|y|}z|}}||ztsqpsqnnkkqnkmknppnnpqsppsqvstsvtv|wvzy|}}}}}yyywssqnspqsttw|}}|vtvtpkmmmjkkmppnpqqsspqqppqpqqstsywzv||z|z|zz|||zzzzzyyytwzvvtwwyzw}zzyzwvvttsqpsqpppttttqtvyyvwyzy||zy||z}z}}}|y|z|zyyz}}}||zzzyyvwyywyzz|zz||}}}|y||zyywvywvsssqqppqqpqwtwvy}}}||yvwwtsssvvtstyywyz}z}}||zzwwwvwzzyz||}||z|z||}}}}|}||}}}}}}}}}}|}zyyvtwyvtvvwzywzwz|zz||||}}|}}|}}}|zzwyywyvwwnUMbet}ygkw\)hhy|eqwYRgtz||w|eIphUwwks^wmSP[n^\y_n}vwsavymnjpty|ysvqmmtedaUdjeP_h[^nj_hgwnyjzqtqpdeegeXakjbswƽ}|zqdnwm[knsgjtv|zsqwvga_[M=;7&% """.5DLOVeknwvv|·ű}yhegkpqhebqwqpsejpwpaVXRS[bXS[VXRabg^jb_SVXXSD,""%+#&"(,>I_e_^gs}ŽúzmgmsyºƷywtmjvqnmmejmjhhb^^_b\RSIIFJXRIRYYSMD5(  ,>CJ\bgnds|kwz|ŷϷ½zznmbX_YMe_FR[SVVLVM;88/21)% .,1A@CDFJJCFF=275215874;GPY[Ydggny|}}wzvtppqtmgdaagYRROPXURLMXURSUSRRPMPVSRRXV[^^^aghb\PJJOSMFD;AGGMYXSR\gmyyz}zy|}zz|ywzwwzyttsnqdbbY[^\VVVSV[^^PISab^XYYVUUYXYUVX\epeagqtqeee\UURULFCJPPUYdgmw}¿}y}}}|vvspnnnqmjeenpkgg^\_bhd^^_djkjjebeeea\a\VXXXUSRUSSY^bdddnwwvmgg_VUMJ>1:@>GMLYbkwÿÿƿÿ}|}}zvtt|z|yspkgegdYMGRRF>CILG=CMOGFGRYSLJPSPRV\XLGSabXUXajppnw}yzwq_UXXL;2.8;:;AJ[jvżȹ|wvvtttw|wsqa_\UUOMPJ=CLOJ@DI@FL>=DGDC@@CLLA:AJDACFDCFOOGJVXV[daegqnjv|}zs}wspyyzqpv}}|̿|wnge\XRICAA==@CJGJ_egpy}wnnwvmdbemeYU^e[LPUXVJFJLIFDDGACFICIGJLMOOR[SUYa^bbhnpyww|ƿ}y}sjhea\[XVXY[Y^eehqst|}zwwvqkehga[abY[\\\^d_Y\\^_\VRY[UP^^\SX\de_\_kj_dkkpnkqsv}zw|}|||}}|||yqmkgeaa\adaabejppsw}}zzywttkmmqkgjmmdgea^Y\SLMOIDJJIMOLU_dadptvz}}}|}}w|zwy|wy}|ytqvpkkpqjjpsqwyztqnmb^a[VYVRPYYY\Y[\____dke[dkjhdjqspjmvwtqmtwsssnvyqvy}|}|}yz||vqsqkedb^UUUPOURSX\bemqvz||vyv|ywvv|}vw|}zwywwyssvttmkspkjmqpnksqwqwzz}y}|}ywz|}z|||zwvyywtvywttvqmjjgdb^_\\[_behnqywvvttqnkjkke\ddYY^a^[V^b[[Yag\^mhhkmqzw||}|||yywwvpsttnpsvvyzvvwmpehkedaddb\adbb__gb_dagb_ba_aa_^[ba^^\dgehkppvyy}}|z|}tqvqhdde^\_\\_abahkpqv}}wwyvknmjnegghdahgggkmhnnttnvzvsszzvqvvtspvstppsstqyywwz}}}z||yyywttvnpqmmpmmpsqtwzz}}|qpvvnkqsvpswwzwyy|vs}zspssmnmknkkjhhnkghjkhhmgknjjjvqkmv|tvy}}}wvspmkhdehgegjkmmsww|z}zvwyqstsmppnkmmkkhkhhhdehgaabg^\bg\bghekpnsyyw|z}}yz}}|wv}|tnw}tnpstpknkmkjegjededdddbaggdejnmpptvwww}|}z|}}}}||}z}|zz|}|zty|zvtyytswvwvtzzyyy}}y||||}}||zzyywwy|zwwz}zyy|wwwzwzzwz}}|}}}wz}|yz}}}}zy||wv|zywz||wz||zz||zwz|wyzyz|z|}|yyz|}zwy|}wz|}}|}}}}yy}|wy}||}}}}}|zz}ywyywwwwzywy||vy}}wy}}|z}}}}}}|zz|zvwyyywwww|yy|||}}}}z|}|zz}|z}}}|}|}}|}}}}||||yzz|zwwyzywzzzyz||}}}}}|}}}}||||||||}}}}}}}|}}||}}}}}}}}}}}}}}}|||yz|zy||z|||}|}}}|}}|}|z||zyzzzzyyyzyyyyzzz||||}}|}}|||||zz|||||}}}}}}}||}}|}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}|}}|||}}||}}}}}}}}}}}}|||||||}||}}}QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/000077500000000000000000000000001475442401000244325ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/rune1.wav000066400000000000000000000351301475442401000262050ustar00rootroot00000000000000RIFFP:WAVEfmt ++data9~xsnkheba__]]]]]]]^^__`aabcddeffghijlmnprtwy}me~iep~~vpkfdbbdgjoty~|xsnid`]ZWUTSTTWZ^cjqz}xrnjfca`^]\[[[[\\\\]]^__`aabcddfgghjkmoqsvz}zrmjhhkvwlmy{rkfcabcfjnsw}|wrmhd`\YWUTTTVY]bipyyriaZURONMMMOQRUX[^aehjmoqrtuwxyz{|~xkaXSNKIFEHVpuZN_mde~jZKN`igcbemv{yvt{~{wtqmhc^ZVUVY^caZW`lwÿwnf`]\]__ZTTY\ada\[_cfijjjkklnpsw{{ncYRMIGFEDB@=BZq_Oaqk{{raMJZb[RQU\emw}xyxqkc[SLHFDEFJT]^Y\lvĽvlc]WUSSU[^ZVY_chgbbjorstuuuuttvx{½{nf`YURQQRRQOJC?XSASh~xusr{mXRSVXZ\_bfhkpwwmcXND>;:8778?O^_`vxnd\VRONMMR[_[]enusrzxsrojjnpqqrqolhdYMBPVD]m~~|}la_^][XTQOPRX^fo{~yri_VOJEB?>=AP_ah}ÿti^UOLKIHFJTXV]fmonv~~|{|~zssrpllqttrqponnmkf[NYkevyqhb`__enw{uh\QF>=?CJS]gsyqg^TKD=65DLLXkypg_YWWWTU]^bmv~||vpe``db]\]`cdeddfghlry{nlx}}m]WXWVZcq}~rsfZRKFHMQW_hq~|ww{~reZOC99EEDP]ir|tmgb__irmov||wtw{~ynlhc`]XRV]\VUZ^_adkwja`]]ahr}yr}uidtwr}{tjc_\YXXVX_fo{}x{~}sgYJGIFO]igmyxwvutpifmqu}wrppnjinrw~vxsor{wroiaWRTWYYZ^djq}{|vqmg^E@A=83.,5AO[gmeXG833BOcvjheddca][YROVWSZnzneebcpĿ|eODAEL[pƾm^NACKVf{~ldkv|}mb`]YX^gkmng]Wwwv~w~laWK=/& "0CXnzwri_XC?LWmǴ{kgf_XVVUSTQNPQLNW_i~vvwxubTMLRhwg_UB55BTlwegu}Ĺ|tmgglz}xoe[Vfs~}}ske^UH8,!(>WmhVF?Kgöojf_\[\_`_`^]XUUWYar{lfmvͼvf^]`jy~n`UH?:>L^zmdddgwľ{vvwy~si`^q~}xzuu~ulkheeZJA71005BNXkp[Y]yzsqjb]]aeinnmnpohb\_mv}n^SUdvuc`ht}s`L:1/:OkiYWZh}}|ult|{qlzxv}skkpib\WUTQMKLS^inljjt|z}{vux~}{smlgba]YU\fpxyzunlim{ŭsbYPLN]tsgit~wobUH;31=Xxz^OMSc|{srtuz~{lwg_aegjkhgijlrqja\]bkr~umn{vbW\_gsvx{{yqifeiikotwohfiw}slhb_dno_]fmsx}}xl[I>79JautVDDRlŷ~q\Xsy[RUSUTOQ^e__`^[USWcx~ykb`lkYRT[fst]H=CTgyzxzP?Ha{m`VQMNYnyhXPJMSZcquvzuP54P~wk`[ft|~{zxbDU}neijeVP^nvzvk\RJKV]cjpspmkixnboss~lehp{qYG?E^ulIRS5=\r[QXukYaqvjWDAYzhH9BZp}|dNNjgYe~g^nyuydbmq~xysutnjo~{cQD. BxqTJ`yg^nogqpmw̳raX`ygIX}B%'Fqv^avfWap}wqpx}n_X[`diq|pgu`DGicQUoshlvz|q^T\j~}tjsioqo}vO(.W~ki]EUйumzzghyvjj{ij|nklszeaqd4 3`~x~jYXZasx`SYszcZ\^adch~q^fhQZjWU\r¢xd__o}ohmmfmrv{w{{gSRlwbbgeN823GmmbtdHW¥dYc~~t|ľiUIN\}dIMwsQE^tYMVbivs`UXpomtum`TYrz^LWyr}`LJ^ZDY}nkwzxw~sfgaZTXqxk`H5<[wo[\{j^zț[.,LhOGIQdz|jcjz|nejzvYD=IUcruronttt{qonknxkY[|`O\˫yZ_kKDYtreixyt[VRpzrjo}zjU>7KjºðtdRF@<;FPaw~vvxqf]XX_uymklr~zsqj]Z`lw|hgrvmrqglvyre[aw|nkvtk]RUixuef{lgq||x`Rdvdgyofrurja]`lqt|xrgdjotz}zxtuvuu~vbYakyslr}{vyvqkgo}j^itxwpjrvsvth`h|xmo~y`Ub|zzmegtnXSb{iY^q}xsnidcacgklaaj~v_]psbVR\vtoqx~vs{~vpnpx~}xw|{k_[apzzxqlmswwvtw~rlwzna_lzlZXeqzubUPSX[\epvumc`hquo_LHZv}enĥ}vuvzue`qp_Z_m|~tox~xf^[^`]TMOZioos|vjgimogQCFTdnjhmu}s^Vc~ŷ¾zq|lUP`s}n`]`cikjjov|}xl_bknlmq}o[av|sqz~xv{ujekv~||xs{wf]alzygZYbcYL@BReonkmnkgdhe``_^_aghkporuyzvsuvwree|Ƽwms|yszp]ZdrzxrkmrtmaXZao}~unqvjnxposv{{qbUQS]gignu~xh`eqy|wk\WVRKFHMVcnqngc_`egiihddgo{|xwux|vlkiggdhx{ov{wsv~~gUGJPQT]go{}tlr}yqfft|p`QOYjx{woq{}sjgmncRA4.2>JUdnnkmpnljfgkf]Yg~uspgcbbel{|~jbry_QPY_\Zdu}{}z}~tuvkaVMVkmZKHYsumo{vps{yqeWH<=FNSY[VWdq|ykb^ak}xrnjc`cp{|~u|u|~gWWcnrqou~wxwvy~ts}wkiu~}r_WZcvujb]]`flqx{x{}vllw|tmifa]^fijid``agqxsg]WZhxypkklmnddv~tos|÷plv|}|qmry~v|o[Zoxp}|}r^V`nzwg_^^chjf^YZar~pfdmqihknh\PLPYYUWYYZWVY[\ZZajtxwzxuqhddejoxr[T`v}vomquv|d]l}yuw{trxzfPHM`t|tcRKTcosoigkossrpka\ZXYWUTXYSNNPU\cehkicbgqy~vljlt~rmwzjblxz|ukpwovvoonjefoxucRIN`r|zn^RQT`hjigc_`fhf`TG?>CFIPWXSKJQZdiiluvplkhhoy~vminu~yrt~vorzzmdfowvohhkmjb\\`gkjggd_`ejmh]OKOTVY]^_`dheb^YTOMPQTY\[SLJNU\^[]ekqupeaeq{|shdhpx~~{jdfoytg]`m{sd]]age[Y\`gihfed\POUZ[YWZdnmbPA<@HMRVWTOHA?AHRXZZZapy~uh]Y]_chowxutw¿xe\`lw{sha^ckqspi_VSTVSQW[ZVUW[_^WNIJQW\beefd\ODBJS[``]YWROSYakpnkijlnswwqg`]\akv}|x|~vqtzmimtz~|vttsstvvuqia][VSYemkc__bb^YSPQSW\a^YVUTQOPQOJFDFKNMKMRX]behkgbadhllgcacjry}{ww|}zqnmlpuwxyuprzyl`[_cfiiggffddb_ZUSUXY[`de`XQMORRSNHDEHLQVXTLGKUalroe[WX^cb```afmsy|{vrtvxwuw}|ùȺ|ronqqtuupjhjmmic_afjklpsncYX\__\XX[^`adfc[TPONLKKJFFILPTXWQLJMVailg[RNQX_fjgcadlx~wrpsx}~~Ż|~|snnptvupkjkoqomkkoqnjijkkigc^YUUVVUUY^_ZVSRRRSTSOKKOW]_]XSPSX_`_][YVQNPW^ba__agntvusqopsx}wsuz¿½upqtwwroqtutniilqtqligikkjif_VQPSVURSVWTQOPSVVSQOPT\dgd^TNPXagid\QJFDGNV[\\[^cjoruvvuqqrtzwtvy~~|tonljjmrspkfbcfjoqqniea^\[\]^]YTPOQUVUSRRVZXTSSRTX]bec\UQSX_fie^WSOMOQV\`a``cinrrrpnkkmqy|vv}ÿ¿vlc\[`gmmje]XX[aghd^XROQTWYWSPPRRPLF@@EJPRQNNMLMQW^b_YRPSYcknlgb_^_^ZZ\`floqrrsssqnklpuwwutv}þn]SSYcije_YXXZ[]_aa_\YY[_`^ZXXZ^]UKFGLT[][UQONPT\ceb][\aehhfdccbbb`^]]_flpqpmlmpqpmkloqqqtw|}|{|l^[_dfd^Z[^abccddbaacfihdbaefec^YVUTTVWXWVVUVY]__`aaceeda_\XVWZ]_^]]\]`dgigcadhkkiggikortwxvtuxz{|~{mdced`\[_dilkifbabdimmkhgggeb`\YY\_^ZWUTTVZ\]\[[[^beea^]^]\[YYYXWUVZ^bdcaaaacb_]]aehknprrsvyzywwy}|tmfb_`achlmligghhhhhiiiigfed`\ZZ[]_`^YTRUY_a^ZXY_ehgeb`^^___[XY]`aaacfhigeb^ZXY_fkkkkmqwzzvroqw~zwqkhfehlnppomklnnkiijklljfa_`aabbbcc`[WW\_`]YWZahie`\]_```abba```acfikmkgb][\`ccbbekquxwtqqu{{xy~|ztmhhjnqponmnoonmmlkkkmmjgedegggggea][Z[\\[[\]acddddddddfhhfbabdimoomkjgc_^_```dinsvwussvy{|{xxy||y{~}zyxwtpnmllllmopommoqqonooomllkiiiigda^^`aa_\\]`cghgeddehkmliebcgjmmmkihhhhgfca`chlnpqpppprw{|zvstwy{|{zxy{}~~zyz{{wsonnmmnpqrrrqpqrronoruvvsqnmlkkjiihfbabehjjjigfgkopomihhhjjkkkjjiijjigeddfhklmnmmmquxywtqsvyyyywvvwz~~}|{{zyxvrpoonnnopqrsssrqprwyywtommqturmighkmljhghjjjjjmoppnmigfhkmnmkijlmmjhhjklmnonlkmpsvwwvuvwy{{zxvwz||xxwwwvtrqponnmmmmnorsqpqsuvwvutsstuvurnlkklkjhggikkjijknqrpnlllmnopnmllllllkkkmpomkijmpruvvwxyzzzzyxxxy{}}ywxxxvtrsuuspmjjlnpqpppqsuuuuuuuvvutrpooomkjjlljhhikkklmnonnorssqnmmnoonmllnopqqommorttssssvxyyxy{|||}~}{xwuuuwxxwtplkmopqppqruvwwvusstvyywtrrstsrpnmmnnonnnoopppprtvwvtrpnnoooopqqrqpnnprttsrqrtuvwwxy{|}~~~~~|yvvvvvvvtsrqqqpponnoqsuutssstuwwvsqqrtuusommoqrqoooqrrsrrstvxywusqppqsttttssssssttttssstuvxxxxz{}~~|zxvuuuttttuvvusqqqrrrrstuvwwwvuttuvwwvvuuuuttsqqqrqqqsttsstuuuuuttssrstuvvvvvvuuuuuuuuuvvvvwxxz}~}{zyxwvutuvwxwvvutsrqqqrtvwxxwwwwwxyyxxwwxxyxvsssstsssstuuutsrrstvvvvtttuvwwwvvvvvvvvwxyyxwwwxz{}~~~|{{{zywwwwxxxxwwxxwussttuvwwxxxxxyyyxxyyz{{yxxwwxwvvvvvvvvuutttvwwwvvvvwwwwwwwwwwwvvvwxyyyyyyz{|}}~~~}||||||{{{zzz{{zzzyyxxwwwxxyyyzzz{{{{|||||{zzz{{{zyyyzyyxxwwwxxyxxxxyzzzzzzyyzzzzzz{{zzz{|}||||}}~~~~~~~~~~~~~~}}}}}}}}}||{{{{{{{|||}}}}}}}}}}}}}}}||||||||{{{{{{{{{{{{{{|}}}}}|||}}}}}}}}}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~LISTFINFOICRD 1997-02-06IENG James GrunkeISFTSound Forge 4.0QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/rune2.wav000066400000000000000000000313201475442401000262030ustar00rootroot00000000000000RIFF2WAVEfmt ++data2~~~~~~~~~~~~~}}~}}||}|~}||~|~~~~~}|~~}|~|}}}{{~~|{|~}zy~}{~{|~|{|~}|~}~}|}~~~~}}}}}|}}|{yy{||{~z{{{}|zxz~}{|}|}~{x~|xvzxw|}x|}}|~~zy{~|zyz|zx|}||{{|}~{spu~{}|}wrps}ts}~|zy~~yu}}|~}z{~|z~{suyxw|~wy|x~y{{wrrx}tw|~||~~}~{z~~xps~~qkr|~{ytqxzuxzrry|snrvrnw~~~zv|zx~zz{zzz{~|vvz|||}zzzv{y}rdv}||}sjt~{mis}{{~|~|qpvx{~xqu~|pcev|x{~}wwy|xorrlnwt|qmpplqyv|{rkoyr~~~~rv|x~w}svxrtu{uz}pvy|}ntyptf\l}wqsyyv~ro{{u}~z}~}}x|rwpgt}z{wessww~oehlawuuxry~mbiu|mgsfe||qnqnlvzrtqsvklpruzwsz{zzwst|lU^yvx}{zpn{texx^`slpxulq|u{|slzynbbfv}t}rvwsoiz_MZyznq~y}v_Yqyy}oeq}{kkrmx}rho}}eSQb{pl}vfpx_emltz}~q^hwzkkvpwrkw}PGe~}}ukt}ycYktont~yxzp]ORig]cdj~wqttt|}mxqjqxym_]jyZVveLSo|pYW`s~acy}ri`dz~}trsqmly}ngr}i}pZK^{koxg`fwjRh|\h}~zz}vglvhr|~~mowycdrqvn~~h`^euzVSnp[[dlxifu}{mxtvqnrbfmingZkzonxwi\fkL]~x~~z{tqsxqnnvwchvsku|vvy{{imuud^qqfq]]n~Zbvtvy~ssxvd_rugy^`jx~}rmrzr~otqhu|qix~z{bmqX[qxduzqz|}cKEnthtss}iC`g`cpixuhm{xr|lYx|^OkqnfKiybb|XV`[Uf}\XhuqfyzMJk}UBMexwdf^xmjtqkrxdVm_[z}n|́=NåpGEZ^Wh{}xzai}tr~XRS[yZVs~zzs{v^shûQOt~je{svy`SNXwukg`gc_{YQhtsofowfhysZ]k{_bj]pm?Ivt~}{d:'(%@xu}ompso~hbzTq{QP]YnrUb{vghox|zF/:InǼyfNXv|maWWtwjjhfQXqVV^|n»kQ^hQ_~tSpbp~}`@PvLKhxvhSPshV]V?Wkv{`_yocxuLRQ'KخpmY]ibWVj|r^rhPb]KC5IzpOBK^qjcLL]x|z|zRAjX]s߶ra`fqjL6+EiO[qwd||^chRhy~K/?ll`bH6owibSJlg^}}s]q{ou}X->}˸ªut|[UgsuJ>Qdw}J7noaokup_ioqruvfzcdnSRåm_anx~ihyd]~wrmersfƴtpcVgzxj^}HFbmpävSckWo}QGt}8)]{WWn}w{k|uy~xfvwloo{zzx_Mp}|qcgvx}l28nmPRv]NLU^g{̭iZpT]utug_t¨U9ZɱocklN/CzcWpW:4Vi{_N_qwqlqyxn`TOR]lppw\Wbqts||urjz{roM`||ldltk[Ty[ZuyUI]mhbYKOxZF^v}iYYUYmskOetgѳv{_txV`z~rtuu~o{nRh]Wlo_b|X<9Ui`^c^fqfZ_[)+`p^e}xpkiqvo{[JoppywUTzPX~zzwsvjJQz|S?SkqbVkspoqsy{/#UD:˹Дnbs}to]uwvGd|va@IgzPfcOMIIXo{hi_Ucy{`TukcmjYbxqSWlV`}pNMkTZ{uav]Ou~g]eq}}kNQpoFPzwwVQvsdJ:Fṋ|WDSvzqgfEa~|Wcc[lp{ȏzcF@^bNmcrwYTizvg\jU9OeJ4Stw~%AvivytGWq`XRuv[Zt}oj]`pgymybevwysdfoqppsshMLz0M÷bVjvgnlWXzhXr~|ZGbuorvuppw|omv}~_Oaqd^cVMY]`y\>\v_NJN_msnhy{wdKRshM[~Ƿ}cvounp~tbbt}urw|~znbbgsydxzplvzhbwU^yΏZIMVhz}_ggdvy_b{ӹ~~LCgnhyy]^jumink`iiv|nd[by\Q}~|p\bxvt~kipaTW}uYgxZRav}s{r^KDngepr_LeθkF;eĨxpk~~WAiʣrNNw{z|}}|}}oz{hp}oX\ot~}RJ\i\L]\HPdu}tgdbc`ZblZj}~zywfiwyr`]p~jLYw|ggeTSS^y`Xxo^ZxZOVS]~QRu{vjRlrn[@<_vjrlRThHUbdu|uy}tx[Oe}~}y|}z|bbzqWgzqgx}t{uvukfnoaXmlun~^XyXOiru~hWqrxwd{yvj`ˊ@7SmxhWnjU^ZA8@=Mq\KtѸia~uaxȤqUR[_^\`[GEhtH=[qix~\ie]trk_EOa`geOPZlztztYYzq[a|REzhv~z`.1Rl}zp[gO-EKHgwtDIj~~YGU`^_cZGJitmss[Ocڮz\aш[dquvYazkSXoxfWmwdqjY]ݩhNb{zs͵k[^fvd{{]>Amp~purwcoR3Dlw_h}|kcgl|~ObŸcb|om}}Z)'R~txgx^I]͑gcf|{Y_xfy}g^a^b|p^i_NgY0Fy|q}yjF,7Toff|kJQN6Aji`i`b]}j`t{y~{lkslkqH.KuiXF^{}~dgypYG[y}iapdOH_|vab|liqEItSWɮhM[rZc~aLhQDzP.>kvmjXVNEUy}~p|~|l^syc]qKMr~x_Vekj~dstzs_\}vtxmcZmȱg@TjY}mRZu}nfgyfUgpdyude}x̦wTGZvy{xUQ\PJbueZxYNsvYFObiq_fxogejbZt]OWccGEe|uWlǘwroaSKWw~{}~x|dcrx{~{i\P\|}vrfVTYatvrraN]v|nf{vG/Nlq{tb_ryhey\BBMZdn|iMEU`Wy~o]vrqzwwro}xig^\qk0$=gL0LdecQq_eluu~|`GHfcXrthn~pUB:Fce`qw_Zwc7._ťyo}up]eui^[\cg_TR`vwdnqTTqhwu{z`Xhlp]CCSZ_}Ⱥl3L{̥neys}yW19Uwo~|q>6Ssźx_IZog{xhnw{rzSIev[KVyyZUVMWzZCT|mbcchvrK2Rв}_qxcwogpswg]rbDUpsnpuq}yx{wqyoJ7Enu~vN;3Oz}yyX:/@dywfDF\oxydPnÂb`XXyzle[D5T}N@Yxzomb?9࿉ZR[ivSCKYbhvpSELmzZipqqqukCJwa[uprǻkrs^[nxl_YfqwŶ}iab]OPt}f`hdG3X{o~p[Vm\_qt~kWhweWswnFH_mx[+3vƬpggomj`<9Nfq`Y|mxu}sĜfPt{mjipš}}~|w|hwsfacjzu`U\pu_WxŸgduĦtlosjex~kp~}v~zaSZqvtrRNaprzkSkˬwisv}scXVG9B^uPWhy|rcVgu__yj_TXenyljq||zokykZtx`\hxvcU\rwsm[Oczkssdmwyj_chdnujbo}~yo~z{xw{}zqw|mWe{}{oopuwepn^kwtzfcu}nxsx}rzx~qtepz~laar|{ifuxovw`Zc~~ow}tx|{|~sspmweIOkz}{|}yx~e_m||h^\cu}uzXUkZeyzz|[Stsqutwddxovw^g}z]GQp|fT_v|nadxy}wsvn^Yfsjeo^ovpyr~pin}w`TZs~laj{xjhmT\~{p{vrg]^lynamtrx}{x~mc^]s{}st{iWvwyydZqfnwvziVZi{{z|{gUZwt|xoswo}h\uxabsrxwzzwmY`{|}}z|~bg~mgvkgp}x}~wokonns}yx{zfTcrz|e]bhvvvrplgy}jp|mkmy}{wuiPPj{{vXZnrjt~xhuzjhqvkipk|t{wu|xuxvxon|xszzuyobcadryqkOYwwri_`j}wqy{ln|}pyqeblyxv\_vzrfn{yxsrstkjq{xr~~vml|}qlz}rq{wrsnq~tv~{qponr}}x|ffu~z}stqkq~yq{xw~zvmir~tr|zz|w{v}tropu{zts{uoy}{~~~|{}znjp|sqmvwrpr|}rgm}v{|~suy|wz~|{{{yssyztt}zsu~zkdmukfr~z}}{|zv~~{v}wvz~oix{xnq|yuzrrwr|~wpv~twyx{{|~qv}yt}zoq}|xzy{|vy~}ru}~tx}ynej}umklvvuuqz~xpywqy{vut}wsy{w~|z~vw~vqx|~zv{|xvw}}urwyywt|~vvy}|wv|{{xutruwu|vrtx}zx|www}~{~yru~wrxzw}|u}~z}~||vt~}z}wz}{{||uyzupox{vpqx~zy|~~zwwz{uw{~}yvz}vy}yolu|}yqrwz{}}vty~|~~}z}~||}xv{y|}{x{}ywzxx~}tqy}~}x{~~~~~~|xvy~~~xttzxx}|wtw~yy~|zz}~|~}usw~}z}~|~~|~~}{}~yvx~|y}~|~}{{||~}|}~{}~~|~~~|||{{~~~~}zz~||{yz||}{{{|~}|~}}~~||}~}~~|}~~~~|}~|{~QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/rune22.wav000066400000000000000000002034001475442401000262650ustar00rootroot00000000000000RIFFWAVEfmt "VDfactddata g Q5haipO.!t[B])BqRjiPA2LfOl$<}tT5j)~c*EN.|h0{Ik{E-QuZ?$ g |3jV_ f K |n Y^TJ IIPh`H/d5_Se`xBLaAS1* KO9[s  o A #  [   n1K2ffkpT 'tIgv P@KHFҤJz] 467*bG L  1 |y}0BfMJXXgYlPrG7'-do }!f"i"l"s QJnO52,n®F =S-}!uѣo AudbK > ci:'x (  T: &V8d#yhq"{%s+l14\8411u+% K_ 8MZvENQTlKfZ|0h{ i3 zm`2FZU ;pck,^[YS Mv^$+m 1P4 BPMe}|{mQo |qR3޾jl]kyפ>OnX7.+)"4L*(@MF[KYPWOFO5u>/BdU;A-Nݾ׿=CXunjNg6ZM@4-d&!v*~% f&D~ R27oOR|Vw&sΤҭնK9j$*V+,@=i|d_(E*6SʒDCc@12%*w/5:;CKdYg\R?," (4;FA>:5N0(! qߋسغԙGDzo оη˰+fN>ISs> ˔ǎÈB.]|Wl9  P0i&2?HGtO}OO+V\!asef;h`eb[\1VVJ{>2, g"){K*9;5lաτgɔTƲŎjÐγs?0 ?] p$/g37(88+1)@ PI[32[2$s %o,#Z?pKWb{mnnQ4DXں -CATMAF<(3p%a ($>6UIl$v ~|f$Q 1Lyı0K zԺ̬qSqR2Nkc[ Na@"Ԕʕ[x_E*t  lʢ)#ҽ5;L>@#k%SG ƛ~n^ "m',j* (*F"͵+n* h¾7(9%>6CCfDL7U;[?aU`l_[WSYNOPkTWlQK9(\$T߼hj k l~"y)I|]>̕CӚc+Н zLa~wdP#j`Oޏ֭J .+(3zFH%W8JP\m+gw`J4N `#-7BNNOaJE+A<$@CR~`hkRvu_ungFYJ:*"Kr%4T%&&2j|&peӓ̬J[ъrR23\G -ɱ4X|֧ľĩɍqT 5^Dn}lh"S@F.JN2fvBĆf M$- 9 D4IIN)M L{KJE@<\85p3l.i) &""_!*2)FYkn~6}{_ D" e"=,HRW>[M@^&) Nޝֻdϳx4}̞ɾ2Ŧұ), !""Ex9ؿon!-998 3-$x6)6HZbj9osyZ~DlYB+m \u Zj3u.eѨQlJ( k aÿ#d.!kݮ^M(,Tŏʿ M/аЦͨ{$4ANKH*A Qa1͢BKgrbmQ|+Ȭ Ek+N)% \ 9(F[pru=fgW^3U"h&n1t<(t>i:G.}&Fс> 2H7'kCՏ۳2 ᩚR2y0Oŷü5!A`m{rj[LAS7/R(  :#*523w5-$ Ҝٚ%8h+.@1"C 1WεῺz]CnSc0G*̈iWD8^dj\bN$巾ȴ&5/)iL( 198Od\efzWHB<9603*g -iޥn7*CNYh>w-j]?." *j+8E<3##f)`SΦ=Ʊ5o:578سݣ?*`9Kf^ZV; C[эXƉy,ۈȚ9)>S %&(,~//g0.0/7Z?ITcsy-w\nK)QÐ 2X-^cQ>+Z*D^hrpnf_F.68۞e׵UߥsA ҭӌj͞ʽ}<÷2FFƺ"ZőϽ}Ie6G6$ >M>]9G41 $9'#:M>?0![֐ղuϬ@Eޭ-).847;;r:*97#;d>@CEHJ>L+JH>JdLPWUZ`irxy|2ykk^Mc=<:? ED^D=6T( #MbMK߬ۥ׷j#j-bӲ?b?,m߇Q0uN̨/#7K_otiM1.ʗ?~ʹ{(g  0(5-:20F&Zmyr"L>&"ʯr1D 22AO)SV2 hŒԐٙϤXJ*=CXnEwT"pa?Ip1z* ޤ^SHػ-w֟F\ȹ,99Pgß.nxa z )Ii! U $).3p8T=DJS[\\][BZH5IG E<3,V9yFa|B~"uFjXG=A4/v+)H(! QdU>6Dڒ6q}։Fϓ?YvדkzԉQıHM>.)# bD%䴣[0ȯ.ۗS,.11,'2L CyN#0c3.$E  +*905c8:o;<~;:<`>iBsFHJIHJ!M~PSUX\Qfos1v&z~ fL+ D}k,DD\0SDJ}A8+ %6އ'w)ʎҁ:+iQ8 {IJ2űĎk5ebI/}ZЭê Q9Z(+.$ {B U2HQZ_miSY52(,0>ʠ¥ԟF U(/6666m6+9;>AIQV[ZYY7ZVQvHHHxX!h)k2nXl~j\NF0˷{؟g "Wśɾ 2YQJ1ֈz/9?FD#B-L "$eјZgS`" / c2Hc^bmgAgg/[HOB55I554)-i%lҁ5ԍ@}„Fʊ!÷E<O,$_L85{0=JKMO R\gnu qlZHIZ5m!w ٢.չڦܒ}jL.ﲰj"hޭƂVvqT6"Bfl2vxjT47x]B)б&{ai/Ib".zT-.TMbmp6xeJ$dԤ1ԾCqFi a8V1ՏSi d5ܵ5@KЇEQ](lQz(}u'kPz6",HdKmutFscR23sijq h+FQ& J*?[w{hkV>&`ٲڸ۰ۃ7׫ih PߺDj_"qxǾVHśg3\b?}ʺEШc$3CDT@PJYepU:2# Lؚ}$aNY^QnlkP4!ZA($A#2VzU,21֠$ݨ;dԌgB+Žgdz°l}L;*"<-קդ"ޟ5>`PpWmZ6n,G 2VzL #5:B!K* ߬A2$.>QELMNS WUQTUZY`lyyyj$\/M;>Y7x0L-!*Y$ybfjӞk}">?,V#8FHQY\WCV*}cHĨƒܩ0-P*Q ɯ ga+PuG",V'!:kYGw¹^ ܱ-I- ,4[= 1${.ऐ@eԉ DcmifnC ɯa`S$j, #(,R112,45B7889_;=?@{ArBGLQV1]c`]N?8111{CUafwBqj_TfB0,Р P"BGM5%֥ܥ ,BgPk"oZqF+ egCsգtϮΤɚ=ໃ%Hk; Gߋͳ!ƎVeìs9‘7>Ƨ~eKr ڥK:.yDmc!~%<=?36X- B>8 -76>>m>:66\6>CGIJFBl8.$3+##+6zB%IORUoZ_ejqs{}!~D| jW:>$ ݀~,PB &CKTLE) -Qt N&-@S\eZN#ys4!8lⷊ2ݬ&Ɂϐڣ\H쯜LǮܴ@ ! Y >,8DZQ^l {yxsrmTu<(z'6NeN 8C f5)U\dOu:- ߜ~` )o8xľӌ){+܈`ȽWq´9~)Mu͜ +|6ABC* By8>7輯v|̂& .#(q,/2R45;N@ CExG+I+S+]5h?sycpG3i Ҕf1TaneJ\5>@AU/P[gkoX6@K`R ۭ `=Qe_YL5  g}Z"Qۤ>Ց󻗴:Ŗ֒MJIu~v,U1 ;!GT?)?Uɾ'' 8HLP#Eѧcܠ2i $7)-,]*6'$H%&*'/4:B_IcNgS`PYMED>r,k6 )V3<9M5"xD[# m*޽ˡ)  &w5x&z&K¤|R{Aݵc$I004Lc @ѿΐݲՃ.f40,|t!&؞vZެ*wٲ7Ѧ$N3ABC7, -'Ib|D~Wuj>p~/CSdO:+_r73/"sjb!"#+4@M(V^Tisyt}zuhV?)5 BIPkIZ.ڂHϹ̃1޿L34,.91<@& ֋s[&vA `=jـnv~4T\dozhnU&z&o ,9'G2y};Q߭ %gňu6,C!7bٍ* F7Y9l;a/V# d  7/=rCIQY$bRjfcR_[g=7XhK-U=`M!)יrW;I/a@y5x+wk``6J 4Bw^EƽG6$lr/#} :њDMVxåðؽ$hƑ'5Ct=7 ۇ K.>MTiP7bi;|C3#ާ~>֑XHٴݶKXe"+.1/-.q)$"U |%*299h:5:1.+-7/2$6(4-245:;~@B+ENXX|_f0jmmmiye_?ZUQlH9*Izgܴۗڲ-ό8-ᾕ3Ъp:juL&;5?Tr2AOAe4_5Y6G85:-!_ nӷ(}7%C`fei9[ KMO%Xg0y7>@B)?;?=>GP]kuGzt`La7!"AaJ|P$ 'BGLPT@+CZݯھ<׫AҮғwXҋҵΤi/ob=۠2AپKп UЮ1γS *HABuDX:;0aV޽$ȋR6m= Bw1} */4'9=@SC"A>>C=@BEHNhSW=\\[b(jsf}~:{uvi[G>2!qXVe;,㏩FK 8&PgedUGLOù(ٌ } %jFns–Ĺ?*QЎhB:2ɁȊĒǒϖי؜Cû'iܫ[3457:62#'*,,b-*('B'{+/1p3.}*'#I#"#|$|)|.g0S257;J>=(=?AFHNT)[2\<]XTH"=e!سD #-7%9:-b!a aחχvM֩ 2xؒ{ʪȼc ) Ζѹ/5\;""$_C'Ưd@}_|@U=ɏJ'YMO!}#+3;#7N2h.*8ELSY^e0mO2UȨARL,:@FFFAO=<%3! 0:MEL9- ,?PbbcUsG!x+X JP0,AVd^f6dWbhRzB%|&"n!fӀƚW̨u&&3?W><* |[aQ҄ώ%E󞠭31)|P#^VMw$*0r/G.*%M&&/9ApJKmMcJZG^@b90' (3(o/6j9)<48?4iՁ.B MY/j?{OYc(Pg5}ViP6tZNޚ&"I% (&%/6:FQNtK!3 r5%?+C2Gr7'&EcWvz$7*.26:<==PG7U3d/+'_W֏J׃$aӔ?bڼCǡ -SxQ)z <)9mJ\nbdY>V" 9oCpg)B8<@";ث*:;IWޏ (Z9DzPQ S=~( b<M '7G-k+‚a !8OVE\'L <Qݝ?גQʣϯӻ Ԥ9T;tGS^hVgf`Z_ebp`\WNE;1$:,mݍʭ7Pख़Rlކ+Uam\ELxC:,:b /}v<V""Bb2 pȵȠȰǿƱ̘έ0Q!Yׯ #X.9Y51/q-Ev{^ } U-%#5DNYNC& +r'>F$O{MKD >2"&`%$-0;>AN@?F/y E'f:=@;7.آ[ -E@vSIZaXGP9!O2&M}ά"ŗáŪ+ϫHVãiVC hijR߶`;k?`t(2<֏ӗF-~FP[[TL;*=8Z%|~\c90  #/;4-C?;n B,8D+EE<3v$` 42BIQ`bcYO+Df_R&2?./B 0ێPLX(]Iy \_1g4峙MKI 0 yٲ8׭f 5yOTY07G,a$A^b]\B)w`IŁdcc) h.-+B.wZ%`ϐh[I75Q[fl\rmh;c#:5SڕTfx ds= l˷J$B4.n)C u$2C:A?=95 Maܯhؔ4 "Kt 7*ެփ&S =u}Ɠ_7< IULM E?$94.-Q,,+&!-9s9_9 ."NZ$SvyḌyʖVuN~q4{¶5uÍ o#o!( #fN,^aseuXxK:(,#9"&&& %#&*,.1w47;39+1%)M r!-9VRsy{wkY`F+ /5θf̱1sʵW"3D@A=40* 2sų!~ ' |rEw -BcfjHqT)8 *˚ %6ꍃ)7ΞQқ*d -;SHHG) ؖѬʽtԐPĚh5Ka(8HPX7NCG6(2*Urdo{ ]&@,,'"g%c !#+48}=5, [~79:R&=dfˤLHKNιM#;|V##)y%!x7  {*$T u*ܿ W >o1k~hRg)Vƴ2` #ͅG5!U"Mm % ,.*P(#6(4@MKLM0QmT1PK?52!B` c.]"BuE'2C:A>HNHBl3#> H S \gs- # N*[Jܪ(V;ĩ0v5zܿu+H 4 <ݥ}^ZV[_Ү"H.%zWKy FPV"#$N.8FT*Y>^_a3^a[5L =N5-?*&h!4GMSUcsysg] TQlO@2iF~Br!!Y/܉2 \ <x[(̢p " -!87C<4'&DNW 1!'7+]/R0H18&@_=:2)Pn!} J ' -r5h³uN3ͷU1 4\ i6"7COmg\Q+m8, Xr]G'w25X{skd]-8{D40%BT  (X7FFUcgokQO8 u"0F\[l{PbH,V  9]#"W"XX|C ]YU9b$)+-'!  !#P{g a% +-79W<6;1&u i$L./8t2,'"0cGuՎЧˈʕ¢O5m[I {G ?[w]\Zص}Ek^QDȝK:(j¬_}/$ɯ&C+<7E1$[ !3F@Q{\`d>`[QcGA;I:8*'Xݯ\ۢ4±.`!!%(((:;p̙¸Y͹I ^E6LkNP;NKlJIIJFO tbQ`YQ[d~wp5@њ(ڀݞӻ&,1ݣlNYcE&!'3/*jL/m SwT"W2[BExING$E=^6-(%)T.+K)k:c  5tW:Ŵ.ڰ"1C9/ p+6:>@BcB B9ESHTJak>vy5}~uk\M7O!4">OY-a iT?( ,ώZ%b؟fJ<.|)ƇoWL˛̔ԍMU !6$Hf`ھ֫֗i;;;iL Ira ;!c-9>BIAQIB+bI0Q#@.:F@9! RŻr[~ zï7пHмYt{̂~y$q; &,\2I>OTwF'8+nAխSʖleć[K< (1-0*F\ u+Ji '@8^{}X{v[@8vg͢z ; 8(s/ҭzGf x96~4.Jٲ[BSeEK0ΦӣGǹ#w)%9D#P[emoulbTF4W!x = T F4" < Ȉt#Rq$)!%o/?L8Z`e[Q; &h P./,1.51975+@!C/*8DUQN8L?}3 ˱ק>޻r ~qF‰݂ug~jU=$i nsBH*6k+L sT ] l7 ruxǿ+PW]Fߓ U  #xSG;))B)!70`?qGN }  7 K;,r# -16), Y "u]C). -- v$(/ Ppۈ~Na ^ v!`QAeK9cRAAtT3X ~S(%҆3߭h; \"+%= HͲ&ȚИӛݝrC F?Eq) ZEj3!2&F+&:"/%  -d:GHI4D>a%1 ~Xgv 6EU[b+"Vd1D Wqw|-|zJe6t|FN " t 6ܖ3!ɖӵ:~Ϭ7zIJҊ+He#3) .Q%FvY/GLEC ?:2*qb.>FCN*YdSBxbK׬ a 'AwNZC1+XmI{fQ|ƦLƯliqqrs$e2z+vӨːϿ 3\"VȰ y_,ρۻuj߼sMcإm<3*"_ www5w'037T>CIVcqvrmaPV)J>+pV)<9 JZOYC6*֡ahM +5?y5* &\J8gڤDը @v2@hOQRAI? )\WS+x0433c( 6j @c D!%"Y }%|um 4\?/AfD$PZE0 , 庼jNI.I ˝]e&X _δɤӔݥAl; a841 AQy#9-+27420x-,4:CL;OQG\) 3-/**dv_G<ntG=f P׏f* !(9@DXOE< #y yzQ ,&:V {Q(Z!W# A uݳx8J F*?'#\, Ho1| wr&P)96Z4+"k)V3Sܷʯѓ~n۬CwDR`" L&,/ lpt.&A m>#M8\^`RD!1J m2MtXQcM*8AYZ[ж:ccc?E/L:z),W;g s9 "iр:)!  湿_!ӪܦݡY,bJ_7Ak 9?;;nJ, 2 |SZ"~ŔO  JHEy\ 3Kc ߺd zw_?/?usq,Q"9 )3 >j70&Sv $7J [kkkZI}9)~5"#N%#"c 7" $h#"&**|*,.-,. BǹɆS6l6 "Fę?sTұPF<ŦU@Uj#3]DNWO$H08,0rH`[ptUiQ|:'q 8HW8;>BFǩ ٝC1׾ю$Ҿy36E(RNs (77?sHKO6B4!A "0?NW`N<$, 80|D Vi%]-/e2u{`DǛ?nDOҮ {@<{γLtoT124.2g/g0g1{ 4^// cYگۣܗ;8e ݕAװМf֧QܹPxY.C uht ?%-03321't3g #%#%"J  ;fYKHEYoK8VsԷ;¡8޳i7BMa J tM+-<MT \`eHWH"9)/59 =CI_EAV3%"r_LiÿūMM6 `ӧ #ʻz*.2Lݐۖڜٻq '6B OpV]WQF;%.x 5V2גҒͻ{]N  qG3  }{z ;L^'&26H;7?4(HL  I!$/$;6v2p!kqC:07{޾F͎OXa/3ٔI}yX5z2_w  M5r1M.= >ΩF/ND;9F84w1(  . E ~4@ h3 E' e7 NxۓșȞۛkaL5w&*(>mKWQL]<, C #7 s_aL'}j D /};%":i'&/3k62]/.,e*'%f#"!$wr6l@1pǮmT;Ϊ@g{(`xڪMٳZd~Ga aLI!PhV!Z][ZQIA9j2*q$  \+cH-*tz7_e)`h̵/ìh>MH D -t mASPLV;٧PrJ y_hR<!?n elty%pӨCwDH.p%7= DCCZ>9.4$FX " ,8>yE=6)@T.&z6EuUY]ZcWK?-0 J f ' %! e*\5  dB qd(^~ Q{[:)"y:UKiزҵ^ )v1Lz0~uܻnұz?&HhfdU' T v1=I W [` !.=MIF5%n fvb` J$! Eqe{ Z"Mxof#.{O"*J ׄNߢDJ",.z0,)$ .=Zw8*!['*-&g Ox7RϋĔ'pΥ Aukaح%S¤NjrV9]&6EIT,UVW@*nV[y\"ԞT8`#,51$./y1' "$ ;&0:wAGKOMqKJIgJKFFA<7$* c6 #+'7ث ϔ>)a.ƟyȇϕJׇUI =#f*4[CQSCTtJ@$: K(CcǑп)ے K 9CLj>X D[S S#!  w I %$"boj%U>'3$.#LNJJ$+X9[*2:h/#"FC U+% (4ӻB˼ȿ֧WG&O2=N9^XSA0*%BLW 7 h b.>ACZ@=&/ 7 Zw"Rq.i`S6,q/Z2/- kd fḰII΄jv \ުΗm@ N$N{,)j D q't2w=PB*GHAf;0<&"Rr  #6Ogh$:QhlpbVTAA,.qom'&,20=/Wr4* Rσq_K7c zЫ`yAٰܨܟn (  K!r)S,~eE%2?Zu-o l1  Rg{n&,-~31g0 -Yԅ5U D(øۧ9TXc17=b.+erFE!D2:B?N;I'D3"C2I VsbK[$TPL}D59-F{>0%?HNTZlU P. j/ыY8 #/;[0$ N5 Ф;/~ͼ{8 0R%8/ݓL h37;q)'&Fwؚ̼(7۪Nٸdx{b>%B5DJQ?-b F̆!+.7|@CFEEl NV%#/7,@AjCBkB`?V!;7/k&(*) (_z""!<z|־՞~Y3c+nғ ͲVm{صz̐ǥ.DܐE"Ku ,8ERTyVLB8$.54(a3jnrLީԃ\=M}fߨQҮ:ґ{o"/;@DnDMDPFTHHIKL"QU:NF:`-]#[@m#z.^nTȕi3?‚js|kY/>e%Lҡ)ϰ[t "U%%&({*.26]:[:Z:4s/$|VB !^-Si \ O;(o - DIZkQR_l d7:9#^(!---)}&T+f>!$ ('''R(z'&!1v9pow$8h \qcT?*&#(!v qǥ-iܸͥr i:Nb J',1*Q#AHOKG f Z+= uU &T" }E q4v&,3 u jgczЭ,yùx,xթ^LOܴJã(eТdݾ[B( $+-K.)#%t>|$*0Y,'"!| p d y!(...I)#0h& (B.n432 0q-)%V%$'l**:+5-1/13K1.+(%#;eo zW5/DY  KtW$~_[Ԑ ڄMIMPMK>v2'o1f$,u004/5.6V,"B/c }۫x/5uy }~ '.4:T:93 ,0K\YU+ݟӲZ*Y½cՙ_bJs_pJ·c!V܊Β!ư c6oE( "+%!0~(4P6865X/)%!'.N5Y6c.)*%`), 2C7:=P<:\62I46==CEGIDA="9/]&^~4 ])4Uuݿ Ԡ%xBkyBפ^ӆϪ`#ȱ>߬ȾĦ[ƇDzȸĽb @v$H8KNQoG =4 ,)%>,2=9?m<8,5 Tt^՞n=džru@ժ{K<-lJ  B q W | !>\ h t  i =X ~x#1'%m$2!e$H'&O&E.;69H=:8 52*[#. HC>VnV4f~ݖecaVK՛ӽюʥ| K c):2S6l:;;p,E=G 5 .'x&;^>P+QB2 sW!<&"1 *g>I w ?!1G{\`<Ζ8\̱-Sy=)!xa<\ɶڕ] c J1 NknqdV $2LdĬh` Z IuK! ? iqP#q+382>m>>=;739448<:[9+98-6^3*"""(c. 6=IELFw@k4_(#uU49քԂ5 uqiaK5U&զԞKAlvjTʶ )ށ$Z܏X!%)Z "-[ cWl Xc!&+.13_4G/0*!"HEB,5 m !N)123)W8iܰԧXQ`;hٔd1dM4=6`J Cyn #F!,FGHO} tG  ynb sm`/"TE5z@2$:_ԋCXhm e`. (J Ozx L|"%$#V" &,=39873i/L)0#  #$>&o!z! ^ܐבۑ,IUabb'_VdD U   $gvхȑǝ3jנ݁a<w ## d G W7w~AW?<߶B<XTD!"$$$%&w',0}2b45V7E645s2/C-*vR0{6%s#  3 ,ٗN$W@ƭSy&յǽ`Ov%r (R52.!#q DV%# 6Tۊ"͹/Ԥ7zL$\q1, (b!n O' <#y%$# K!'5ChKRTVN6E4$pbgl")0?7=DGLeD0u#=  #efhNSXE2]Xlۿ Vc8-Xs 9")AnںˀզQPNްpK%'(AYԸZ͞ɰ۩AN5r(<)#*}* q \ h  k[{N1+%>   Sg{Y (09BENH@#91-@!{.!&.{665))Lo^l`تչՓ^\ V9ׄ>7li27<J^s_,6AWbg u  {rNE6'_I=0+ƨ&a X<%m+18@!D1HFEB>:678;=AgD G@Cu?5`,"%rB!"&!,?a^ֆԮ+S10PmB݂te 2o-UkSNԚӝۗ/cmwU(g:!"p %k}niv5P  8}& swzq7ԫYf@HN)O",29Z=@=:0&!b o'3.5B=Q9a5+T" z1)*<5܀bD~(0qO"X >oXAaP>x!!f ,5? bEݍ)/ޗ^¼$B(W 9Xy 2Ng`w!y%d)5))%" #'#)*&#U}X8  &4>I_goS6RnFxbLZg#e?a"/ <#5DSVY5l4` QW_yyhW h Ai W*))F$s Mx: Z[#]/b4g9r4~/' <aO94{f- p K e7J ];#`N !y<[S K"B$%H%$$$f+%2;yE~GICo>0"#V \v(I s~>hB [6$ےqyΖJ  (d( R u-hP~p1vaLhՄFj=\͋ңغmm=Rg/2l!""Cw$(2Otp qV MQ #[3cSהzGo^ ugų2 4]E! Sޗ{; G :w! wJK 3^dk@ fAT a ;~wX9UgM3{6\ z 6'^$sx.+- Fa<i?  e#)p  t\M/{&$oT 9 HXSN#${&&'!<- :AcHگj$׎A1!iڧ> . U!#&.6>FJ4OM b \Z :WtdQ)g h24zdM d pEQ#w" &/<9;> =`;4,c t K 7c%@`B#-752Ӵ6Ա,Ӓϙ:{48<+;KpҔ Eid F]7= DLm;%O+3*urY&a k/dQ" /jr9*R  4tgw  1F4i C  {}!$o$#!1 r ؃td̴2 OsT<S[:" T!A ^ f n & Di(i.XB+wEzjYbj!K}+7D  { H#J 7:>Fzb+@ qQ1n7 }l p  P"1,543^-+' 0 4 w V XZLwG4 QM1׍0xS.Ui~ߞܰV؏!w+yRxQ) )b j s K$Z!%q" reX ! gik E8IKm`:=+Lm{ ^3E"%(Q.3M:@%>;l4--'  #Lo4 \߬yEi#MGmsR(Y{hT1$&Rm+Z0%  |  [z4RB2 HRYKVS~ | | |#m p"A`#R&E)]%u!  3 ,M+v>O; V3q R~ p u { #  mdP< Nf)ZA;z~sSE$/\ݯ}["H=1](W<-3~YM1$2  ,E ".%%&')'&$v!!!""l"! "$%%&%$%&$C#w Tl7 Dtg fy}] =Nbv(ll(i9oZ]`1; !h: Io+ߙ7ښ_$fRi qRG =$ &'(L(&#<$$'*$.14765/*%!,_w YG Byma~Y4 ]wgCwd&kITK $e'D*,-+)#(P&#!y~ : a/m7Y{!XQzd &"[ An A] !B"q9[ PIbUHTr tͼ5f̐ϺHHHF 23z SqK_r U8 3 W.V~qf\f  <d ]  g k p )d XMaO=GX r 1 [Hlu] FHF=>R\fj)d)6I}N _ V ~ X b o|$'P+,.~+(X"`C& 2`kosytoڜVsȸ+ѝ6 }˚ZeoZDE݅ߩ7W%R]s   nstv F f   +?! Q 0Xn W{gT e d+pT!ffkQ$3 w_!j`#*3<>@=W;`5i/o&unrY@m L , Z ' `5A NvD (}gPэt[_D)CvS}(R".7@1& p2 rCwMJjߚ`rOn. @s5 ) H Vd_XR C  Y8^" (] f%'W4x?y  dy  w ` id+BJe=m p [K <|3V> l h;!q%)*,' #G( !Pe { R)S|:K؊4e_أ~Yuِۆ|lM [ f7 4eM ] 5@1RA0 kWC-)e #5fO)C =g$$6,I443k-'%m$!c] "s#T$%>'&6&$#""S 05p91)}82~LBHӏ1ؔg|4M|] [#S FUd&i Qm%-Lu' \> s u" %'$!$ m >+E`WN4 zO0bLmRCԝGc„Lj |, ď6ʖѨٺr ""#)h }T3 # H =39i'y?k"&&'h'&$r&((L)&%$z iYwG۶%ImB);myik-O 1&q,:'"b HL?Ӵ(r6{)+zttu_&-14)55+5"' 'Ko)cftO+{ !y%j#\!:-  o u  4>1$Un^N?0ӣ>jѼOZOD;a%.l)cYO +O o Ei* A 1 $(_)0*=)K(l%""t"#(%!gI+Ry *O۩QѲϿ2ї:}HֵW,ߨOIol4;A=8܁v"iL* 2Rj&&+J1/8.z-, -V-,+*k)%M"D 4^yGHb):Jg >>l?V Qt ` {VD+S`+k A ` P,qN,OrX X4L$;BS,`i???_:i%Y!OMUa!\9  uw)m kt"$|'(*I+y,*#)|))4)($ :V8GVߗZ޿fخז+ܿNa E&`x7K}>\܏eԙ@BS%0v* 6.J8px+"%%d%"%$=!Ax""Qn4j0[ :(1,J0 'A~86+CD=V n W   8[2&:PսӢ֛tn|bic*++Ll0GN Vcp=X8x j RyHGX ir|"1 E@;X"P >%   1Y  uA8? Pa )` W{  t  i sS41- T`KR e1Mj% o>J7%rFZ@   b  "  , f 5a:t B K+ 9' UZi  s5? `@ p=|l0ٕ׼v *5D)"9&',)'{& ! 1.BU)4~]Pp92E Z>" 9om)9~D Tvj sx} j;yAb&#|%JpQ {Q}{yvs 4 f ] mS9.3 8"#%*#U!?)i a+= H Iu'p3Pm ;\})%0;fUD$dk234 tLS0֤F́җ ,%QTLBl&/8*5r1*#|#2# /kc[$m8 x ^ Gq`&;1Uy4<#  , u U / 3:A\Be,\u.l>47 +Z43w aP?Z?#Z E @=I]/Pj =[ z  K0s"x=rIN-i]^6 B 4h p5vT0T'KoI \#+3: LZUGE^7 OQUL  ` b kZM  j  @]xMvg d  &(q6Skp _+m @O@` (08\Nv?ԭҵҽҪԗ+ٿۆM'f`-pNG! mI%E/mW7@MZQG; }Jc H#%H%$E$##Q$j$$#" f" U = dR @ 5U*݄ C G۹ɷʭ*ͧΕӂ ܾ+_܇݃~ߣR9  d > E{_/~i! 0 6Xz'LJ 6u8Y$Z "~#$`&'(E)}('$@"GN d w 6 WAUh~ 45.Y(f۾!S!8NXcp1 E \ s A  !~LJs n j l|Wa:x#EP'' uB # % ' t5duW 3 r|E I^ .mr'2+Hdy&WYTp`3y߿߮obU _z20~E v  z l XEmM&]T &4B  _ n!!"$D&(s*`,/3@4d52m0+&" oZt9iid,e]ps L?Q}KrlUrL}9GGMT=~xWO v f,! <y bE ) *,cF =\fv #/&\%$! ^ ,k ` w RQc| MI* :j!\eM&#l:RbSCTdzFvh' ?5c>t\}Z)m*  c s t va+>R/ G& cH}+ln;$ YzX$\s*.?xvgO!KuT] A % " gt97x@LX,= |^@0!"9 Q  Gu nN.xG5rpn THL" e 1 H_>? A !$(D`(EP (>o2m|7[6c u:>Paw}F]UH8(E){OuD-F:']<MKG D 1 m Ce i | o/7?+-% k,$HkxF*I&8U&J3Mfy1)^t%]S.#*|Zd +q$O+/O455^2.J*%A!@K :&Z|G}CPDR?_~o_isI#_(7GITy"Deb^ Ksd$]r_$P RiP IrQ wTh[j} ' b <'{Fv ] :0sN(kCڝGg 98mC=2& 70) |,SWfF !MVS# \iw [ ;6 h&=  ) & # 7L2AB?#^yFxTxE~0$y$)?O`['S  ELN+j578u 0Lf%'),{a?Zu _NMA lO1>-xT[l%/iN *r"$j'%B$ C\8v] 6dQMctw&HjJ(ylvB |x]_ zEYm."dg y W _d( A#m~w1;EW j?6YT  u#m  $Af)!T:zCFb} yty\@o\M?n=k]cGA'O_}[(?V')@]$'e+.Q  9 A. -:hu e{iO5^R ߣ7gbjPD8?F@: >yYl nXAf,~J{2 j-)a ^8= i 5 ; 6W d-<\޼zr8-|F<2~%=$t` L3p ;j:{NK[U7KJ~c[)I;. B IXg. S X'1 $ [C\'T Tjzm< %7II  A C E -vUx? D#kw o=f feB~2e 9:L_RF(#? w BPe CGQdpGR$;5.fBZr#dXzV[`&>&P&'{DU#h&ti 1C ( 8 c5>G)f fH u El71;F`z3 "W7 nqF lHn*>AEGw f^<{963^A91-KU_qezG'hw*!O1\1nbU$P^8x^]<V F~C  G"Z&$D&afl,A}6]f-ZJ;Hg6oMdz.}Mb  \w3YR" >LsHJ\F|Ao[!(#Z^cz  $u9. $ g ';YmquwxP(S.H'.MA.n U d N \  u=">DI:+b&A +[fK0 $yT!hI|<@c O+f@. #.&Tc= ? 5WT { #  3`"o;6 [E-dM  s /9lT;Zy[B'5*;oCNzb 0Ib7n_Q xN F T?r*fa#X)@7(mfL8RlU\Ypa o]Y- nH%KQ  d s > { v ^BxOC6OhR<xPV{Y P$jM05l&rH&K9Uqv -UrsV'+sR Cw< Ks1yJ 7GxG'\qmWv-Uu9Vh~ V  L< s M O.O , R + g% Mv 4 ^E `=~:kFg0mpsN):vBpc1wC t~'fuS " A ao~7 0 ) # x xCQ`..5;PNH! e+y2i#U+]nv2!UMEj4&,2@Nw3"e' ?t4U5o^N w)[k o `sh]*C T]f7 T T U B / +E<OZ.v+a' @>N~F 7_YS#rb  AGM&)8EcMd5UE54 bEzD0f . >[ ^upKg e f ! B 8Nc[:)/hL'1_c!b(X'Y\_`}@gm1 >oaS'!<$(Gg%Sa5mkihgo9>.:j"Bf&bM1 SLp|M\C[/VN y7h[ u ^ G 2hG2s  a c  !bnO $>~A}Hn > i { b '_8`  |{pf(H|\)Fg R\6 s{iGPr]Zk lUN}{yWhfvW(tA ; l`! E9K<4L8=o2rBSvT2: ) y  .'K]nW@](61_*h-m-[J~Q$t / )rtw1} t 4 :q~,nn]gtE _;  d #/i[Mp3Y&*UtR/a[{.jk2Lfdbn`gT'rN 7 P it'&q`%PFi+`K^M.iaZC-= v 4',=Oq vYZ0[ !>[h +J L e7{FV?J* ]%*q:^ (2_;1hQ;i ,hb\l8  O8YG5>"-sU1 y)f!NkA%vX % V  z r j 1  1h{`F~ *J kU y  O   avs \  ` A  'u1\@f(/tfW YvY=[q9Vr]Y W*[$k1GS Rl,+iFk(D>)bAFF~l oR5 ,$* 8 4 0 J *Jj H g \Q,O  ( ^ W P g:62p \o;/"5GQk_f w cU&x Qrjbj:v#~xG'Z:PipUZxfv&KxjnU;-QHg/a(n4pW4JelZ9q`bs g [`ffO9#Ks:1tvxU *  [  :  ( [ `e3Cy`;0LhR;:9z~YZy% b\U)'&RzN9 RxpS. L[2 T  0 =  z 7Y7}\QFOI7_\Z)AZ*?)A{;xt:bW*:&c:i;9<{.$NqT6a ax@x#; #B"0lk'OR V  ' Y8Gof_\XXG@HOlt_|V}ap /b3oO/,8;N(_Q45:@o' rjipw5@Ko](f/,{U/j?[I1rX>c%MoQv~ea]Ba:u<9$OzK-km8I@AB\7Y-JLzp4:f3P[f kSESYQz@ _rWO'  + 3BJ7`dr1FXu"P_!SG" f uaWM/ ^:S\)?h Bw Q %=Up8[jys1 SA/ G<d[s} k0o`G?7DQy[=j=!Vl hN3K$G) * XZbjG#_Vgg6\5rtt ,"gH&``QW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/rune3.wav000066400000000000000000000350061475442401000262110ustar00rootroot00000000000000RIFF9WAVEfmt ++data|9~~~~~~~}}~~~}||||}~~~~~~~~~~}{zzz|}~~}}~~~~|zxxyzyyz|~~~}}~~|{{|~|{{||}~~~~~|{{{||}~~zxy|}~}{{|||}}|yvuux|~~zywvvwxxxz{{{|~~~|ywwwvttuvwy|ztpnnpu|~~}xx{}zwvwz~}}~~}||xwy}}zy{|~~{~~{{||||}|{|}{vw|~|z{zyxxyxxxyz{~}|~{xz~}|||{yxz{z|~~}{{{{{ywy}|xx~{zyy}}vqrx}~|~yx|}|vpqvzz}~{xx{zz~~zxxxz~{y|~|~~volmrz~|~~wrqtussuz||}{uux~}zvuy{{wx}wux}~}~}}uqoory}zusuy|z|~|}~|~yoiinrsqrtv~}tqu{~{squwpquxy{~~zohhkmlou{}}|tlecejmljlszysomd^^ab[[aju}{qicbelswtjcdnw|xlcbhmlhhnuxupnsy|xrk`^cntuvusolmu|xrkc^blvuqmjmry}|jemx}xlaXRMHEJVgryzzyobXVUW_ksmioxw}ygWOSZ_bhv~}wqke_^dp|{vxz}~{|wkfn{zx{~||uty|}tprz}|{pjghmot{}wjglr|~sihu~zz{}|~}wsv~snnorv|~{xuvy|}||vpx|vi\[h|ytx{xsqtzy{~|rcWTXafeegjklou{xcUPV[_^XSOOT_s{yskdccdb[RJKWj}}|xyrjimlaO@@M`p~|rouymaWUZcp{umhn{xgafkaRIJS^gmr~xywqmrx}pgnw|yfYd|vkkrwiVNS^chnrywrvz}mYMIKOSW[^`bjxre[VY]cg^TQXer}qeTA;;=BFNczxd[^a[\epnaZX`kw~ziUO_j_VT[ZV[ix{uzlZZjrjfghaPAKlyrjffd^RZiogaq~ɽzl]PHJQMGDAGWrkYQTY[XY_ggcfp~|~~snrz}}yjbbdghkv˹yi]ULEDQbng^bgp}wdSU^^XU^^VQR\l~hUTZ^[TUbt{lSFWu{vw|xkZ^t}qZNIFDK\l}}tYB.)6I[hsuphk{hNOSO?=DSkwq\Uewwuw[>7Fbr|xtsiN=>M_ltwyxw|yonobX^xzpt}{|karukhqy{}woiimlryvnls^J@JaofE7E`s~ztdVS\a[NP]jaOJ^yxkqzqaatzp}_D?V}~nqvos{J13F_nu{ukj{{fI52AV^aj{~olmcTT]aQ?7Ciʨy|y|pUE@?ACDResuzDZwongYID?=BOVMHNfyѿrfx|]EB_}tqgj{{py{eWcxxv}cFXuhmzvy}|mXFAMU\mx~oq{vmd]WTXdomZJJ\l{ݿx{oWKNX^UMNTQJTm~|~oHHUYLACFUsȰxdXUjlK?DEPf{U;?\y̭c[gwr`OF.1Lp|³ƷnA+PuX@-/BVZT^}~sŶ{gVS`xweeoxvsrln{yjtle|hT`qrgaccXR[nxrplik}~~|jgqthUKZqrit}uhr~żphtzsu}w|edll`]qvd[`}ywz^HBLm|ggzzebtvcg{gm~dRI?;H`xdOYrYJ:0=csn{`b`[azieurgUEAJPR^l|x|}qwnMDRfYDK`gUXk~~hKCO_hsq__owbPRmάqaYVXW\ZHLdz}|{uyuovƼydorg_dpv~{{}kL/!8X{»˩taODGE6,4GSPFBKayĶ[IB=0$ /Jf~ĭdO:Ndhp߿cN2(BROFG`~â}cR=8:9*!.7GXdZGMj̩oj`=  3ER]jy̴_ObzphffTM^ntrntypxwozhnU:ARVXlvrxygMFFSl{qacʴopVFVs{oZMRftpersndPEQYgx|fHOX[^ftytwZPoq\OV[_m{}|έ|k^t´}vqogZSJAE\|v]UWZds~mhkowjfiiioɾyqdYVXdylcȶ}jlk][[ix}ujggx~{~U63BH@79Qs{wЮ{V5"0\b5#5VٵɳyXNK<Pg4,Rw淑n7%7?<:DPRJ7'-N̺wobcjY[{Z>D`xlP;>Qg~y_RI2"'Ccc[qz}tr|ǵmSKYle]^jR.(+6@Wmtugbõ}wzkr~zufE-4YkbSP\gaUWƝ~S56Tu~Y-1Ujnz|q__illhdZSSF=CQUTbxàεwcWZ\M8""CNO[q{oeuƲoaa_RA62456:?GP\r۳xbRC3(0HVZ\ZTKEEKZqٸƣxQA>6$$488?B:3BYxÿvaR: +/8Pqxjhӽ~oL>@:448-'5;CRgkfЭ~I-*'8W|οR (59=R`]hyױwdI/360Ejvtw̼|T' ,::1.@iǵnXLD8-3?>.#8Qfmt~һ̫xXZmqYB@HA517E_kkҵ\_x{jb^^\F$ 8bȱI-,4.9Ww}lbYSI_ʳg4';NZ\P>3:GWqמlM7 75" Fξ༩~jV<%)"+4CWlҼi_SA$!Ao˳^NSVA *HK5;_ƾrptqwlYWceK,-IZ[hʲzm[UOA;HatrhiltwwufUZkkO@BINXni|ëzpfdglnYC3-.8d~~xŮj[c~mggc]VPVekim~d\xlgmvrcJ01Idhfl~­|rmlke\WV[_hqnghy}{y}Ⱥ}V?IQB.%-?Ufk\KNmş}w}yjWQJ@2&'++'*OyvmuôhQPRPIEA40>\~±[=350661.4EPfvrƻЗU1G`aUKGDJSWJ@I[pqO;8FNMLJOXgsvtoi]\j}pZfykcO& #1234BPh̻uN"43.0I\WDCg˙~sgYD& (=5 &CPUf~ȤwZRK5" &2=LJBR}ԵdB-.?C5((3><6A\z}դu<"## %CgɻlQ<132# C^jf`sƥ~yveh}X5+75<\pn`pļW.(;W\exzxtpofkvzvxӺc]itŢ}n|taXO@.9[oZKa}ĵ`=.)',:Xg\9,@Yn}ķvI%%*E\ѯ^C=H9+/KQ)  -YrſкfQ]f\XPK<8TƴwjeN=I^k`RB-$1T~~pWHI]z|og]UX_`mUCOpǛ{nfio`:@ShppkhsղxsuqrlYC9:=G_gYIFQRYmĢuuvhU/-72.6IV_itt~Ι_:./:HRL6!$GYgrwo^evzŵzM@EC:.2Eb{lhp}hnqZXci`QP]vuxƽ˯v^IFOH;2J]^q{we^oxɞiSlwYU\osqn`G:I[rwu~zvlUKLVafeb`ZPB9>Z~вorwfC?DC3,FF@Olz`RXqֻ{_[k}tVH>DYsnR=2?duwɻyb<  1bƿ{aRLF<5-1HXaegfožc: #-Wwhc`esyxgULOWVQVcmeOHY|ǰ}hmrpaQINbsuePCIZZjiODJVZV@*(9KOYhykhpq^D."!.6>FRap̩voi[I:&9^ٴcD--8CKMF5)1PvȴwigbXGDUJARvrlqttvɱpfa\YYY`isͱtZB79>JgkOEXɰukdVD64@O[blvr~±{}`5!2HXcilxŻstyyrtxuvdI68Rt~}viaUMLXf_RVi||x|vbWWSJ7' )6Qm}ufqhV[hǪ]`rR@>FKHNU[agoyϯpJ*&&(=`˽ͿtkcRFVroF+6bzioaWYWOC@EJE::Vձs]MFCKZsyvȽń= " :jհa?-05*/ AlαʥzvbX\mhc|hD5>IGHXwsjsvw~vovthVYdmqsvx|zēaYixd]tlRUoyrv{qs~oVGMbe__kx|ô{}U0#6Umuqher~|~رmfnsyugFVp~|mgkԱyx{y|y`Vd{yX7Bx̻pceuy`NLT_l{wz}ŭt^D&/LYH. )AgĹgG2;DC=55:AGFCE^z̩ktpY\l}{~zQ3.Bdɴzkffo}U:B[xgUUmǸnbqi]YC#%036Ho¬l@)0SbTYa]20Pt͝~̱pF*+:JTixqtwtrxЫg^\M32<6&aʽj[NGF>8@DJUbkfuȺ~ywphU>=Ue\cs{}wnp||ülZ]dV<7Oc{ǷyY-  ->RdpxζxUMTS<%+GVh̵zjcR#  ':_ýn`ZM0$ 9VclW74BA8 8RnԮm@&)"!%5EX_g|m[`urY9>LG=9FPRPLRkű~vpjynLM`]OB@DIORU\f|ϵynG6AXrq_Yaahy}}xsthu~ȱmA:Tbr}mcpvonqvlgc_iv{q[TZeîkiorj]YL;1.A`Ӻĵor~xqjlusl_]p|[NLA:@Tk~ģiUKA1 )Jcr̻tN22?C4 &CQ\jg`a`ezע|zfmwVKIViyn?/Fv|yɾ{w}e- 7bl\buz}o]TF;Roy_D(2KibMCF]㻪k`a\K3$:XbZRS[g{ɴ̽z`:,40+"0D@Ky˳ŶįsH'%3?9,1Su~kmɷĤzWRRONC;932@[utr~vtlUXgvĶ}}gcc\K85LTWdľpũU(+GC0'?I1(:enpϵٱU2%2+%eƹ¯}vpidWC5/)).3:H|oY_Ͻ`D---6DGIC7:Q|ֶsmiY<$5Slhd\P>954E[dpxxqqַ̾zQ6,63!$2DQPLO{ϿiO>;?K]d_M;- 3Z~smuw_IDHF2%/ZtlksijzP*-D<,)+-5gϺ~aA($5?4-GjѬxqbJ.#.,!'Cgͼ}tpb9Aajpth[Q^xy|nvfbRM[fiozcU[l{dYQTct|kl~dH8.).G\YA&"HpȺŠtX8"&>KOHO[N3"?ShɑybUNB'  %?Sd|œw`SL ]̿d) +TxŧyK !;`jO,:_ǻƨ_D07RV@=:9@INUgǦnM68;)5> #YỒ͹wZEIk|gD(%/JoǢ{wkSO`bOR]_W_}ɸ|sqy}vgY]baa``kplb^rxsv}kL79Gizp|ʯ~Y<32:MJ4.=_sȳǟpQHJC:A;WynfggbTTiuu]Se{ohjK1%7IP`ozsww~}vz~UKQN;&# +O]kк|Ǯqadkmvsf`ZYdlmUL]gjh}{ŷ˥l4AO;+UosnXE?@IUբzӷbUe}fKOd{{phbS<*TtyfuŬfL9&%$#1BQ\clϨwVUT<  #CWk}ϴ`MWcSHFMTTcZ@A\ymhdiw{Y7<\seN[twpzξwniU<)2_vtľhQLYaP94Khuvv}aLHTiн|eRL5.'%>GJOd͹eIEP[UHA@K]n{{mch[<&+QѼrgWT[aP838:57BPZ]ittz~|ԸrUG0!!2GKUds|pggy{b\cn|eUUizlNCPbmjoqheoxxöxk\F:=AOhzŷyeem_K=GX]XWmyx~hhy|ywwmHB_~uqv|ePIXXF14LY_nȷjVQXZM=')Mrb?"6Q^VE:=FNLNUgy}}ѾzteXPE2 !1EZuɼܼynpxW"&5'-?Zxėp\]_T>"7NXUSWcmu{๚yVHQdsnZB379ASnpccgqȸ_/!/A=8:Oa`RI[jvzsmiildSHTo|hvǰy{xszhSDCQmvhdglim}Ƚ~ytqsi]QF:Jr~x{|s|vvzzxocN:?HLHCDQkͶskeK1+=E=)5Ws~}ſv`crykR<(&58-8dwxwƮrQ<8KlthTIHI^~vicrvquvomyshhsyfYXcyyiadkoqnhb\]mxlbYVY`jwzupptuvy~}rjitſnd`adhV7#(AY[[o}niaoʯviS:./;1%&&&+D[dbap­}ocYMC4-18AGPRH>Fky´rcXG@D[cT?,)+<[zdVX\XQTZ\UKKZfedlkVdplQBHNSVbllov`EDQZYL@KYeq|}x|_G622AWcepwsps~aY^WMC>>CP`kqwxtbWMC<>@?DZeYEBHa{x{{wjUB@@@ABMWXUPUdwmeYKCAABADIR\hrxxuqkltzdWV[elt|~u`Z^]\`hlfjrxunsznb]ZYXUZaels{{ogloh`UMGGGNanx{yorrl`WTT[fpoaSP\p~tin}uotzxz~}rdYXcxvmkmqv~n]VYcgjqtmdft}{|s{yqmifb_cjkfbjppmlpuyyzpceillnqng\WYcszz~}xn`[Z[XXcoy|vs}upsyxqmnpjeit{xxukhjkkhcZWarwqsvvttolmkhdfpy{~yuspjfhmqspjhjpsuzpggosqkghilrvyz|wpmkmruvrqt|}xsqty{|~}}ywtpt}}vrnlq|~zuwz~|{}phcbfnz~~rox}uljmljloruy{{xvuvz~ywuqnonlidaaadkv}ztmmnnkigdcbfovz~wlegghhfegknry}ytpmlnpsruz||wzvrty|vwwwv{zwxwusx}|yy{}yvwzz{}~{z|}~{yy~}{{}}||}|{ywz}{{|zvtuxwx{}~}}~}~zvttuvxyyxvuvy|}~~~~|wux{|{yvsstvwx{||{}}}}|{yxusuxzyz|~}{|}~}}~zustuvz}}}}}}}}{yxy{}}~~~}|~~}|{zyy{~~|||ywvvwxz~}|{zyyz{}}}|~~}zyyyz{{||||}}}~}|||{zz{{{}~}}~~}}}~~}}}}~LISTTINFOICRD 1997-02-11ISFT4Cool Edit v.95 by Syntrillium Software CorporationQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/rune/rune4.wav000066400000000000000000000263721475442401000262200ustar00rootroot00000000000000RIFF,WAVEfmt ++data,~}}}}~~~~~~~~~~~~}|{{{||}~~~~~~~~~~~}|{{{{{||}}~~}|{zzyyyz{{|}}~~~}}|||||}}~~~}}|{zyyyyz{|}~~~}}}||||||}}~~~~~~}|{{zyxxxxxyz|}~~|{zyxxwvvvuvvwyz{|}}~~}||{{{{{{zzyyxxxxxxyyyzz{|}~~~}||{{{{{{|{{||}}}}}|{{zyxwwwwwvvvwxy{|~~|{zyxwvuttssssstuvwyz||}~~}||{{zyxwuuttttuvwxyzzzzzzz{|}~~}|{{zzzzzzyzzz{{{zzyxxwvvvuuttuuvvwwxz{}~~}|{zyxxwvutssrrqqqrrsstuwxz|~}|{yxvusrqqpqrstuvwxxxxxwwxxz{|~~}||{zzyxxyyyxwwvuutttssssssssstuvxyyz{|}~~{yxwvvuutssrrqqqqqqqqqrstuvxz|~}{ywutrqppooppqrsttuvvvwwwwxxy{}~|{zyyxxwvutsrrqqqqqqpqqqrrstuvwxzz{{{{|~~{ywvtsrrqqqqqqppppppppqqrstuvwy{}~|zwusrqpoooonnooopqrstuvvwwxyz|~|{zyxwusrqponnnnnnnnnoopqrtuwxxyyzz{{|}~}zxvtrqpoooooooooooopppqqrssttuwxz|~}zxvtrqpponnmlllllmnpqstuvwxy{}~}{ywusqonmlkkkjjjjkklmnpqstvwwwwxxyz{}}{yvtrponmmmmmmnnnnoooooppqqrstuvwy|}{xvtrqponmlkjiiiijklnprsuvwy{}~|ywtromlkjihggfffghijlnpqsttuuuuuvxz|~}zwtqomlkkjjjjjkklllllllmmnopqrrtvz}}zwusqonlkjihfedddefhjloprtvxz|~~|yvspnkihfedcbaaabcdfhjlnoqrsssrrsvx{}~{xtpmjigfeeeeffggggggghhhijlmnopsw{~{wtpmkigfeca`^]]]]_adgjloqrtvx{}}{xvrolifda_]\[ZYYYZ[]_adfikmoppoopruwz}|xsnjfc`^]\\]^^__```_```abcefhiknrw}~ytojfc`^\ZXVUTSSTVY\_cfjlnopqsw{|yvtqnkgd`]ZWUSQPOOOOPRTWZ]adgjkkllnqsux|zuoic]YVTRRRSTTUVVVUUVVWXZ[]`beimrx~~xqkd_ZUROMKJIIIKMPSVZ^behijjkmpv}zuqmkhfb^[WTQNKIGEDCDDFHJNRW[_cfgjloqrtvy~yrkd\VPLJHHHHIJJJJJJKLMNPQTVY\afmty~yqh_VOIDA?=<=>@CFIMPTX\_abccdeiox{slgdb`]ZWSPLIEA><:9879;>BFJPU[_chmqrsstv{{pg_WOHDA?=========>?ACEGILNRV\cltz~ÿ{qfZOF=720//0369=AEJNRUWY[\\]^bhq|zskc^[YXVTQLHB=941.+**+-/37=CJPV]djnpppqsxþtfZQIB<7420/....../1358:3*#  "&*.49?DHLOQRSSTVY^gsþzsjaYTQPONJE?93-'""&,3;CJRZbhkllmpu}zhXKB:3-'$! "$&(+/38>EO[gr{ǿviZJ;/$!'.4:?DGIJKKKMPU]ixû|vne\TOMKJFA;3,%$+3EJPX_ehhhimu¾lZMB90'"!%(,04:BLYgs|~n]L=0&#(,16;?CFHJKMPWcryoe\WSNH@7.&!)19AHNRUZ^bdfhmwĿxi\PC7,$ "%(+/49?HR^it~ƾufVG:/'"!&+18>DILPT[dp~yqke]UK@4*   &-5>@CGILNS[erȿumhd`\\]^_^ZUNF>70+'#!")3@NZeozÿ}o`QD91*#!%(*+*)((+07ALYfsǼ{smiecb`_^]ZVPG>5.)'')-28=BDEFIKKJIJLRZbkt|ɿ}vronoppmifdba^ZTNGA<74336w{l|ioiqtmmykoix`yPKi|s9txxuxfLhUzwd~ubmdpd}pf|WQo*vk\rjlr_Sn[{rrhjo~tZiepuex}zXimszioh~vMs~f[eWBd[WaYC>hvS_~@^\qA|heXRPG=ގM;\ahkodR}[_f`vWp|a&svlxe3~wh~y{Ew|uqBkxrlxllVwvj^q[y~^{fHwylznZjqtojmKftY|yiv~yxuXormlxlvmwrlqrkh^Lxnr|xrtY_wkt}hmpyy`cozbkri|vpi~irohmzpz}sgm{oqpQz}dsQ}mA[hh]}w`iyduq×}nyog}{blqxUmhhhsynuho{|zahkrxxxxx}piz|mok{[{n[cup{txY}zP_w[lLvfb_gnuppukynsqLsm|hhrlty|iv~ytvjp}qp}}miotYy~iP||}T{UqtxS|vijyqfw}zjvivr{|swpp|{uu}|zxxpt|{qvqnytvbvxwvqxzvppyy{}||rwy{xqnu~xx{z|uxxx}}p{{sw|xx~xvx{xxx~{urtxx~|}svx|xxsxxxy}xxxxxx}{{{z|{wz}vrxzpzyyx}ttxyy|~x|}xxxx}yxxx~~y~|~x|z}zxvq~~yrx~{xxx~{xyxxx||z|xxxx}~|~x~xzz}zr{{~qvx{y~}yz|~y{xzy}}xx~}z||}y}xx~y~~y}{}z{||xxx}}yz|~x~|z{{z}z|x~{|~y{|y}y~z|z|y}{{{{~xx}z|y~|{~x~xx{q~|xxx~u}p}}zxyyxx~}xxx|zsz|zztxyx|y}}zz}{{x~}yz|~y}{|xryru{{xu~}xx~z|}xxpytz{x}{~q|r|r~w}|~yyt{{~x~}{xx~xyz|zxxx~xx{}|}wqxy~x|~xx}rvwqz{xx}|xxx|{xyxy~yy}|z{~~x~xx}zx|~x~|{y~||~{~xzu~sxx}zx|xwyw{}}z{{z|xsyzxz{xz{x|{~zx|y}|z~{|z{xxx}zty}xx~z~}y}yz|}xxxxxy||y}xx~~y~x}xx{{}||xx{x{{{xx|}xxx|y~xx~z|~yy~xzz}x~yx{z|y~|{z|{{|}zxz~|}z{{|{|~x~xxx{z|{|y}x~x{z}~x~x~~yz~x~x~}y~y|z}zz||z~y~xx~x~~yz}~x~{{}xx~z}z}y}z||xy{|{{z}}{{{yzyxn}pt~qvezgyouts~r|xxyz|~yz|~x{}{xy{wx}x|ywvyxx~{r~}t||}~x{wxzy{|tttu{x{{{xw}xzy~~y{|x}yus|{z|zx{{~||z||z{{||{|y}x~|xy|z|z|{z|{xyx{|{|zz}y}}y~y{{y}}y}y|z}y|{z|~x|z}{{{|}z|y{xzyszxu{{}xxx~~y{|}z}z|{xy|z~|{{}xx~y~y}~y|zx~}yxy|z~|y}}z}xx~y~~xx~}xx~y~}zyx~yz|y}~xx}xx|{{y~yxy}{{{xzy}{{{{yx|z}z}z}z|z||z|xxx~{xzy}~x~z|}z|{z|yx|z}{|y~~x}zz||z}yzxxxxx|~x~~x~xxzxwxxvxx~xyx|cz^ypy{nzvpzqvxxyz~t~p}~xx}zr|z|zyt}w~qxxr{q~tyzy~xzu~s}{r|zq~~yz~{~xt|sz|y}||{y~y{|{~y}xx~zt{z}|z~y~yywyx{p~x~~q}yz{q|vp{z|lxyyt{x}yxyz~xx}~xztwvxv|z|}x~qut|u|ypqx}}}{}}q}y}z}x~|~|}x~}zwxr{y~~y{xs{~y~yy~v{~zx|~x}xxxz|x{z|~y||{}x|}y}y|z~|y}|z}z{{x|}}xx~}y|{zy|zy}y~}y|zvw{x~pz{}zzyy}xq~s{{|tuvy|{}hu|izuihahyvc{obAzkxqyjxxldug[kk{~gbr}}xx~wzsznj~tj]yulrmvxf}t|ytqri|~suzlm{pn||q}}wyy~}xx}cxy~njuksgrz}t|{txX~x|xzrwtp~lrxqx~yxkt{~|qwquuuylz\ozqwqwz|}zx|{w|zvs{ws}}uox}t|ppzxzszx{~q|kr~utvwzx~zxxxx}pwxxx}qxjw}xxy~||p}wl}kw~wu{xxxqx~xwpvbuio{|zRhhyYrl}x[iusu{Q^spx|zr~y{}}|{utvu}mtkv{spzsl~r|zbrr}|eoXdwqimyz}zxz~y}tvp}wjfvurltyup|pzy{{y{ylqlx|xwqpwyasj{{|~x|~xqpsrYue~ws{yt}s{|ti|zyoq{~qplqutxy{{{x~z|zxtt|vpw}|izzszxl|y}|vp}qzwq{~yxx}}xx~}y|xxx~|z{{yxsuqhhu}y~xxx|~xx}y~xxxxxxxxur~~xx}zrxxx{|q~{xz|xyzxxy|z{xxxx}~x{xx|}xxx|y~{{|xxx}}yy~|xxxx|~x}zy}{xxxxxxxxxxxyzx{y~~xxxxxy{xxx{xxx{xxxx}}zz}x~|{y~}xxxxxxxxxxyyx|~x|zyxxxxxx{xx|}xxx|{|LISTJINFOISFT>File created by GoldWave. GoldWave copyright (C) Chris CraigQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/weapons/chain1.wav000066400000000000000000000064501475442401000270240ustar00rootroot00000000000000RIFF WAVEfmt ++dataT y||knqVpjwtgsp}syz|s}}zyzqj|z|swvvsq}wzzmqzvwt|y||p}sy||wkvyt}|}|vv|wvzy|tzst|kzttww|z}v}sv}vvy|qzw|zvy}}wy|ywqtqw||v|zzqmqzvvs|nvny|yy}yw}|vsz|t}}ytz}}vwvzy|z|yy}||}}}|y|y|yyww}z}zp}}|||}|z|zvy|z|qhjmvtysytdnvw|sywqs\q4}yFsjkezt|eqddndqAz^pYVw|ngVP|}SysVet_z}v[_spa^gCpg|}m}zws}zpvkn\VqwX|wbdhzqhztvnvVpYwtsvqdnznpzptvznnh}|wz|vw}||}yt||yv|w}vyy}zz|zy||z|}|w|vyvz}wwny}zvz|vy}mk|wynqzvyzqytvye|nw}wzyqy|szzgsvty}}}yz|}z}p||zv|zz}zptk\qFnwpbVmdYmqjFª}JVs_ŌA}bbwmtzFgMtevV\vjptnw}Jkw}kqstmtpa|v}zvh|qqvbv_tbwkqtzvsn}p}}ww}|ssqh}zpspdmUqzvhqwy}pwkwkmwwzm}}|spbp}yz}zyqtpzsqq}yhwz|y||y|}ptwz|zw}|h|z||w|wyw}}s|s}ssvjjȐdvzV\gȟ\gt4_kayDzkedekbqd|gdk|qt\wvgY|^w>\tXMazy^t}at_wnqz}ghtXPs}gVbs|pq}qmvv|}ztq_bkvqwnsszzy|wztew|v}j}wpstmwz}tp||qttntwws}q|p}sjyy|wzwznyvsz}pq\wsayk|k|||atyAysttjqyvd|thy|yt}m_zywq}\X|}tgnnaq|mkhk}vq}twz||qnqkwjds}zw|}z|}zt}w}}ykq|}}t|ww}}z|}|tv}zwy}}vwqywy}z|z||}z}}ywwwyw||}}||wzwyvqz}wq|zv}}}|vt|y|vwtvnswvsvzz}}}ztvwvwvvqtwytv}t|zq|tb|jqvyvn|wtq}w|nysqwmn}w|ytnqv|vywz}ns|}}yy}wmp|}wvq}}|zwzz}vyzwzz||wzyz}y}}|}}||yyzv}sz}}zw|}}zy|z}|y}}y}|}z}|z}yz|y}}}}}}|}||zzz}}||whzgkqnkvgnwppXVskyzyzpk|y}myhsywmtv_zwgPw[Xh|tswwpvtqhztet}j}sw}twyynpkw[e|mvgsz|k|jwzkqwswp}mjvt|mtt|t|w}w|||w|zv}}|z}wzq}}}|}}|}|zzz|}}wwy}}wy}}|}ww}|}|ywy}}||zwswy||||zzyw|vywzvs|zz}yzz|}|z}zwyztytssz}z|np}}zz||yy||vzzy}LISTJINFOISFT>File created by GoldWave. GoldWave copyright (C) Chris Craigcue dataLIST*adtllabl MARK000note RangeQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/weapons/chain2.wav000066400000000000000000000061701475442401000270240ustar00rootroot00000000000000RIFFp WAVEfmt ++data _jygyspgqwzhjwwzpqy}pvwz}ezypqzw||tzy||w}|vj|yzt}j|q|zy}q|zwztzz}v}}y}}||s|zvsw|vz|y}|}}}z}z}ywyy}|}z||zz|}zz|}z||y||}}}zzzz|}||}}|y}}|z}|j}gntyhvm}hskgzvwtwwdkzvvq^mmtm}}twyynvv}sznyswks|syz}wz}}}}}vz}|}swt||ywt}PFshSUbpSpy|,JF݆_:bVpnvzFvVnPa}nbdnnkVsjkyCbe[zeI}zv}y\gtswmd}mnbh}|b\kbt}zys}|pzdz}tztanghhnq|tvnvw}}|tz|sznk|sszvzppzv|pvkmwvvg||n}wyt||zXSmvbpkUvXR|}yU^pVd(ba7M˜CҀJzjsV\q^h^qsmmnhp|pw\Unhvn^n|y}bs}jqdg|wytd}dzt|p|}zk}nzqnjezhgvjtvjyzsj[sskvqj[kvnyhp}}|swnvp|t}}vj}hwgj}|yew}vvwnkwwyzzpwvsyzzz|m|zjv|ssmvywtvz|q}zqyyww|pw|}wztwzwzzw}yz}y}|v|zwzyvzsnyy}zs}vtzsz|}|}w|z|}}z|yw|yyzzz|}vz}||}zz}}}y||zyv}[GmŰOLѱkg(phgɞVhgMke_IUaYnwXR^|zjhj^MJg|wSSyj|jdɓbXs=MvtƄI_sebjeɤvpVe|^}ntCatvMyMkmsy|k_tggVvaqYqgj|bgszhP[zpqkwe|kgnytwqYetjs|a|gtwzmqUhe}}\tP_gwqyqzvy|ybsbt|jyzpvsasb|}}nqzzzvtmsykvzjmpyk}yqqqppv|}|q}|pkyyznytw|vt||qzqtzywt|yhzzvy|w}yyzzwwvt|w}tq|wt\vaq^^d}g|n^nP[_gsqzyvk}ssj|tywqpsvwnhtjmzevn||smtp}v|vt}ynqyw}gw}vwwvyphbemd\_y\mwy=Pt|/^hzekpm}qmdzvv[}bs}[wnbbh|aIqYhsbYy}_btjvz|}yynk|hn|sd\Ysw^zszzq||sj|j|kdsq|js||qz|z|vwyzp||vyyyvyzw}nqpnhywvmvz|}yzy||vzyz|qzyz||yqytyw}|w}||}zwzwz|}}nvtw}|ywzy|wyw}|zzy}|}}qtzt}syvztzy}|vzw||}|syz|zy|yvv}}wzyw}zyw|tyy}||zz}w|}zyzwyw}|wz}|yy}z}}|}|}sz}}yz|||}}}}}yz|}zz}}}vvq|tyw}||}z}yzzqnq}vv}t|t}||yz|vy}wy}y|tz}zLISTJINFOISFT>File created by GoldWave. GoldWave copyright (C) Chris Craigcue dataLIST*adtllabl MARK000note RangeQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/weapons/chain3.wav000066400000000000000000000140341475442401000270230ustar00rootroot00000000000000RIFFWAVEfmt ++dataHzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzztzzzzzzzzzzzzzzzzzzzzzzzzzLISTJINFOISFT>File created by GoldWave. GoldWave copyright (C) Chris Craigcue dataLIST*adtllabl MARK000note RangeQW-Group-ktx-d05d6ca/resources/example-configs/ktx/sound/weapons/coilgun.wav000066400000000000000000001722661475442401000273320ustar00rootroot00000000000000RIFFWAVEfmt DXPAD data "A{g9(GA^F=5BY5as \{^xZ- R.?|J1v i QaV#s[R o[K$Wgx?Mr[c,C"a#Yku@< >yQ2GD((Zn=E8kCKIw] IAZ; XB..%hXJIn\x TzfDO uIfLb5 1 G-3YBZk >l8d++Fg\xscln'Wh= TMP%U4?R9Zs)jB /JYYC k z M8ZGFn5N;+K ^8/ueb.L*R8#b-Q,,D]7*>$HGmG1|<S B o=S&V3/K"Ya@aeH<MSlo  L'b!u|cLDO F|!g~ )%taW>FS.X2 /=H~<OGwyV'H!Z&@H60@Q%^6YXQurmqHGZ' ,l =LIw0DuiN_#x ^ o . c2,$n4+)PMT$GO+}Y=X 4| ~!h jYCN~_~Od7r7t&yTb^ir)(@~Y%c7o9CVA Mh3`)3}3$ Kxs`#Ks&(tHN`d]%7o][ MvVP3lMM q "  / &K\v> w,f?TuA n# x"B`P=%9]2<V o0?~/vBA%b=.((Iq D2I g:+xx{pY ? uPdU< >' 0:G@pKoL ` WkT>'cB|Av74pVy6 }KhocL9^-+G${*M $P ? rOjcMoxZ* &R G^0$Vo $ ;46VZC` c v NVa  b[  l[t# i QVf3 K<A g>w,  rc6f>1~ :, ;l`  Q*F6/6svF % &"7(;I C fw 2 ) O9cVB  Wgcw5=<{6CkN L ,   w !}BQ4 eGqO9H9%]  ~e BGV g y*t7 $[Xo=\[RrPva2B] j 6< Y -,."E"m /me/"1\Z'C )-"=$[&nL [gdFNN q [ vK9J  5Ѫլ\+o \ 6&Ty4){*5B߉ֽDԖsTɐ؆9sKIG8 RDR̶4񮇫X8;!"5 C:5*ӱ-NŠ-<Y)<)->9u$.:@C.2x%E=d5"131A*(&#%'(&4 2aHRH8/:kCHQoU SI- *:C5"&)+.'^/77;C$>z"?1l(yی b[   :yDG\u;,Qj41!fz (fsޫz}ղNJºռۢo~)= - k#!b.ֺ@%TkX8sD"j>KSWVTDHT$"47C+:/1C!)ȷޮežϫ̝fg!mʼ6 2LpR܁SNqhdF֐`Բ!(Úkϱ*w .DA;7(*<;<&YbkIs z 6w$> BBV>NCM NILnN"M>)s j A1RE.!*=S' "˻گܺ!H5TCF'|(3¢޲奙}ۢ#!$d:aJѣzhֵb5 y7t/ Ǖ-m _vu)$' w,J \8*c-GU3Y SkC8@1=b20-RT:k:͞˅E'ȴƫ˥̄,!~sjE%lʼfԮ BUuLD)&'<=.ŰԮ__u6.}]?g6DQ@@`-9C-G-A8A>OTR^oQ-v}hD#jDA,JmG|YVH0^ 1Y~N:%6AfF2. (GUɱ%pW8 &,0KXQ!#PGW,,qRGNDC DA11fiTNU ^Z< qBAY_\\RIL#PLMIp'@Be4Ԩҿ°[6Gxר0w0 %Ϥȝ;McPw/(ȯڲg zEh#dWо8̿ Ӟ@3{(/X*6Ğڣ4` mPP?ᡔy?.ɪuMBe 5]LE %.#/Fbʈ%3+FA O(54ųAѼC᤽ԬȗEr'='4. DaLLAOQ(ZvI.B/+2{*78HA#HI'|iNZ;!R>ZDU"]6Y"D>D?IQ.~,>.%;}WH[jbf_`mftg#P6ۄ"UQM]> o8lWd_fx^!AO`O$^teJ?><7 FdOxkrzGwy{xpoupzynL]`XnlR&Uoh|uZVi|tE#G>}GbB|Ti`P!iai w BnG$B8qUF4%դbH=Z4֋"o%;[#nX{!3j, K ٧~&T1V;0(Lܾ"dFޟu؄*z=qPnϰN*8?RD(-8͵P<ҳ],L3!=F65b+ŭ=r"ɫ2y 9oERl̈YN8ʟկ Լ1PM"ZW:s!G {- "$- .̞ˑy.H& ⰱ~ ոt+W;/ĒbۛއhKqMoy@7--@5f9ñ;_*u8+AMj˙kH9/b"L ` P`[JQH^9)+NH]K{J`IsFZcacRzPWUcjkiidO8 Z48`FGh%o;epiywSi<9׺KP]chWk/txmmvWN$-'$0,ds@+dO/l-q$.՛HS}9_g{ z=~PqELG4%{BprDoZd}pu;lwR YYpmNopd7t_zVxvj(aubicUjx=2)`FsyEzt4hW>NsvMo#>xL}[} ohf6pUh4-#>(PK85wȿSW τԎs1¾-(׆7,w)xȒ׊Bрٞ~б0w‚$nє\Z޲_%؇օ zV8܅: jAI« +l%ϸܻ{|W͛lՏ g[ |ω0r^>D1@k,}tA2>O\{Ϩ&;8*A{PZY] ^GbdWd/ܞt \*,."TR >;XWa?*68m6_@K 3 ۺ;wMkD>^pm|dZCJVsʥLhGiNs@nb?'7u0~d=UOYF:$_MxcSz n.cCU(M4].dPCwTlA'Kb:r|by~YW:3JlTO_VBNH$}I_H>'C^uxHqF0k5<K`׏%h%4J:y=+52W oͨ Y:l3^_q\L^=|D{`r%ulIv]A3 / _7݋]diSB&+`hHk:rcpkfedQ<;  ([JoO->WD15P8SxWVnbc;N+$F+#*eNP*M7R(w;(9aANQL.dQ/ )I-)3%5$RaJxlĸ{Bһ?tοոD` b)-[v&(ٟiδ;!8i$5黰,x* T3A`TH't,6jP~D͸R|J֥bnIK-?]4Vĺ !쑼ӷ cěPvڬ?g5$MY&sG<C'" ݕvӹ* 5J$"p=1 f 0V06DIKmH&g B+SC0|4BY<;і#$Oh1߽JxB !6*\ lV"c"jQ=7MMM(ʟڲ9%Wg'I8hx*;3ū1ķ`%\Łқ&CH_N%R*^oeqhGs!=CGY? Ώx֠1ݰøtRqQ-$3>4()kͷ~˾=ݕ7HVpa]=n"%! Z$$ܤS$hN:o/GVG!I?փ;4;_0qޛK"RK[?r."m݆f(* Z*3&:PIT2F(' o?اйk;LbNKRTUN'N$@4 <^;+ p2DU V*V4SW`d_TF-|h R|(QXTBRZVW^IHHT]TNB-&#yCU{YN=K[`*XG0J΅3,(P#0>ILYicbb@ddW|+&SVdO^F  cm,PVZX^/Z6X^`gmg^@/$Lcq[yG3=XY2ejnkhkominecqdg-jh gmgijmhaRsVjnqo;nkmnpmqSqJrqyjQOc UQpY7,ySbE+VY[3XZ+inn'mh`ihgHaNQTj;fYL+{:^\$\a\]^"fFeVIQ`a~e\KR?   f/hK%$?Z?Kv%3(W $F$:&E"#^1;M09WUJ&pLj̣^~ɶx]Þ_eşǢɿ, 뚽SƗbk!C壜Ɵ.6(Ɲv] 'pgkvY#+㍵Yxx)p xւ|돿GxZɽ' T֨LY|~fH 5"S⩤v\U΁SȺJfХfw32.{$K QR- |ֳ μɝ ?0ʃGuDF+s+ROG()c&KB% Ԋ9Ѯߠ\\89?n/`6ScLL`殚źr˃1&ļ̵ƬѴΦxDьŋ1εiGC|+ĩ*N !j 8*H ?K9&iܢ8tΉ5ӭ(?/U<!d:5O?T7z*8m뼒ɫɫf)w,*OgNFU@hnV $|Fu}?Ș*4Ⱥ>BJ-4F/vw%N)> 2GUR: #ue+R{' ;|B*dBNI#\φ4ʓ'ۗzG$U BE7"%,yу<7L*X-\T20  +c6-E , 8JAlQcS1951\=d5UIVIPYJk3 0I#PV4 UR+ 1CT&dF:~7 5MKG A%j ^0Ћn:q[*Lȏe$q VStMΣQୋW{F/LIY>*Dƞ-}Xj0\N? ]FPQp/Y մ<ć_ſԕkb_R5MĞ^[U n軡ɷ(Dkǻ[ IЫ7@ߌt~J[=Ƞdܮ^~ ߿5CYÏg߹Τ)Z;Oպ$ {=)<;2ٹɭg6 ͤϼղW׾[ vytW"/;(u'!L؈2zAD=)!4 324LJ0< FKK $'@,;#\*"3 K+=@FFv?BWeXA;*6 24K$ki.)Ԟ-Pe5:dIOUdgZjoYptCqV;J59Sh3[0d#*%-lKX<|jDGZ20. L(ߋUU],4,(%cjM:b,;{R!@=̢F[KǞ%HhD9BAoגc쒍P&ϐÉ%wpNAؐډ^ʀ 5V.W5ϞОn%x nԠc҅ƅ M~K:%$98;CL8L/I<  *#fсMg /O%th#9e"&)t# Yσr:> &)ALYAc .YK|: |/f0Y#]b BZ/)&Ex`bf07ݧL| UZH`b\QL O4?6'{|BKNpP0B,@L_[,a5ad cH[ [+b][SR4LT?>AA7.V3;:/I WiqBmBalYQ2AKql\NGX7bU=61#-J&jnwt|7Z8Bb}n FMJo]plllY^[udlMJR?#;cD:=+):J3p{x{qh{}u1vjl~7s@}l\_fSll`YUO~krwhlyy6eVBhuft~$~HfXDefFXZlmbq0||w|j{jKf6 ]<6)DUvM{K[j`\Ltxwr{|u(w0k}U{Tyrd[t]h{9)px\S[\VP5.e\sxzt|4~lZB?Ugeld(Yz0W&axlxk5]PQqzkwklF<-`,r^D??0xl _ ' _ʰG֪_ APK }#2=u (!0 nC\9ܪ\-ΦR(>(*-o) '0K81%KԒوԷ6k܋' [a$Z} !s%y RDJ̆ǶC~Kߎ$.<Hs>,jpLHË 3٣ B{^ڷƲFӠe,ߕPgy{S<+&h+d ! _7.<2106|8A7FKNK'oiqWղ׆VΤ 'RN Kg.8@89*jYR+ =(G73Դ4nܸcƞXPѩϤճZUE u ԂHjت=,8܊KݹsePZ+-M" dzGHѤi4-3d m )#Q;yS s ANAai '򧮶Z ]AƺAÜ3d 'Ըu/W߳v-{ȟZ3>=iނG_;<  dx!vaʨsj|ֺҪ ~۟rT#@2*IՌɶ ̞"bOo^O52d٪ɢ+Ȼ)й]ףQޡ-#\"p@LfKwGA94."3?y<#'-m:8IKT_ik%f[PeNQ:NAI54388: ANZ_D^(V^I1>@UbR#_$r$ J2 O w t$$(?VX?E:B/I$B09Q ݮaB b6JT~_Akm?h[B#=db =:;%$!$/N=]=&7S83/..$X #Wg .>BZ9<5M:6]*&,m) }  a ;G(B+ 't/'{H@  `)aa~5\ȖZDxb h]wܧsԳތ>d%ADs(/,  )V2i>KPI=z>$H7D7R10;+4{ (:M6/d5:. Q-->/^8>"8D@?HOKqC6)3 $Xl;'GAMMG??A <0"\^,62//3k5B5>JRJJYycVDFEYJ1F;-AI܌|d r&(q `Q|"d, T   _ 8- 7k> ED<9K;837- '"UW3+?'==lENfX`a\SLGB2;4,-#&H5?>BZF^JT_KbZap`[cCf^QIK7V"[#VQI<4.)%"$*,*,J0139;.m'5B9F751h2E?A0W1< "6:x1-*.0' ?"*/B8#ByAA0HJJdF`=5t43b( kl"*m- .)%)13{-)$ e֢$Su z y EZs\zal "!/++'(&O6M  ?{h~XoIU*-&Z(uۓߕKʗџn߹{\K #,nA1Rj-#]9@ fk A  Z  > /@kE@ Q}LP .J-?ɾşa+&ktݮĀ(󼟿I!uæ6~qՆzψi>à"ϘT S4DДi\<`*7%dի[ޖ|ݏpۥh$f:ٸޠאDs4Y{ڰbUI  *KH>2k 6  Q .    btټEz`9 = < T *h(B5p86`VK"}tU"עw˻ Ĺ%a\&ݢ=iVpАem#7#jl 8IY r!2YN &Q(" 4! UQ.)KDR3M/_FܙӃ 8R9f#?iG={gkM 3ni:xf$  Tq2{!"'/1g/0'3v+( F82Eu˼ȐϚٰ&#  lMqm۔, &cOw"%5&"kG$(*|2=A@^?g?@#BB@>>==?<744C6709; ?ERHFCBA?=^><7d2e-C*(*&0wmt: t$#H]k5~l3`~ޭ!\~k^ JA5׶"هCܩ]tT*U2Œ, ьO@9   9{׺Wt|^.gL;3K VIfof)Uޘҝ̵0ƹ’̈́ёة^64=RL : $(C;gg>CE%H-Su!6 v tN&W&!(:[nV d=S @Y 8`!۪-~gQ)$e,|^ bVe@ $VO1 'DZZzzbeC  YAc+L 2Wc"#!! %$B W"!hc P e ## IU ` =LN,qo W7x&fty?.d5 `!*115p2/,'%! N 1% O fri'/848h>B}Ca?P;9.6- #f#$l~"-&k$"!;('g oQ lY [y[ӈ=U6<_bS b,J߃F۾&`fz3Sڢ3|AcAVI؜ع66ۅfG''jq^=<`}B" w0!#9&1) *<($n$19F;:A964320W-a,.u125gN 39U ;ަYIߗ`WvJ" I JN 7%* " 6jFrd)j ;)lAі}Ԗُ^ܴ @ B[4~܂}Qi|FMuNC*-lx׉ᳩ}'󲅵:]LLf 'pN*\×@̆UςI2<@%߬~|5A1˘лb/%g֡ jz˵ʆFؑۊN "y_QEb1lOn5 A mb+f j:cnhLy}jS_)o  k a W$1 _HRn'Y167736750g'0S&*c'!!U+n44=/b*&wU O"#A }|^ en m)8j+ '  Zz7  L3\ "k r /J r2;>O/ 7 z : 9f[iX.9gBJb:  *rg!$#U#&<*),%!# &?& &(w+(z mw-,|  66 p&~ d / ?}(//..(i<u DHi/r d>b,!# oy _i Q k2}*޸8jJۯ}߁ $N~XM E|=4c+@ۂٯ֙L{UsrSA| @ x , 0H9]b %)'&)%07h:1;:q8_2+((&!kk} #&)K(!h,~B:  * i 2 q d< !*`pzb   /J)-N}tMG 4uyIn۩KbBIG;[7  Q  u  =U: \sS'II? oW߱;0߮3+"(83FB^& \g >   s $B">,W O (Lg ` }kG|8jUdHsn~[o0Rpw!aו}Bٲ׵sjև$N}do ٰګԪFp'r45ܭFUk + F * @z(W7KpmIODaMx=$!cN'0 aMo5 ESzid֜ <֡a''Dݥۢ9+nԝ٩۵7.sq d})\e?[O4N% =  v Q L[ ^p l R1 +z50 Q?/_F4nl 24[F,"T f!">;n-#(]+,+.'1M20,_'  8 }ReyKC eH K % PZ; : ZrCX"2%!s ]~`Ab SN@RR )&j { DpqZ.LN9hOG'K^~ f?Q/K} Uw݃ҚΊlR93 lv)J:Z=G'A8; T4n=҂бTԾb7i;pAݐ p5јf נo1֣{y!f,~9p،pq٢>\/'9ޱ֑bԨٳC٥xXөѦ-Ӡ/:սnjz,~VP['E}  #% V x  @ t~| u U J VaA$&'}&&&% q?D.; #&(/,d.-*:&"";&4(m&e$%f(=& &_/22X4:?:?@r@ZADHK(MmN$ON~MKHC=73.t*(L*,,+9+M,,(,7+!+*)'&%#R ~ C  hs7  H @ I 3^l >g7t"'(#~?$#p   * 7 gx!`c!3H_. cQ9F`ge@i4Ub}EEfAiYm=_ U}8Y8.HM.߭ݤ۲Jէҽѓӻ֤ي L(|h '^WHߪ/]:{Qr]<53Mm(+bjV[ܴ܉ߕޠ> V3%AA!/:nW l %A ^  @;M_ / {woS]YiOzRl[  Y1b;3)`hA? { Vi x=de. J S<B;"  x ]p%H\h`Wf:"5),fIfg@ew > O [U3D{ MkgBlg){ޠh9Ri)Ebc";  _]( Q #2;y ai0gOc)!(.޷xxRsTu@W{c!QxQByQ+4s.VjqV2v,KgR0 $?  T A  !zDY :%Wkmjk - 1 ! xCa6uBq2I@fwg@)f h <07Yx x qUZ / <./:%a G:c*L c 8 2[AG@x~ &   }u h/ v [v}uB#" 4  k9 `v  V#2LHy%t&a\ 8 [  f } L@}|+po^!A>"l X  BN A Z ~PE@ N l$Y- s|EaA_  d8OF@% w ] - ; Ecz34/D`9N;dBJ3'mV?dK[ZhCI""9r,6on-i;M[FOTK/$T\qh uZ / 3_hwKs63.4QZ=PBk 1ykIWuwdCU O w zv Ea0R@ZA $d * 1"O& \q v % * 7 K _ 2 5 = ur"[?X`r> n!!hd Y  jr.   ]   / 5W d Ob:E% W VmZ/ZPRV;GE~cO*M5.iD'Z1_uBb`$}XaE)nߛےݣVnc9'H[y9V|mCH(Xwah]J|+-9yzPe. d}* (vHw%G6?rW|j2WKh$G~wLH+2`},A@4L}Q b kc'Y.bo/h- d? Dbd  o>""W#3 (32j ,kE*D/F nm7I.RS vS*-*-49@~2_Eg-s7B E g  v !  Gp>1H) [  nY ,pN~A+lT@(oaTy0WM[Kkua17>o t XJ 2P@6B ;F$zv(h3OSq?< f#yG b8OeTS ) mz+scMaf!,^]R<.AzG6=>JTY 4 : s] oBI ) V * 99q ZIgs<0, p]w?XekzX S S B 7 q k  S $8rS^:MML\jnNMUK_F>R.5[qZRj9MnF %C'?mX   F& +\>\!;t`B>84s\:8Q&@ ] h Yk0{w O   7 B & n 5K0 (r: k 5" /3ky Y O~Uk "Fa$U C < J [ qSk6!kMI352%nqf? #  = 7 SK  f  ^ s A 4 w !YKy~!/#ZIYrz]a}) N  T`j # I^eC 8 o -v<t;zz(lUsbU2?&:9uzk}p_p D  $  C@^kR`<\k!(HR,-+q,P/7JBjDBS1t;RH'Su'Yq&fz; qr| z1;8o8['X&8YMC}zV~,w@'T1=T 9 lYa<";C`/ fH+U51c1'W4] k#j-6YCggvlG'. U3jrC;|j  ^ Y ` C ) & @ , " k  5a<s'&g.g}8Ds3gPW$ctkll{?qU{ Z/a!RPvD30`U^1{&C{{_&)_ ` H<z|i02&AjVBT'V+$I tbzKsf_#1&=xA/tlxqjG\ tH2XD2e~2= 2 $JdV8%!GJA+'gZV!*&O"cK(4gx9\*^ $9lqH><(xYM CGTf'.^RlPgBr t 0 )[S .  C   0 sC*N A ) @ 2 R _  ~m!.ozEO4  T T  :CM T $h7She/TeFeG`?)&sw/ 0 ] w +  Y N # M s F ^ P   Z Xk]&5pgcBHh"vf']HnOMmTn`bI C i + k_7r+bjk)&7'2,>~n!3JHKbvWq  %  i v  { R b9G2CkH2S2slnjbc}qjUu]B4HTw6Sk1^ 0WJ6 H.v?%uM#R]}5>6{   mS-fgcmuF;v47fJdnyY%)dl jWo2Qu7@4T!)vE6f^[3 Wdt[ \)]*-v<;"-;;3<K'|q8D[#uT>t* W}XCX ,fV^nX!PA0wRQwx|aM t{=3+ &5nUkiz /"2<P.Q-WC@, L`H5?T d3?%c[-|UF=jq~SSL|JTa@wk]pFF=cqo5IYS[: }'kwCzo`G dSWlQ2RJ[y(3<]'m-^'P:VCrgQNiT =p+#kFZ[a5g VsA U"C/#QBP)A>:-\n^;x!5 jSnvsjtnP?NH`}_vG*L^*)sWea iyE[$ I JVr 9"!  | W&1uqh{$d2EN"yLW0J ?^CCR}:<~7!ho1wqf^G^3;v$d/ie`a0.5uD1<Vi[!xO}K6 t7WTbZ40fVg9 8l~B%_flRrge$b?QfHH;RJUI3iGY -s J k 5t]cIQgaM1j}R8 /?TXD#Kr/c{J<wW EI!0sVXV0'f*'g*  3NN\2K8&/;/"3bSkQGA( K}~|ljt^Y}=! "5Nw@LC4 (] | I0 wt ?fZF{s9TEeG"';/unQdr.[XA\]r^alhf|36.1B;V\% ,;C N|%7ndR4f ?Iw!nKF"Gxskm8IzghGAB7dX&0f"iTU^CtgLxPm?D90y X I*z ,.M|+QccT.j.~x"jG5<_XOdpK0KS+\wn L`^luy[=4=ChO|tp%>k(N ;]u;l~]PHL%=5DuJf%6g.PEw[8QNb.$""5e-Q U.k.G4]b Xy;_QL?1:XplKa3 qO|vT.x ]iT8CA3|WF1O~)v@iN\{rdFSV^n}rO:Rxj|  ?3/-?<@Rm|xb4]>xf3aBdk$.d=x}k~W]2^znQJp~yf+fRq!W8HB=Od^EB^se<d)6 |M'[+|T&|_QW~ @j_*DOC)";n#YT>:F^[~d4#6NVLIRK, +FbwSlu4 Ck">b~pcSE7n8n[3N_KC4GbhcagiYB@Y )aXNw{niqzP- -ZW"rcU.W-ygt$Db"=[M[#iS?Yqzq6&RbBsX@." <cpx%&-:AH_:Sg}[6vyk8JgK){k_H& ^?-pO\{1u .g6Wjr|t{{]4!#`2kEnQGJH><=*h$BVTTdjW8m?+xK @aMB( '.Wtc R )<Vd_[g~iRRF"xVf-uUFJa #TGd/Z/_}OHav}Y&1Di)ov "8?GU_V77c=HKQ\jtqK4A1 .2#,@JPWU9LuODMVYbmd@`. # DgK&2CeS]e- `@/kM8!b0 &575?Wr6Xl  771@QC~`6r/O"<6q4GTf~#u''5YwzujH--=A+",56$]HC-`D ;h>1RpxdAwZNC2rKGJ@695aLNL8,NlI'J~Np| 2f '%IQ&pxyRa|U@=AGOWZXZiz~vt%@JK]y $X mG'xN/MX!]NOG3-Dg.=N~6l7:7@RZ\bjdO6 k^N/^H6"qZF8- Dcz-^%@RdvtP&wYE%i0VGex%>HUkz *" .LYj/DJKKB+ }p^;  $;D6 9LU[clquz7\ni^`m~i@*@sXSVMBW 5i$ +Nks/Y{iCze`juz{{ncM$  $):Tht Ffw Jb$sJ( lZ@$b=Y5a=n'$#7;/1GR?&%-&rN5mUA%n7hJ:2%&-$(N+Wo3@Om '*2D:$ # mC{xsvut'XZKoEk/83)(%aR?~iP='y?zx!8KZhw .Yh]UUM5hVSP> 4.,9FUer| 6o    tnqn]MIOJ0|mU3piskP:2,),1*2NTMHJTdu$IW[q"X & vh[7ob^[R?w>%+0,:[y$:KPS\fntyvlehi]H9:CILUicPOH+ npeK<<0{m'Q|7t0CZv 3JPNQ[l~gB+$ rbI_*qcS/-7Q} 4Pt 1b yhO8* uaJ+ynnngYI9+!&?_)Z-\&W{kT<(W;# ^D:!cF#>HKV^^aq}|7A@Qu~xeUF0%nO"}plsDVYd#4:ALXeq~mfpoL,wlaUC, %-4;@BCGSl:UeupS.~sz~qZMNRSUVV^o .FNSZZM8'$;Zq|f[`cS>9BB.wzwh\ZZWU[htxz 5Mbosog\I2" xV<1/(jXUSH808Qu1\t|}'` .VLu[/}GmWJC<.!4G[hny&2AWs /6. )8??>2(yutndZUN>+ qcM3$).%(Hbp}4g4P`fr($/=1fI. iO8%!#*=MLDK]dak5EXx}eUK>*zhYNE64OXU[u(EZkz|wx|weU[o}}qf[SQNGEHKD2 sWE@=:?KU[fyu]R[_I/+=HDEVju{lc`W>  &=Qbu!),.4?KYk~wopplll_K?5zuqmjeXHB@3 (>Wcdgv(25>NXSGIYd`X_tynoz~qcS@(v_G* lgc][_is}3LeCu0GYh{ $9JOG@AC=7;C@3'[3uomV$oL9/"  'Ca =U^ev 0>Po{rjdb`[XWO9kYOB&Z>4.{{0GUgD`r +H\rlO3hE$kTHA90*(#!2K^`]gz~y   rXOOG;FH<%x^C-|nimz#&,6>=63>Rhv~{Z9 r`USPR]p}~ 2Wq}#6BNVSE;95) `LC9'vc]befp!1?FIMRXcr~tf^ZP?2/)~X;+~}}~zngsE;k!BNSh|fI6+U9) xR( pYONQV]dcZT[c^Wat !@]r3NcpzqR?91! {aF$g^ejdXU\dhn>_y>f/5:Lm^0nYC){uqhVA0'"0:AJVdt!1CVgy|umaWV[[Q?- rYH>3$ "25)dJ6{bXP>&! $8IZgmr!*:O`hpm_ZTC+qfedYF:8985/$1BJQ]kojkw 'C\t  '*)(,56&wp]=~ 4Qdmy}vk\G0 oR9* !3K^immv#-8J_ousqrqlebb\K9366-!1FR]p^;[<-uof^ap)G_y;Vg{B^r}|vqsz~tkc^[_ggV='qWC3jRB82-'&:Xw"Hf"  wiS:%|eVG2 "3Ga~)5Gr8IQ[k|pXK?+}_<p`_iiO*%-17CUl"6Malpsuqjit}{xsqu}}tcVXaaS@.{vtqljh]OGGD<9CS^a`es%5?Mbv  "pX=#yofa`bgox"+37980(*6AGKLC5-040' qkdQ;-+..) %*),7I[iv 0Wjh`al{thifO2&,-  ,9ABAFSanuzz{zm\J:,o\H1 #5FZr1Je :Ylt{wkZI=83)v`J5) vaTK9 #2Kj4PdttaQ?( zeSB5(    ,;JYm7Qi 1:==AGLJB;93 fH&|k_TE2)>O`v"+4877<CHKMRX[WNC=@KUUJ9,&$ {jc`]\_dgfdgq{$.:FNU]kuyy|~rjaVI>5* ''%-<A=>KYbhqy}}~zvy|wpopeSD:*~q]QPNGFLQONTagdbm~';KU]hxqaUSTK;49?=70}vqt%*4DONIJRXWSUZZSLIDBEHA2'$ wbG4* !4Ja}(Hax 2FRVY^ekorqmgaYL<1' n\J2|aF-1Pcs3[{+GZj}raQB.gJ1jG2$  4Rlz3ADCEKQTUQG>>A?:=IPF,r`QLS\`\RLMPU\j1H\kx (;<67<7+$(+& zsbI0vvvlXD91$,=GP_ox-D]r  }qfR4vkefijgefkuQW-Group-ktx-d05d6ca/resources/example-configs/ktx/vip_ip.cfg000066400000000000000000000007261475442401000243050ustar00rootroot00000000000000// IP BASED VIP // // 1 - normal VIP (default) // 2 - not kickable VIP by elected admins // 4 - VIP with admin rights // 8 - VIP with demo admin rights // 16 - VIP with judge rights // 32 - VIP with rcon admin rights // // examples: // vip_addip 1.2.3.4 2 = not kickable VIP // vip_addip 1.2.3.4 6 = not kickable VIP with admin rights // vip_addip 1.2.3.4 63 = VIP with all permissions // vip_password "vip-pw1 vip-pw2" // vip_values "6 1 " QW-Group-ktx-d05d6ca/resources/example-configs/port1000066400000000000000000000001631475442401000225130ustar00rootroot00000000000000#!/bin/sh while true ; do ./mvdsv -game ktx -port 28001 +logrcon +logplayers +exec port1.cfg done #end of script QW-Group-ktx-d05d6ca/resources/example-configs/port2000066400000000000000000000001631475442401000225140ustar00rootroot00000000000000#!/bin/sh while true ; do ./mvdsv -game ktx -port 28002 +logrcon +logplayers +exec port2.cfg done #end of script QW-Group-ktx-d05d6ca/resources/example-configs/port3000066400000000000000000000001631475442401000225150ustar00rootroot00000000000000#!/bin/sh while true ; do ./mvdsv -game ktx -port 28003 +logrcon +logplayers +exec port3.cfg done #end of script QW-Group-ktx-d05d6ca/resources/example-configs/portffa000066400000000000000000000001721475442401000231070ustar00rootroot00000000000000#!/bin/sh while true ; do ./mvdsv -game ffa -port 27500 +logrcon +logplayers +exec ffa.cfg +map dm2 done #end of script QW-Group-ktx-d05d6ca/resources/example-configs/servers000066400000000000000000000001771475442401000231440ustar00rootroot00000000000000#!/bin/bash ./port1 > /dev/null & sleep 1 ./port2 > /dev/null & sleep 1 ./port3 > /dev/null & sleep 1 ./portffa > /dev/null & QW-Group-ktx-d05d6ca/resources/extralog/000077500000000000000000000000001475442401000202675ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/extralog/ktxlog_0.1.xsd000066400000000000000000000106501475442401000226770ustar00rootroot00000000000000 QW-Group-ktx-d05d6ca/resources/logo/000077500000000000000000000000001475442401000174025ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/resources/logo/ktx.png000066400000000000000000002301411475442401000207170ustar00rootroot00000000000000PNG  IHDRG~bsBIT|d_zTXtRaw profile type APP1JOK-LV((OIRc.KKD 04006F@9T(Y)Oh-، IDATxy$uYo7.  5@$QDJ(ybҲ;B3&?ƢO8&<%%q@ FW`ktՒsdV-Ux\nʮw=ᄏ9FI=;݇vIIIIII;Z#nu }Oѧ| ;ڙ!P.iAeȲ,feBRҊ4ƼӨ '`"r;ܥ (ә9Zyx"mcRRRRڔg8ZViyIIII\߰4K ?*dY~4] нL()c;8x gp8yezv;}Y$%mٙc|֣8ӝIN咛occcV%MI")IG3Pvw_)\1[qkoóz p&۸j s=[t;Nvؙk&О ˌ; xt!xo @Z <5t,P)*aMLt ̽03c߰zn1OMcϾi</x3Ca{`<ҋsg1eKo Nw]Ƒ.՝zϖ֑گ)O",V0:`t }p>[ /YEvP0҇f )TP9uqgmpkܹ^ :cxqzqqIʙ9V sߒFOgee69IIF!X*Cgnྌ3{[<vCg']ɻtSФR ˘X^~'^8Ñ xj>Ǒ{H7Y @.+%Er* o?Atss!>) ?py'?` n>@ ég3<ͿEoɡh3n p0}eT a> grLbzk-#sB;-[/g8od@=l5}K>8p`vbb"T@^3\-st(!tp atrN7r7wMdxX̿j]ΨK@e$ˆSZ(1rc19^vK9^KT-/.߇s'pO 8fYU4$:A0zǁo$?=>: F.9lCUS9ȁI 2*06Qm\Ůߍc8vnO-N+i&J%ҩul:NˑOg8{q77x1߲,Ta2L`4i7rfJ, @"@)l].;6-i:Ф$cʰ嵘O Kf\5zb7;׃]Xvq=89?#/8 δ"^ٹ}ʝPjs0-iUϵNY9)],9K$ӭўsh^?)AWZ|%-}џ3pIE]f؞^[ӤɁVeIj(ep6?n-f P,,0/pC= pf_DgÌ4*L9Wh[֝s 8`Zi1 haB0NI#Yd2Z|'edu{ۯgp{ΊWޏS̼q8F-M4J'aA!z~+$0:S>g̣_xEd wC˰t)L4 |e4eZEe{LOZ6.¢8!G8eF-e1Yy |nu}E*sle *;}ܷ4 w>̽ /xZORej%mL8¸#JYbrEsk@E1wqaq- N0C8m2[Ʃ;v)9I#z65_/x&ǂ: [P>f8wc@{ C?3xT#3y{٢` Ψ}pI=uj1ULo^o0i imV΄Ao:C6k].(:]`~vnqn~_qvg /lywII-)466qGMy(0e:0:>c/:mI8gL'eH74RW)j%rA9#R0Y-?Z99\'77?콁p >QC=̳@{ޢg`rF;v0=NI[<@h)cx L{Ytۗu[a۰-M?ŹG c Ό/[JK4r^8MTviP{z}ww r>oO^C>#38 FK*r`NuF@J0gH9~+%Filaxk`-vKL81NOf8/)i&aTiX5}Kzv;~9|(sQx`3/0ƦWG ٘ѧ3x&ܫFF6u0BM ;ݑ y3 0b\1 ߇=t~q /w`/t1 tމEr@vR23`0:P/v5 Msȏ0:6c\~1q-6xHdX,0}wv;˰O6*B<9|:JVN'rMLfؿ|1\oo 33ϖL SqD[΢9aR X1%0&%%*幞'Q"9=^[:Co١gsǘXn?W`{3%ޅ\|_cu|߭ኸO4=YM3v2R}sEuh xZT]QU}bg2Fo&' gN;mvlpF^ZO ` ;kVft  ƾ0=Um7\?G~#`kc?w][p$:\8]勞J+m3#Mok %MJJM9+7TM 猶/x }dvF,::ݮQ p+U@hzW5O/oM&{ؚ \wS7:6Nx|,+b=\"Ĵ9+g9O[|a!{ca `+::K 6\'W%Ԏ$NfS2õrQ]Wpj ٞsd]e{ -㞳j? w>Hlhİ_<089%m(#2i **!T/HorA*mFat|/7 ~cG 'OdxLβCo\Z@۠Y/a&;OS{{vZ , cUx?(Aa,Kg}.FAt d~!Pxhs p'Mzxt s}YgBY0c'L×iV]Ju@|?QU,;̰)[+| hQTdmi1!`yH>9Gk>2 x2*9MJJAF=.0 w5%wj!4वH{ 8H>|'w燁ON=n8[;Wͩ;pkMS31n:fl~6]X̟Sf{fw<00?=N0οo(۳>ᗓw2Q1d=5p1+Sgo |:` ApᄁAV}\|j PXW,\:ݖ$: %.g q5|0Hǐ(߯<,+pqi*Ca{v.mlYzmZ/ّ?5~O,Gh<2@3gTR~BI IG N QH4)|I^S9Ṟ@xN;Me@VEzܪ.yHieS'&haQ}!~f Xm\rC dp,+$׌8a @34nP,w(WuT;5zj{q(oRR/ix \fmx XF?]:/4xR] hOPpJg&ҥ'fBV,MJJJxH-@u4Z;Gpk2xr{jǖ&S,kN9ͩ9KY5궈2|X;䇌+cDŽB9p<qc~;I',t.hf v7Uv7mGV9aZKZtH;K4zpspsE+>H^SЪKZs0H`J̍ az>EyABcZ=wPBܮ#Φ}%&CcqmuG–`Gn3z(qx2qM=:jQ~Z7]Sr6ܖhp:}'6T` J3xus %\[.B? ^F|(iP~X5}UP;)ײ `tiYf}equ+o(66>^V/x++*zF : ek` 0H; JLDZ)IVC2jP uC( ˶=]CexLџe#TGTmS ୁNߩaXsXTxr۸Ns~'5'LY!]xxFxe <7Qq2T3Mv՝a0m)=J6Bj/wtmO^y xVjOgkOCqyLpc3!Sg@Q×}[k`Xq?i$_ z(@,l_CgӊJ$ه|HZkO=RM 0|K|Vm[ j)m1f\,F,<~G xrX*Ы'/7iG ! AjK%rPe0jOnsIk੗3\ WO1k ;hh44FI8gN4EH ?#,78cMQ:/T`U,yZ^ĵ.E~4b@} FfRQk3Q:s΢ϡdPmK>yez?&`-W*^+[>H|EPSaeϷh(Pi:XI'տ .IB$VWPlF+*;hV+CDrNBȮtP=N>nV0hr BjOF脀km?҆\Uԣ`Z3x+j3(TP@BZ8 RA0_ܷߙ2egjR;fUT_. B㺴Y pl@Tf@&,t~$S 6qFj5UuKTe}g7eRL5jSD`2@wl!$4))iG y!T Pu:Oߺ zH_`Pjg} Q9 %tKJ[x ^Hܰ\tvtɹTC䒲:^\W(?]>׆༼W}Q1cG|5js5%MJJMi(e*~jTϤT$)z<,|8LQPq֗+E yST`,,?H^kO S\k?6٫FS}^gu7]=bcc di&SiA i@f3 |i)'1v7BAT!\pJ)%.6r\q;/V#!yp;~r I`(Iug=sxsg;v$xnAsYPr}aLffBDiq B>lM(I>v|?uBeϛr>^A)K/-p-dsz dz2"Sxj,\Y&ϙUZx[`s}6 : xtI&Z^s;5x~]nX_W/'b\Q <}c<  ̦ФQS!N-ʔN(#"ReC\ut8ÒzGG]>ԬF3j_bgw}|fqzۯwo:GSç@԰O]h5e(# <׼p8xXq {c$-4a,+4RR7Zh9`S7NuP,tl aD<G %3#;/Ł8#O<5  oot"tڍ0۠vyת{~ sg \s""CL8gQQr\gV7Sٌ (on G23I3jn Te9|7:20R<%2;P 4r%ԡn>Pi[iOlIz''΁swL@m^A5y5h<Co_h\s3`C~-'9III# RP]$ MCe=.;*K(@LXv.|*j S_muoN@%Ֆ ڦipѠ6޷gжߚc s/5xӜO)JOy<a%1㾟$E]"`{-xO~Pȕ-F?W9mtmn`.\0jTiدT~o:S4SurpC@ Z TB:ԮzT.f>b:*@ZO=`GJ /8xO{>1/0òO9 f)2,z㈫ꀻ><&޿IϠ'/8VЁ ੥ЁPQ̌Gyd:8+i+B2KO.X :YJ!{7iuU6h%֍?*a(>IP)@@O>uorOw@ 08;_ >)\B@nU`Z蟺(sMAnt^2.>90\p5B.E+ \`5_9V`%ךxz? <jVf՟}=mdX5}iE'=LFuέB(s*G"뛵 9dA(*y›o*x wTϵӴX~:.jm:xY7ܫQX ; Σ_ҵ⯗ GS PO7!{罹mx+Z.xP㿷!Sf9XhyzOBܱ/m?)mQ! T;*v@up:~>qrj3ȔC7)M9Uށn&]M~Wk%dT$P %x:pl$n(OUY~M0(=[;alz<}VrS8N4itY.S<<[|0+f?6QA5)6x{LQ}:jmTq?U0Nƾ1 4g{)-}=X<-`4LOSq: y;ѧc#5>f $[;Vaw!7# `L*Ͷ'k":*r_M稺^ 9%,/ ׂт+a-B꒒ #ݙ3.3fr~*pxd-ٴlھ^(ˁ?5?†h|R6^7V 3?ؘuϖC .9p&\ D~@( e# 濝[֟4ܯϙ ) >ٝ1ȝa[hIFI17Qk{ִJ x9~3c8 oEzEk  Uheh4f0|?=y>_NohMh+|ʺo+kU_/T.\JOtΛuwEDnqe}.0;wetø\:F`m"5()^.Tǃzi^;(UwROqzH~U_O#ᩬ O80| ~FCց^8ZW6k<~ӲB[x6?>1RX7D Z84Ny/8) Xݥt<+Mقp㏰ veW/.0=_oI㎻,{ ˲}oPdYɏ|#-E˻q/(+y.~4 <%c 6xV+;ϋ6KVr)^7pe~&=f: m p\XfP( ZϚ΂ml fg^dߴxV8I5pǦtB|a90 ,/3 #  #w~h|[gԲGs:A9 '0Sw+eVrUܷ(ݮnccc2L* gx|3;۳ymC Ļ#q[ KaR;iyt?*t0YpPL .RK*#Wo:T/2I@5o\e4 j@.ĵ!vU֤,x 4(x,lAAlBg52b;xOT3lDi~曝aL,B\g\c;`]?]2xU&ͽ>^s$F1CdmmLHII)","@w{FOW"*uƘO'!c*П-@Z-nnU}]_Ԕ#hBi@i0iQmw0&igWZiNjTe5+5"Es(Gku,0oBD`) (2s*԰~X' EҭlT gA%drxr| "ڢt.n}jr1_t2Ї w.1p@:qᔄ=3<;#琀gMJҮGsݯ5\RΠGjI,"|jiJ|m$Ɛ|؆F&؍2C>\o׿)K?2j0e"9vv$p.dԐ)vOhwpQߞmұec6%α>XZZ՝TѠ%??q;?3S/?5.lfYaJB4>04)*|՗ۊ<E4%jVf׹iՀAtԝO3aΡl,3Db#B|7_(G~@×eQOS IDAT)/Q, {hף\T"~'!T@X,A GR3!كoC h$WQqk^8jqík/ɴY <J,G?b_3@dH4s{nƦ>d)Z¿t3球'@ c&mBb%f'"cd`t(`#uj C.Q.!P@ Z2*;"B l,*}`G7mm8#&7@RNNfK5L)1<JdVYߚ0'7n맧C]b9ߔWK0ud!O?+^-OQah\ޔX>澭An:ux]sFϗvZB8 N NtXKWȃU+,aa˛V=_Sn:,(P20+Jw\*qBygq$2`RlHa:NׅJdf:'hg)>hm&x6i__wKFU^g38h,31OTʯ}r/p&7=xcSv:is[Q`zH=AEByyBrx",U6I*NJoE`9\uPfcf[",I>8?Bc{~3xk3k[Uʪu]2gF<E۝=z)M xB'w}׬+{ r>T+As]uf`1l"nGf5V]J.$Cw=5"s_vyh:W.(i7Tj\AIzu5`kM\JJy 4p)hˆx.e&Vq9|8h)˳7ff3^h%Ekl|Y?d4 xu}F xn>9๖6R}*NtbIIIISzpJ"@O(kJҡٌnPû"1`sNYFSٖ -o՟SI ;MvVs\b,؆Gj}~g#era fa/3=4j4pn>!8fxV4rv 69&?Oe8pB6?,rZ?F>/{O?}bN)a9x&0 Bc4L99O)Ye+r>w[^SI,8 A-d&?ّe5B]b68@%tߪČd|P)P̮$]: IwGЦrO۠ b-dK(cHy+h9O\'njh2.dw~祡Rq9ڛip<Acwx}('Ȕ5,4i?:UilO-򉥣O?ZNgs34F769ܬOFrkq`ϱV6r<~L7WStޟb+w2. P:Zֲz5kncT+a%}[K*n:b]^ Ǝ[5}[MozM%k?/v0"v,@HR( aq(<0B"aJP hpT+FjSoS_3I۩RzX'CDC%Jdd;>|\i @_ ~O=>6x~ktZ?ߧ0;ğޑ6t,^?xx4}]*ɺr@W#혰 ,Z~K9qmym/|Jt[ 1$/t4lS\ƨo >:^{D.:Sx[zÝ'zaՀAZ!U_ns%&sߢ'ɐFv9k*_"JԠ)\nN y| T )K;@`0pRϓf3ET xROJ¬K!?3/#dUZ-Y$|f^< Y⃿4Cykf%EG zs9et0xJ_}UE[%} f> @.pΟ.ع8>|2?}}`O xU3'noLPLQ%4?qϏ4 }N/[8Zel֛9&UBڍTgg `|3rt7#v{l;j/_CɴƴE~zHa\.ǔ9LPI(7H'gj_'eUSOq= 'Jɺzh^uݖAhisad1H@.>7BΖq9:<.x% _q<5KQJ7#:3/7xͼ'&#cuw<vce]|xS1:MJJaqMqDeZXYJ4gX\LА\• %fhh+#yp͍!D} sQj|gRP50rW7; Dep< af# v.|ηNvp~b}vY$.Ng=4t#Fh+,mIN2b]r[\9@B GY]_v mDdzi՞?>ܴuMY)u#fC*Q\^LhRRIGF w|QrA;>Dk#p\)^)#T)y:gMG){KA P DMzD@OCa(Z:p+ 1clRJ`يc<7r<[߀Y6s3L_ɚ69C6:39kp<}ɮ B_RIIIIQo[.8G0(r \ ]UUȔc dc`Սz 'jع @hUdZT1?S!t~(t|zÕ7pg| YFn|s>7 sLFf=O_j;biW9 <k)x— Ie(UEPR9[PP @ Pʣ.*M,!<*ENlV. )~J Ll"4)ܾ8uJAx:(c1I<~vg_v^/󞟝=[b78WšuOr[| `OJJAXPߴ*ĮŹS˰{-Ss#+&87 J{(7G}׍~03Q췄l\رAYʸcs=΅11r̮(җ ri3W iiP>+'|8&}My_鐈 3w傀׻:4>jM}+eok(:(^SIϋCZI39|ׇ0!a0X)4L.'2MTԊC mƛF XNF5He(ߠ auq8j'ԶnTir>9dN8!A܆a]aYg2lSM݇O5wg__;{ 357H'P<-zx]w 2d 3!%%%%8` ` aB#QrˈSQC^v`߆(I̍ A"Δ(?{omu ~}9(eIA=y#`5eB*P 4EW*hf赚e^U]x14tQ`(TYe04C GlKl%eVZ8|7ދ+gq"nكa*̗副y,'qݎ< e>StAj&Jйk4'|  U}^h?eHv4x5P/,kЦ ''~;q/ɵ Gvxf|+<0(0LcE6Y.C:6m~aTƚ@m;3a^guhVʢuÍ=gpJ>xLɊ,,\Yr3ڡɶ]ha9m-nD II)OvA7(c Ic]gKgp"gF0'#ݩ/6xF9ܗ;\uW[qS=:LM34=SQ3e&ld:$RVϹ/6V-;4Z=B%/IN0c7"yrW<o#6A)L~ 9ZIM~lgk,333-oڜ%] `Ny&fAxnvl<#}$\gO>96GOݐSCs2K;%"f@9ڍ Xm~hSɍ0:b hH1:H 41+Itr l i@m ͊\FmD/DH&JrٽcpyA %F_E\sg[q<U`QJ|z(DbpƎKr,]"d$u勤qy|GPݸ:9? '@ w&̱x353DAxڦ 5q FT65;|.__xve3J 69-12t,Jt| >~dtwO2.a8 $jxc,Cx9gYHMvkoƈf8!n/*]T@I)5CBf9顉,kC4&w;xBYdM>>6E]\&>f,3q/9D`ԑE0;P-WSǧF~~=1]YrwQ.z\Ox{y1_߀䞺 1'|g~fsYSqN $L2bQ#i~ID" 9:"*KPN/ <=mbCY%"%޿1лfCjEWbe;v晡g-$^Pge>9 YZxTrS]Ȃ= {w.xdMƳ4suM\׻fWns`Kڪc0 HÚf>rɘhWv~[riƊ?1Lcɲ-!M?u55IW6dXm='bLÁ HNL&8nbAB520i,wkNvTPgESc *kaB@(+j,f )o7{9Ę(؃2j}eo^ܖDfd3SАTYYZK*) ä~:L0 J hg[=5?Y#:]3Q.}wFx2x.o@vx6xBzeeӱٔ iI&8X%\p$křXC4I 4COq~ ƙ@( tL$ 4S嬠U۷9Z>;QUE;*bl>L̹VvV IoJTkԦ M Rda)&T <\},xsk&Zn#x8K8s`\9$ƳYb]" D?X#ȦL XIMkDYCՌTmg^%FF,r$JiΙ׼(7/{JQEmDM!B񌏹+IThVwtQ9xгD5:|lhe E ʜsv#(j_gJ'3Ak c-=SOjͩhLoG7|?%e{/zwoq}d=A.lj`K!B#Lk/Ov IDATBu3)b|5KO΅9>h z,>( RV}hv6e=1Xeա+N@<+vYAiMN `Nv3LiYs_@1"|w~ 빏gy}s$d=E33gz.dٛ>~DƐyca6]!޾XT55IW6qdBs?[VX>`?ϤR qsb3$AcY37{ FӔK SR|4=僧Ї1@vVҥhi 4nQ"0׹DMyv`5Df"J  uY_90+sEڌ>[211(1\r0NMoHf-@a 3kjld&Vv- sI$v PP1+VSZ}@$CO@+,W@HP)lQ q(X A  kdP% ` Efx&5SpF %PdTˁŜ:Ald ڧm@nzϟ{^vi#+ G='ٻb$L?E-14jXGp/fF{'9i}OjYk%%bQAM6&A 'o:y3:問au8!<ςܾSO gD5OϺqP<*Os@ x;g7]ޘ%@9Q:l~ cs?kjlySoL#̥'bNH $Í<퓠C`s". hRYO;3zbgH7J٪'.2, v@ipo оMg]k6"*DD ԈUA`.2 P(O/8])r'|RG {9 L(OX *-)10A1$ i8#9@P̒[G m#fKX%%N(%}geNVаL4Iǒؗ#ʷ>}CW"vX\3;(% M|>KCNE60`牀ϟov.8~˅sHF\ (`_1]J;€z#t$t'xg}Lml$]R1q*u *Sa[˂dO!Zg ltCC3iǬM}sr0X9ÊJ󺴱~,oߩ\ШR{9޿bŻLΜ|Y;iY楴&}ܶr|I^Tc:~oonUe|wyS+uϣxsY]M详loo@D53(OaILQg$ȳxOkVy%8eS۰KLM TRaC90yV n췱 =$zGWZ̺;GP9,qMX^U'C鉐<(H:EvsƯQ_cPwgH** E#ˀi|Ϳs=!v>K˴DXDUz_T8Mg xI{+վn'ۉer(394Jyavg $XA'& TL$&}c YAA0%OS9O/o]$fin.]٭1(Gx6Vo|flooQUի"ʷ9\&{#er^җ޲Z"ɾ9ZQu}׽{A+2:1v(_ =fe@})=8QY.r MbElO@t:*̩/cjS,B-C1pr &h1̒8m!26 2kVTBV~xd羬u{sosOꆕ\)@ E~x.O`FWx箁(Wʯ㩏m1 bYfcf+^A2$۷GqdrtH</yKf>1Es~#*dM!ssd,Q;A]l;cCc*3r G1:Y ޵u){YK"HJAT[whb3.[1KR8(23kv{N<} 2Oo Oup0ι [uÞt Oro{E#ݼ,նDvO^* 13Pfb3oyQ6֗7fvm閹^Ҙ4b;+}qAW֡S*3aQ65'uESzލl C;8.%jW/!`!5£Vz),Vjvپī=e}7^r{-uO::A䗕22;&]޾o/6} }E/qLҾBrJo{3I$'uD !C#3o&Hf KS{OPMTr$R1%.uَsV@CU%DP10w5݂曘Da9^A3l62V K80Cb%+|sOc'Me(?`}.wl/{ˁJe|>}lMf>%NR![xjcdg@AT뚎N(,h4SL)Q-C m"=uM4fOՓuU}ꋏ/e7H(_M-fXR"Н9Ti,\RiO*j2 )ybzUUzw6"O_ ஔRcрlf3f>wcS_9AQ/;M U)M"ZOU0vo?*RkF,RMo.;ϒbg 3&Ձ B[NIG5)`R4ֻ.q^["F[~_'vOIȈpg~3qxq練NF"i1RD0ϔyc !z^΃oe{{~ lf3f3lmm9:&u]s:0[ȂA4$$ߦdFRAYXRdu5@)qy/T+۪|$ + ?ްGhةZ#zɐ[N LI 3d 4͗r{f,Y @ k>\x/{1Q}K$+'ʜHLv52Lwd<>Xɭ*;DĜؽcjRz||ڃx㍷;vΪ^t g7%3gyss& DaIpiۿ!"]X7/w6 $VҨxRdXP5! kRdJv4,1lIa_㱮SҎ}&`-g" wf@m9526WvDu?d_ڗ{ùgп[H2Q[U88f:<{UƳ܉\a6茒[U!?H}? _ۯO{޾ɓfkz1c7Ȁ5U X2d^4C4K}ݘE_]o0κھ<ωa:;ʅl;^ 7ᆭy z_{+RvWN -pdBR򧿏nB/Z6 G9)c3?@>4~r|~ &2F's`3t=&f3!Y1z›fg꺾g>qn3>e^Y~7Ԑu]*䜑RŜwkx&$eO eIÍG dJ<,<Ѭ.U$wҍ+ɈlQvw k%i\P9v+tGaTPM-*7QƓ(69EtzkMiGJc7׮0|lȇjS8(xì+X.= ~j z> X ]1@9{Ȅlk}m@`i34NpKq}L'0w]@O3mD4G#YG9: '画+l9r,1ҌC€D/fp27kIW(Z`9gUaɜ-͜J ug,kfMI9*gg`, (DΌ(1E{d--49.t@l4L?@T2t( iθϝdugg~=/xp7WLYptI0JH'}Ͼ=X$}gyc_yO .e29KlO)/Kd`^[JSJўJԱ `4+XL!Y*eI2+v ᙘ@He7؅F%%ƒᏂG!:]ӿ\x@ؗosfE<0O3eLTc=s؀I/p g$缑$ѧ=gé̢J(%THҏ-[_ CHNRVQk8"u27v.q _rG$sǢ@a=\A+eNk$˽a,2q[H Wd2"iR;jɢ(OO1 aSktրab@ya/^h:ku0-Ǣ$-sOfD͍xr\˽3qF=45&t.v(k2bDj+:7;S‹/뽞43*Lh`T\Ǟ+Aź,(>%+>SO׬F<s'xKz :M}o4]O).[x.oMe 2dw̯#x$\ In`R`!)1 X(G'BŠIl3k,kЎy}mxJ쯌lXMotb0WBA$[16 H1 HڠRR$ G%'P. e(5cDpw8cd.9)D0INk\}O>4+\WM+ʙ78Inȁɢ2<=*K'ݱnb@'qa&s1 #0 rB\ NeiX&@,({fXh[JȾ,N)Yx(,eXlZ!3x[RO RP;V:)uyKK6ڷd_Ԇ etٝj:%5B35AU4g&BfDz@זLزs/7~FT%zm=MWxrÊ\-odm`{U"Ϡ1yy-<Ϙ./': ;ZI&YU=04 IDAT2} #f$(cf8ЬH|deB#Mm(PuX, 71nUӭ-Cg#A /*PqKz$seK1ReeXrueg˔~tg?E8[~8u.=mXp0Zx+֞a&oA<j9/ <}`ޔH9KS9VifZUe t?E[ dU`㖚[^fSO9S!K& U@^@{Xh*gWqsEB@a@oH5A%R"P>gr{ $Y5R ڇN_?iÁc7:יҍ֒<(HZ׀#.|wL+1v, ̤sUwpd13s;nqnj36;иdoޓFwqI)A-f]2aMclx4F(ee߳;seݝ4=|!ʃ,}{~S^Ck=iXyjyYe>Ep}"+ <{M\( @XIIQ}k8jtI ٩Ƕ1YA2AH R#tԦ(N%(׬K$xnq HY@VtriaNRT۝.YG*,3p, R<8ZmWbϦ]6"k|}o۾idv04Oox$gO΋ 2|~X'ĄW1n: sR`FQ@#D \nC);ȵrr'Wx|0 蓯%iSe,Ze^'V Yi-*Hdn"CsS5dmuIt˖E|ϝ[{(y4HEǕzC?_C uF7p22jj$X!2ֳaO`O)] xk0-. 4=40o؋1dʈ/C,v!j0e]jQ%XKm*2S=3('mZ:sy%%|Κ*H )|^I= D[|!be6A gݛR aHZT{7бwgǭ`z 6;&?_l |tӗ'w?'RFO`%PUĉkLf?|A1${f_\STByPK6R!d)Y3@;A5r6Ԗu\0c+{Cɤs`Ǟt(9]"ق 2+B ʲU\7Ŏ=ضly?nļYL-v}2],%/|/w;u7b&+b ZLK+rm<e.K*=ԥ P" { )~4Zr6|(>kU*v0oeH y&[gg$>e+$ uaXJŔ؟|6c]Y~L갤hUqgU_T18gs*$h d::Q) ŁAqZpM]as\2ޙwM?dxgډӨZ>9h41\<f<_2lj="s~A1$"J}6Vq&kgtFc@<ND쏎I@Y΃c8CJeT$t2@Y@j br^Doߜ$["J@|PsrZ&\/ٔ~ǰsw'+:] Ƴ-l?g~jw6d0lc's=2C005}sbmЇ>tA+i;!ZtF' 0Nj+& dE9{2xe@ԉ!^A/B(i*P3c98#ra 3JTF˳#C<ۓ-b}޽[meF 6Y._JՖuGKzXWZ-zۧJ g<?-LCVZYb\,W uw514c;ZЀ4p߽z,bKݎ54Xc^g|oCgtt TD5-b#v`s`lIksxD޾̙37*QBH/f.2_!}~-fd'-egNt ΌLpHa %uuPgR JzN jfXb͠YRyisfYTUbMUZ\3tH?-(?dp|ҾN Gױ_;;7x'~_4dh< EWYlN'0ݶ3ϪL-H)Ͳ|bA=ug r؉ќ:U<30O46Pk\%gLeŠ6&<3J&@^,]E[Y=CSk+?7'[ohho <Q&\GN7FMrԝo6Yz$-:@7e8/ɫw{;&QBN`@u4ؾEcyEZ%hc*C%緶W6bN$ʚOտ[زqӪ[9Kݍ-0-Vg)1Dĸή1}vO{^cqlr]_^xjGx8 j51 kP̍j0$KM)=F{>~ӯW)ҕFM&'%yNGpl(8Ř`eE^3#I2hn$d'hJKEP+{Vcqɻt@_CJNC 5K$Ҵ>z!^8'x_uJBEe2oQq~5骧Rg෿&+:_3_bVdcv[gn:tЪn{a6`%㩝/~= "=Utd<;@jQ#e)ٯI'ڞfwRL+QVԶLRK^602MFQe% lgdB/'F9)%xve2Ŗ`8 ,y&-V-IPUcx Q['Ne3mB&$ҭQimsw~01O%$Q4qN ȄVU9sjXP`\7jQf0My ȃ5"IedZ0݄"RF64uu3UT%jiQ221X#)k? )lK6gR 2ΒCW0H=zB!_rۃ3ʰ|mO{ZOBԃ*}l-7wȵtz Όǿm ]<C+Bw|%91Q1ytb@1[[[wNLB5;@pbfmZWȪd %d!n!-sa&3gpaӨ̧_ʡ&3۰uem kv23gi@+0LRV\B?+q7}FnOӯzgP™=l:qn8ٶIuyU?~QdW㯠G2Ƴ%5H<| ~L$#zuHYIX{bzZ&+iчgj!/e ԝrw-tPa7CEa3R,-'^##%-r=hd':o%(#yŖ,Z5L-p81n;Nʹh\Is*rǏ~EMH fmS %,nX `< -t)ĀN#ʄN,$/@_p>j0c W2HR^,h|1۲P Mm b&jT|LiyæK(<"yFՎx{K 9s]*D6~!W|ۉ7ܸslSO|w;6p}v +Ƴ:'_S<,c<[z*d:IG69#)[3kvu1)9Ģ  „#^ϐǞdV2dUvrrwY'9ffWU"IԬHπ(u\9S ʁ2]ݾõ]g䜉k,ڹ `"TuL ^xƷS=%" 3TOյ_F7w? Z1Ap#vteY{c8`g 6ԘTjnv퓞R]:{P{+_\`هğwkbhK ,?t4eYxIB{``NYl-zP 6 `MQmF۴dp*ێNW8U2!CACe=<3'yޒ 9ԋğVR17!,&\:ICz$-XOg7eW2ZB:{F64<%l$Mm43C(̨ǤKݬݹˡ=k },SY7Usʳ$5vF >6o"reֲ쩳ZK[5Sag.qd 'Br]b&q95RxT2=T\S&$Xr0ǫֱ\/tB7Գ7@Fxuǀ2Gqx.cTiϥcNgPSYũH]$SEgB:r Qj{{gI?Er,a/Qw#w*aLkh.2 IDAT6%ϲ^__plPR{yp/rd-ACPӤc/u@- k=~{Ɋ$2=/ os^Y%j|CˁzN=yx6Do}sqFxJESqԾ Dݡ gf >n9JD5i]tƱ#^@-ǟ_ V̦}70w|@ TѮE GАIPNSƐƖ*VG/2f>#؆~7:F&WW߯(ݎdpdUKw/6wl3Z{~⠗8T'13DzKG\7Bj_wkSJ/kpQM)Μ9A]~e9YKjioklkpT̄Drc Uvjϐ PҀ BHbY'zɰiB($Te=@1,O E4l^ul<Әha#o o=?Uf4#d3PٯS5VGx[ٷV7>g?(0l:hMor'@e'&P؀j϶9s3g:!L%Ƭ@Q3y=a~4B~H1\O f7-BF({TfT2 ԵO-E_v YbƧ2K7''P_z{a_ o~+q;u:3 <_[T?Cv֞sQG7<"DpwUh3X|l+ y=ZkZg>P`$tA0$ 15qai9#A +g#iuQ5ؽF]XlY5 #I0w_YTg(c=gEsf\ x,@w 8G؉ejK(\b{].s֦ TgPl42~6hi۳^ç21+fd{>#:~ =w V8OI0j}@3 c<$ff萈IނEfc9̿}̙Z|nl6gY1z-lx㍷|}1NfgdhGƔgd/S YӦ636aʽ@25+ҌQP /NIrjfICb*~ݡUKv+(Yxbؠ.ddH?. "I8X4Vr ק-͚3H*<~1љEn{Ϳk9Ϟԣ`f1 cC3#ںud\< F22q5 +ld`یm0ePgd\ j"`uz>7mKV}fu,e!RnFa\X{=|t3'1+xg#ҙA9d/Ƕhn>-t=e<Ȅ>{~TfrջA(j}FxGʴrikl(Ѩ\Pgp=׹n 5epNz2W؁zx%{dx8&ځqfp &d)iRwE7}ݫOt*')xl6;Z_蟿s[qP>Ϧ>WD)_xR.+HIbP@LQ3gΜ9}:, .i#gBo?h&!PUr\@%*s`G=^g=C,QgSkBpΌ5H7oxc@-,gǤ( ΔeGݹ\~gCh蜵e}{K L׿ O,{y00aQ[{yEO"*9u2u@͇ ~L~,@:R]zL2IbvP۳OgjvXRZKlD[Im\t132YPc4 cY7؃Ff{66lC_bY6*d[۲{I͹뻍Hl{O';WU#b1 oόgwbE{g:߻ C4F9{#u];FФVcIT=%]zW4-N;ٸy`;N~KtvVjlYrn8#wW P`>!ZIjv8ErrѾm`6A= u|͖xڳuk׽<|g_OZ ?)V3v6E\ . ϥg/(A^~'ePd<{ӓOgҗCu6B@cFcбOrΧsηFtbaxNJ!: )5$x=b7ic<}'Wu`+s> m5Y6Nx=@9ĠAO !(%!" &$NM`pĦ2D5p1::'SڄlYpUK~O]Lj=gN|7~1`\KA*zx'0 <;> (/yuϺk (IyfM/7ـnG$+$k7 ezF[ѸTouNTYDVC],)KEʄ]Y۪ Y`vp;f:^+&Zx\OLAtLZr\2;҈ Q˕SNuRge<ɈܨݽƩ/}z?Sfxn!)$岝xE݌镐r}^e )6 !yErحD .DY xCH!SܯUIc}Ue=h^;:%i@$*z?:qȐl)ԬkIæ*)e0I3:ga~IDZmwL72#kKZPF xnF/I<ÃdY&Gf@]VCL~hesLn0 vxQ⏙U4iOK)(YՅڀATL 2ж <˾"(j,,Ȑt?Z8 !cx{3>UvͰ)l^g?x1Qzm/n'ׇxYTSZ]#-vũVZ2!~5!|~SbEǪvI\eF.Ou%(Ke)`)ٱN8- 2>(b'"6}z>`&9_*>8є5 $*qL?z,}FfPm?8[5xx&zL{\1d ? ȏM㩀gnȽ{Zz>Z_ $ѓPz`t%M~;9Nط=jt:V=|-Yۉp_EU(0PJD_)b/K7ir"bw G=\E#yD]S (*.ڞփ0L)~\G8Vv/hbϳ_iφc{_B'iy8gSW L|nSuA$la3QRrQ dBNaTl C ZZ_4#JU{a% ^5)|h⾄f}jOh"sx2Rbi=47cTZe<}^bz ,hSَ`<\xf&B Pcu}ʆ:<^rbm"5ޥ%dzǂDKf)ioө#qR|R!vi2 5%o:ָL~KO頤gH' j ǃ=¢BJ(3hy$r#)pÐ 2 | \r+Y|JUc0~p`Ej0ЈqNkFzk=l_D+xfwuBzѝ Sfg")S8B&T1:7M=v^xxII/u((IK1 쎕^m69AكT/o$7)ف4},iUY2x~?c}-BIbHԂv %ڎd,&QS% ^ xXňևY"`ʄ]Ы1W/ CU;g5ծL+*O OZ"ה?z yY'yM"VͿ W̵rL [|}Ri2?/?uBxFMrgRڦD(g ~ UЮ_jTЌh%mVvxڔOW/< IA@cKd`1S&^~g$zܲb:}@7NUII1Wu Z,x2wWW%7{PO$6 (sXӖt%fsu˧tRZ-;[̍;53v1YY )7 IDAT2,OyY@&PT}&שRTX;=, ?p+0Z!ߊ}zFv@L?)2,9a\~ @T4U#MSOD=0{!P oyN?=tئn;_sJdߵ7-\s)'HG?&D@[ Z @kμʒyi\.皋*POXօ@l<!UǤMU$2yތ"e0J>9$f5I@3™=X%z:VlDsj5M7>wtgovݮuONiގD]}V޽W[tLx@d#Ɏ L[=WByVչЛ1Gz"UF6}+p3,(8J TA*W1 :Eղ҇oCV8a=%\d"߹7 !m7[:mć.OhU٭.6l -C1JTxdpЬ<?:S˿Wc}»S~}.LP{k'0|^.2g\^n;^t5/ [ jlZ e)6'6L?۱e23`,ILDLg1%m09s8{r0IiS\3! #Uz(eXh>"2+/,}rt|Iş՟[ |4a[i@&nE1߽ kg?eD2bYt_Ũt` <7Xlm4h+rwrLp+&{Su!`&ɓTDi/8)~!(I:$CJ ; һm&>A=~6)v`? pa}oGO'{Ɍv{?ǣW< o'052yB]ңx登T{+y'>fxJyynIcx>)8`)*#m|+[Ń(Y*Ц'd~G R=<vP}QUAJ>CV%TK$ΌP`}W6nc5 cɂѤ( ˥ PnU;x]G?)zly͞']s xq~$y^_3U4gĵ?KX -*!6'K;W.e] iD֯T]ob X/ ,'ySLT{(A(ͳ\8Zx|`GٛB T$,z[@a!E4̏QӺ#~֏`D?/{ToMn~܁\ٕG. b/7,lA-a6?2Kl3q}/~w01'?>X:M\ X3j 7vv.ɡXS\d}M0~\5Ɠ<,Vې%6VZ2 lFۻ@<e@US>YYpLA|I{$9QYQUVYf%d-)'L  bS>/Caihsn<ŵз?-!pOkVO-ݯM`IzROlxDQFdTr`CLۭlmțՎ)6o(lp TP)!YFiG_2y *p)S&< O -%ՉCMXLP͙,ShweQV"+"g4,>bX6JjTqkyLw~/WL!]V@TY4ȱ!8I)mK .%Kwz# g6"T<=f?k_wsgi՝xjk|s~/q WIox>Ω#A夠~,Uc93È2]C'utJ3g Xϴ.FnTQSҖmVv'"Oi^/6%ۗձXNrR؏zabQ}9a\k_*f4_;Sz1G6~fȂJl#Q"Ɣ@'<?:6T geO->ɇ#)dž_3h{ݻWec%wπ~K˕0R.n)d'y%(^|.yͷK= 9&0T2$TFEz^Mchȥz]]F'b1G@aB1ƉƫCl>2~;<nU618) >t?UcTōG'csdu;9}3MǷxbDŽOQ$rL:-:<nQ0H )դ2t!TO >6'B2[* ˶qLe/-ỵs'7?.FA~Θ99iJ"2s9|O?\> o)▶xfee3SEx T/G"-< rz*5$-!۔gW xR<"  \AH.+OY+>";zi.9~⥜UۡQYm+ӲNXUO1D`,XE&x jSڮUvqd GsfWh8gdZQu.t&+9k7}>[O*~}9ƳV5liԮiԶlxI~;JTμ Q(E(lzj,9F\j[iVv< Krz( hF[)6<%e/PTOՐJ!GhU}j4|>IO:I +t;dlo5fS'i2Ѯr> iY>*)x椸۟yb9~I9\ܞg< Cf\S0/W5)EtjSE55 [IW2IW_1ߜ輵@;~ץ z2.`OP&y;QMF>@ VbV1aE`7` `SX ereRCKv dTX,'7WwЌM3Daѿ,Yۈ|4We*}s}pV;י{p_ ;:jteto i=smc<3*~%gˀJ+5TA!+S 2'(Ux J>DhSu(==M=PP XbUtnG]%ݠtC<d zpo~toߑ<7' >_g6H.[s`!%XSCso#*xZOA&i+&jSNБ@@.luҎ-9lEA%Iڬzڼ@^MECfs@2\oDc|S޳O~ D4ѱj>R pF@i`RTW*{P𴻿Vhs J$escKA\8=wusuZ(~"SgEoY,m2SZ?׹"S{z_ 4w Շ' N9L'hjzk3'j3&BVkVZi͈0xTI3=X : {(~ Q )n#z{ĶʇUDGnЙ2ZfQѺgÆ@FEvxyՌCOuW~kzovIOF=7~u=6>Lf쮃5VS}nS!?ViMxr1|&'P=F2xJdG;aaA{ʮ}/sU&!idάَQFn@ 2!a)v X% L,ڥ][n+aDiɤ_C69ga.\~ W‚#tW=xlv[UI3WugZc*W6MS^6<=kx Lu404u\~:AtEWXD[[/ @ۥ8<"f4Y%3=K#agU;VjrL&_>6-U.cT#&Q\4I{Y ʵG^n־λG0N>Jӽ֛=؊ Zx*1 9ˡ}o%cG4 [ԇe@[i'̛R^۾0G"Q#?A\XI!(!`Tہ۪^ieO3e MHtS&.obΝwu320{D%~>4HcH87 V{ыyؤH㙓lu32Aˠ`4YKg)x*Io&ƓlF ОM'!I1`d53r=ci+']x8?O.f J+A({ `gxF?^2*1x}4HHNt,Y񬑓œb7U6W:Gz2 3ZtYƷUpQt oxҀ0'1}=:tv0i! 0ˠT4Ϡ.` 1ѽh}rJxWCL($'oR)蚖2S85.e<=D B%TLtIW&혵 ?I&m?shyɀeHiHTeP1$H\2Rp1ծJx@xu 4O0̯3s`W?$^l&1a :)oL-qОOsO*zM:t⃿|HO\'TmX)FO>v%k0⪴2ʮ`nq5%LJ,(0*dt4Uٰ>lsxBڧgJ {䪤:{]ol-+):u]wen|F#ij;y  \K^p@=# l\CqB()G[Ii&}%?w3WMZ/|x]x{r7}޹eVZp&aeЭwt'ʻS,f W8d e`<]?͆Sv.xBO5 xRՒMǂKjAByh;2u)|[SUoM}c/TF紬nqD肉?mfR>k/後Lj>`)I-K t `( @LzD ع-;opRn禀.9@~={0w`î[,-Y\D0CA|$!e4*s{c <7ѧd3*~D7f?cK,h`[ ,wi/0x>xj$:1,%PEڜbX]PL\TMhu!,rJ '4xvا>Xo^0D6 _Bm~ pFf)ߋN9tq:c< kQ2{<<)g"@=4e~,`_f#$O 9F@Q (?V;`\JwgHtcWx!ɾv𝪕VZiH 0k7tLonޡ-zs% irZkȓߧ]dt`O=2@m7^^7~uߟ; 3J&ƝQ;ta6 |(h#EF+z>&VZie Y3 o}ۗ,ƿ<}a8<=@*EَIO<[33Gb?p(, & T+-TP ,oV떀{g$fn#87 eL) JRIܒi#ڹ)sfz~"ƶUrR4ٺ"nAuo *vc5UjR 8%:(TZ@VSV:rmg/4xN"!U4,=?-k'+s'@gN,ΝΜp T:e#3 Q|\D43{x +v~~vX¹ᴯ6dxn dw4 [v6q~߹O#^iZ cFayaܙ3SZZ6tRgԬ p 36 4F& &ɺD_C6a Zt~<xsP̨fY`:5o'd`<6VWP|)6 4X<@=A~٦hdԁgbmbFSY|Òc J?` ^ә޿`B~~m/Ck]~<3SBʬFe&& xa~>VZuBD%̼?c`: kzy?Μ_xbS+fЫe uDKw,ac-P!R5P1_znEe׸1 )Mbfg1|kFLUS_uNPz2w?H|O <#J>e_|]< ,9}8tk(W.T]1Ց9p: pLhY}cI=GI@f 3Su;Ai6V\bįi>-TpQ;7o)c `n}@[i'рUم7% /ySK?~ieP>w~Lo*~Z{A`aε*h"!sR}IYrD$@I% Bd/}f" G{nGqgOC_evEC'tT~τM4ȡW`'wR0 ԁIRp(/C xu&F'bj:wv-,v}uPĦ_qIm+'X㦁gQmT !D?z? y@[ҎI܊Yk|=t|ט=e㿲twݹ݋˃E13wߖ;6e릭nǭRyMw;[_MM8*)"- SL:x/hzIHt)t)A Eףx7aQr'-BLoq*g#^O'ZsDØnaWf~ `ng lb,SQ Jz<Hi OK ,@golykK D܀E9x*}GOR;x"S etMV_uL1keR!!3/رUL,t fߴ;/ O>u6VV7,NdG[0Qa¯ΒauAI4{nhSXĚI9TRZ-'!*'oz'x z>SWA/ U u>K{xK@s X48tS~a?3 ɜs+P̲PaQ? .i8'JɅPmka ˠQFdYDoaۛtٞ+ÍU;ɀW\lV/_X- (3kˀJ+OjAJ|)rLg6FQ2|ɛs2!g z ȗ]~a镔s."=9sXmdg`]PzAlҨϜdjLrJ PSS% 7ipQ 뙂&]X/m9\+x8sU=w|ŠӧװtC<b o-|+gN-/]X?/-.E㷂1[@(3)@1sId !''U: S nw|8h?0s!`{,HL@ sfH.v=H 'dU^D' 89vL6ӔKia`c6swǀ BRgԗ&?+<^'Pk+8A=`{X]p\`\]@fnK"B Ҏn_27k!Q#p0o]ϟ;_Zz|ά.{̾fn)Ϫ˴3`Up#KŠW/P9X!(!\xJ%ClcCˀEZir)-VELGѝ{S~K+ ֟X7g$BJpǀ.)q s~ >pD"i @U3jQ %HG0ix( ?s_}Zuy= (j,_ ^@@DnՋ j[nsg JH =YZqL(__k=ZyR3)< 9 Sg)~ۑ./~:srJgn6)^z$%l%PMU\rJHQOO8 -%ZG0-VOҝn IDAT:]sQ"s{+@,e YqaBT SS^m &wF>zdWk030 ?xf)2J7Lu] hژiʒ@Eqax%3,;xʏ.p<-J+ %^Éj0P讙W|=sgi <Okh+J+ _P5%,?_{N_>}Dy>whxppQn6QW|B١ҹ1j+%Լ'VQBX%JR/m [,UaCɄYI 8&yQhz΁F3;tnԌ:R}Mztf0\[#V KRS$f P ě'(]$V>Jf_#&V_t~CEܺ|,V o[a?MloxRCH֚kh+J",̏ر qk;}o?eN۹)u;c%M6%@o- -י 9%4[dAhH$ s}^2Tkգoxu>p< iH |x&*pv)pA T/#hpLZ-*uR@ %`QcӔFMH^D_9&i0I9 <+zx%MjuߧQF,c,_\:OX]"Ctg`♪ AhC˭J+׽Q郔``#(:ݻO^;ߴ~v}(YTvN ꣎1n>c밃E#Y%YuzUր(T>Jc1rgp2*64kbl9rTY@h>z`0xj25 Pu* ԮLjct8<9e:R;A_1ʈ8F4OXJ) RR^ 2`^L8a}p%`vR-E.6U"LRJHJ+ vO}+X<7>[_ƞgOKtdf`R$9 0O$dӋ~n2DՐdk.gnyF叙*ik2iI>*d8rWc(grUxʅl E8p)pdjAFp07!@()@fZGbPI)Rpyv} O0xjgxf<ta/{.a0\2clFO`B)eC/[8J+RkxXq)kevS5s?ggzb;SgdtddGFҌHRd =.})_nyVhYf('qd ',7;xVdHn_w}<$E`j6%JKC`2짊 MH1kEٰ)7P):nuٔMj_ U"SJiI]wLgG3J=%,/S9aB_t @[iV6!>wy?30c0}/Y|ןv̙啍ᡍ={ͣ |SЛV%76-Χ[5 g+J2j91Ru5 r<0p@WxaP)U/EI#VyM)SoyN cA 24ҠRSP܂Uߔ:Q &>Mvd?ǩ01i5HV e"u( GU `@QAL5!7O{nY.```˽(8pd7%ųk[LTTY̓@ b2RJ+[&>HiU,/FaY[{7p{ܙew38}S8){@H.AJ؇bDPES2!6`} `rC#!* EK3h&2}fI$WX_ۭ_qdtOF|Һyuko8X98+V=j"{80{j{Us 0<` [-4PJZփSg͡iKPT·׆?6'\Soni0;2*Y s ~VT!ñw羧;N[S~{&As\&1cSa<6o}22AШXeDD6>D݄g[?v߸ow\G{ڃ׍R(*(8\%$6j3s@,I "%̴-nxmJnٝ?xDSUm ¶>x˕0gU סoŕlWʽ `fwu,-+C719>j|f%)(m n+PGhOP/Tr~"3O7^@r'  s }`_aM0y )o; LT@d9r D`6~~xv~޷έ\͟rs;-q(Iv~˥}/q ׆c'g 990r[ߡă>~8G}Nvogۺ߳װR>7!?Q? 6ȇ R>߇ew t1eU;wVB?6\!xVWlXoМjpFU,t$h <4@N09c@HR+!EEEE"zkQt6̅}kt=8йѠx}sKxZׅAƯjT/$S5%`GͭYtge#jl݋ 7‹h~ۧJ N&N'X @bm%J ]+_ڊo|;R?)sKx.o8'M|1Gz;<} Cw5׍Fq;LCYpnLuC>sc{P,WiYDz +Uw)*xM*zs=)@)01TʊaQQQQ/ʰXDcc7 }_z]omٿi0x޹^w^W0@%hրD ;]؞  =',<|^y]1s3Q9USY>wsunBG <]:AA\:-_;v嫁ɛOxNAB&C$U~uwm0)qv@iY"={d+ĪEШUUg¦Œݹz~n]n}OI3[גӧ۲Fz'@)2Ym* VH'4ګ+O:~؃xV.$_Kew{y?;U𛄇ڧQj&\yWU\n2=Υ}Rߍ y`8ha+$B R38 mcw.t\vk?Hq36\7D*c@\:pQ[* D -(A ܩfmTT *gPᧂ_[i~^㑿s2(V[Z}7l"۹`=9N/?;)>g2By!4)x4/OS'j0ӽUTJΣ[LkTC$:E>K2 0}l[dRf,VD "hbXkŰ%f+"K< YpE1:?~˷JID:2F> V3}jqgeXJmk0`r@x_ >HWS@şx+V< 7ʛډ{T(--IQ!p<aV8he\LV4X`|4VC&]6wR0v8Jr*!%8:*G*Qڿ y;0uE@Lp brA;0l*k85hV(bؼk\J~|]o0fE(hTTT] Q~4=(wO}b|p4zSͅOPskQ4 l$ ^Mz Vv=@om"ҠFjQp釧m98-Vy 3l!ԇ3Y>_8 t CrAw99#8ߎQ'd/<)8'MMv.8@(}Rt\eI.6ۧ@D1>8bc0&C9@ftW;Q]z%SpZ3iM𪀢|v߶-ټ( +tـ&>x1OAH-;S:sϬX!{M !v$u 4$j#7WR9Ns(^u9@6(~bt!"= Lecd0`DZ &A"Xi0cS zK_6^aE$".d?ag5aaMrF6M۹PH @* 0Dڗ,oܛբ`%xV=[E܁(Ib\. =c<',8! м-Ω5xwiksJ|jm;L_;ZۙH`@^oW|C,JZc#2i]0Sǁ}Jɀ|()=FNynm*3(`G`kl<7ta;4]a UNëH@R8Hx+H <2_>Oǣ /vTo-sAQ>",eN(*@KK:ӁB۝gZ;UQmnK1+n?rx~sLZOfPݾZuH7ngaYghPj+T;I%v:k ¡tj `S =`6Vr @qj YRLֺ(kE}*s*9WD6DlJ=)1pE)ϡRx(hTTT].Ip2K`|1淿BrBAز8s@ #X >]%Q8x0EI47V7@8.UN]:QUtۧ἖ltQmҖ#;]G}6iz;6XHɤYp$Ktmt(UV<XlL鎈0cGbBQʀB@%W %VX>/9hMa+`,08e\@^&5= Q?cɭOhj,%:w7*l- m5'ka s@C}1wߌιE!϶9F  .o WyN 9<>;t1'aEAIDATY;-8 ]M4eGLT5(ᑨE񏛟PW QQcm&[ VʒRDNbEy9yQ&4 p^rEzIDx`~ ?v~rc~; E8^I+깡kF4"$?hX,{Mا} 7 wþ@hn6G07aŽ{5tͯ,oͫth/t׮9~ޤ~y\s1Yk{I٘[1l)F(P`VʖE;FX }+M&s~na< ߂`[pQ"FEEEJ%"s8<<-o|̾G'tpa=t/<Py~k&6pmR:4h+سzyz% wgw=?dzͽ -zssۄ%m aAԝ'PDtZRfH%e.dk^xVmtoUz5rc +{V0,{$V&{,IRt+QV& K Hm䇤F>ʪoxQ EzKD\c.A߀Ax鸻8c,,)t.ku|#Q ^aP\&HѨM|? Wj;9#d~Z4hԶ&%,2٢*F tޅ;eS2ĝ*q(]'[2j2)%<>UBYp-%<=dp.GU`RB$(+!c 7yN+ߐ|nH;Q/"FEEE$" ]tV? wG6~?6{.~D nT5 *.\^-o(j5/G"m#9`*x^S[˥F?M4tԺ: t&U '] *R)Tn/u`K2ˎy^$ePcj(W t*%@nA~K(W~ΧbOњ(*\Pu<,N#pXxfv~ۅ1`&YB8795{b&e e[,L[ɶOG*݄dC#1s #7N_緶8ADW_+5QQQQA&{@M^C:'F;[sSsT&ҝ+ìKcԣ56!xBp!)9 ]IyRz0Iv.mu>W탣5KEd)VA^89|̖ |dEY%R"JY$)s+ z:ClIrKF;)9 _+ w^)EzKD466`E(i0>H8[ ̝vpܬԃPkpe;cuaQ/r$mu[I *KSuʩ%|IT,TJ`MJu hs HƸvGEE&4****UUd~7拏k;+羓l۟Oo󎊊4****DUEJ\Q| ^Ew@Kx$"J7**WJO ****YOr^# fFEEEu[Ddcב' `f9쀈"FEEݑ?9N-E6IENDB`QW-Group-ktx-d05d6ca/src/000077500000000000000000000000001475442401000152175ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/src/admin.c000066400000000000000000000434531475442401000164640ustar00rootroot00000000000000// admin.c #include "g_local.h" void AdminMatchStart(void); void PlayerReady(qbool startIdlebot); void NextClient(void); qbool DoKick(gedict_t *victim, gedict_t *kicker); // is real admin qbool is_real_adm(gedict_t *p) { return (p->k_admin & AF_REAL_ADMIN); } // is elected admin qbool is_adm(gedict_t *p) { return (is_real_adm(p) || (p->k_admin & AF_ADMIN)); } void KickThink(void) { if (!self->k_kicking) { return; } if ((self->k_kicking + 60) < g_globalvars.time) // Check the 1 minute timeout for kick mode { G_sprint(self, 2, "Your %s mode has timed out\n", redtext("kick")); ExitKick(self); return; } if (!is_adm(self)) { ExitKick(self); // not admin now, so cancel kick mode, just for sanity return; } } void ExitKick(gedict_t *kicker) { if (!kicker->k_kicking) { return; } kicker->k_playertokick = world; kicker->k_kicking = 0; if (!strnull(kicker->classname)) { G_sprint(kicker, 2, "Kicking process terminated\n"); } } // assuming kicker is admin qbool is_can_kick(gedict_t *victim, gedict_t *kicker) { if (VIP_IsFlags(victim, VIP_NOTKICKABLE) && !is_real_adm(kicker)) { G_sprint(kicker, 2, "You can't kick VIP \x8D %s as elected admin\n", (strnull(victim->netname) ? "!noname!" : victim->netname)); return false; } if (is_real_adm(victim) && !is_real_adm(kicker)) { G_sprint(kicker, 2, "You can't kick real admin \x8D %s as elected admin\n", (strnull(victim->netname) ? "!noname!" : victim->netname)); return false; } return true; } qbool DoKick(gedict_t *victim, gedict_t *kicker) { if (!victim || !kicker) { return false; } if (victim == kicker) { G_bprint(2, "%s kicked %s\n", getname(kicker), g_himself(kicker)); // hehe G_sprint(kicker, 2, "Say \"bye\" and then type \"disconnect\" next time\n"); stuffcmd(kicker, "disconnect\n"); // FIXME: stupid way localcmd("addip %s ban +30\n", cl_ip(victim)); // BAN for 30 seconds } else { if (!is_can_kick(victim, kicker)) { return false; } G_bprint(2, "%s was kicked by %s\n", getname(victim), getname(kicker)); G_sprint(victim, 2, "You were kicked from the server\n"); stuffcmd(victim, "disconnect\n"); // FIXME: stupid way localcmd("addip %s ban +30\n", cl_ip(victim)); // BAN for 30 seconds } return true; } void AdminKick(void) { int argc = trap_CmdArgc(); if (!is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return; } if (self->k_kicking) { ExitKick(self); return; } if (argc >= 2) { gedict_t *p; char arg_2[1024], *str; trap_CmdArgv(1, arg_2, sizeof(arg_2)); if (!(p = SpecPlayer_by_IDorName(arg_2)) && !(p = not_connected_by_IDorName(arg_2))) { G_sprint(self, 2, "kick: client %s not found\n", arg_2); return; } if (DoKick(p, self) && !strnull(str = params_str(2, -1))) // show reason { G_bprint(2, "\x90%s\x91\n", str); } return; } G_sprint( self, 2, "Kicking process started\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n" "Type \371 to kick, \356 for next, %s to leave\n", redtext("kick")); self->k_kicking = g_globalvars.time; self->k_playertokick = world; NextClient(); } // multi kick void m_kick(void) { int i, k; gedict_t *p; char arg_x[1024], *str; int argc = trap_CmdArgc(); if (!is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return; } trap_CmdArgv(1, arg_x, sizeof(arg_x)); if ((argc < 2) || !only_digits(arg_x)) { G_sprint(self, 2, "mkick \n"); return; } for (k = 0, i = 1; i < argc; i++) { trap_CmdArgv(i, arg_x, sizeof(arg_x)); if (!only_digits(arg_x)) { break; } if (!(p = SpecPlayer_by_id(atoi(arg_x))) && !(p = not_connected_by_id(atoi(arg_x)))) { G_sprint(self, 2, "mkick: client %s not found\n", arg_x); continue; } if (!DoKick(p, self)) { continue; } k++; } if (!k) { return; } if (!strnull(str = params_str(i, -1))) // show reason { G_bprint(2, "\x90%s\x91\n", str); } } void NextClient(void) { int from = 0; if (!self->k_kicking) { return; } self->k_playertokick = (self->k_playertokick ? self->k_playertokick : world); from = (self->k_playertokick != world && self->k_playertokick->ct == ctSpec); self->k_playertokick = find_plrspc(self->k_playertokick, &from); if (!self->k_playertokick) { // try find anyone at least from = 0; self->k_playertokick = find_plrspc(world, &from); } if (!self->k_playertokick) { G_sprint(self, 2, "Can't find anybody to kick\n"); ExitKick(self); return; } G_sprint(self, 2, "Kick %s %s?\n", redtext(self->k_playertokick->ct == ctPlayer ? "player" : "spectator"), getname(self->k_playertokick)); } void YesKick(void) { if (!self->k_kicking) { return; } if (!self->k_playertokick || strnull(self->k_playertokick->classname)) { NextClient(); return; } if (DoKick(self->k_playertokick, self) && (self->k_playertokick == self)) { return; // selfkick success ;) } NextClient(); } void DontKick(void) { if (!self->k_kicking) { return; } NextClient(); } void BecomeAdmin(gedict_t *p, int adm_flags) { G_bprint(2, "%s %s!\n", p->netname, redtext("gains admins status")); G_sprint(p, 2, "Please give up admin rights when you're done\n" "Type %s for info\n", redtext("commands")); p->k_admin |= adm_flags; // Any previous votes should be invalidated memset(&p->v, 0, sizeof(p->v)); on_admin(p); } // "admin" command void ReqAdmin(void) { // check for election if (is_elected(self, etAdmin)) { G_sprint(self, 2, "Abort %sion first\n", redtext("elect")); return; } if (is_adm(self)) { G_bprint(2, "%s is no longer an %s\n", self->netname, redtext("admin")); if (self->k_kicking) { ExitKick(self); } self->k_admin = 0; // ok, remove all admin flags on_unadmin(self); return; } if (self->k_adminc) { G_sprint(self, 2, "%s code canceled\n", redtext("admin")); self->k_adminc = 0; return; } if (!cvar("k_admins")) { G_sprint(self, 2, "%s on this server!\n", redtext("NO admins")); return; } if (VIP_IsFlags(self, VIP_ADMIN)) // this VIP does't required pass { BecomeAdmin(self, AF_REAL_ADMIN); return; } // parse /admin if (trap_CmdArgc() == 2) { char arg_2[1024]; char *pass = cvar_string("k_admincode"); int till = Q_rint(self->k_adm_lasttime + 5 - g_globalvars.time); if (self->k_adm_lasttime && (till > 0)) { // probably must help against brute force G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); if (!strnull(pass) && strneq(pass, "none") && streq(arg_2, pass)) { BecomeAdmin(self, AF_REAL_ADMIN); } else { G_sprint(self, 2, "%s...\n", redtext("Access denied")); self->k_adm_lasttime = g_globalvars.time; } return; } self->k_adminc = 6; self->k_added = 0; // You can now use numbers to enter code G_sprint(self, 2, "Use %s or %s to enter code\n", redtext("numbers"), redtext("impulses")); } void AdminImpBot(void) { float coef, i1; if (self->k_adminc < 1) { self->k_adminc = 0; return; } i1 = (int)(self->k_adminc -= 1); coef = self->s.v.impulse; while (i1 > 0) { coef *= 10; i1--; } self->k_added += coef; if (self->k_adminc < 1) { int iPass = cvar("k_admincode"); int till = Q_rint(self->k_adm_lasttime + 5 - g_globalvars.time); self->k_adminc = 0; if (self->k_adm_lasttime && (till > 0)) { // probably must help against brute force G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } if (iPass && (self->k_added == iPass)) { BecomeAdmin(self, AF_REAL_ADMIN); return; } else { G_sprint(self, 2, "%s...\n", redtext("Access denied")); self->k_adm_lasttime = g_globalvars.time; } } else { G_sprint(self, 2, "%d %s\n", (int)self->k_adminc, redtext("more to go")); } } // "ellect" command void VoteAdmin(void) { gedict_t *p; int till; gedict_t *electguard; // Can't allow election and code entering for the same person at the same time if (self->k_adminc) { G_sprint(self, 2, "Finish entering the code first\n"); return; } if (is_adm(self)) { G_sprint(self, 2, "You are already an admin\n"); return; } if (is_elected(self, etAdmin)) { G_bprint(2, "%s %s!\n", self->netname, redtext("aborts election")); AbortElect(); return; } // Only one election per server because otherwise we wouldn't know how to count // "yes"s or "no"s if (get_votes( OV_ELECT)) { G_sprint(self, 2, "An election is already in progress\n"); return; } if (!cvar("k_admins")) { G_sprint(self, 2, "%s on this server!\n", redtext("NO admins")); return; } // Check if voteadmin is allowed if (!cvar("k_allowvoteadmin")) { G_sprint(self, 2, "Admin election is not allowed on this server\n"); return; } if ((till = Q_rint(self->v.elect_block_till - g_globalvars.time)) > 0) { G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } if ((self->ct == ctSpec) && match_in_progress) { return; } G_bprint(2, "%s has %s rights!\n", self->netname, redtext("requested admin")); for (p = world; (p = find_client(p));) { if ((p != self) && (p->ct == ctPlayer)) { G_sprint(p, 2, "Type %s in console to approve\n", redtext("yes")); } } G_sprint(self, 2, "Type %s to abort election\n", redtext("elect")); // announce the election self->v.elect = 1; self->v.elect_type = etAdmin; electguard = spawn(); // Check the 1 minute timeout for election electguard->s.v.owner = EDICT_TO_PROG(world); electguard->classname = "electguard"; electguard->think = (func_t) ElectThink; electguard->s.v.nextthink = g_globalvars.time + 60; } void AdminMatchStart(void) { gedict_t *p; int i = 0; for (p = world; (p = find_plr(p));) { if (p->ready) { i++; } else { G_bprint(2, "%s was kicked by admin forcestart\n", p->netname); G_sprint(p, 2, "Bye bye! Pay attention next time.\n"); stuffcmd(p, "disconnect\n"); // FIXME: stupid way } } k_attendees = i; if (k_attendees) { StartTimer(); } else { G_bprint(2, "Can't start! More players needed.\n"); EndMatch(1); } } void ReadyThink(void) { float i1; char *txt, *gr; gedict_t *p = NULL, *p2 = NULL; p2 = PROG_TO_EDICT(self->s.v.owner); if (((p2->ct == ctPlayer) && !(p2->ready)) // forcestart breaked via break command || ((p2->ct == ctSpec) && !k_force))// forcestart breaked via forcebreak command (spectator admin) { k_force = 0; localcmd("serverinfo status Standby\n"); G_bprint(2, "%s interrupts countdown\n", p2->netname); ent_remove(self); return; } k_attendees = CountPlayers(); if (!isCanStart(NULL, true)) { k_force = 0; G_bprint(2, "Forcestart canceled\n"); localcmd("serverinfo status Standby\n"); ent_remove(self); return; } self->attack_finished--; i1 = self->attack_finished; if (i1 <= 0) { k_force = 0; AdminMatchStart(); ent_remove(self); return; } txt = va("%s second%s left before game starts", dig3(i1), (i1 == 1 ? "" : "s")); gr = va("\n%s!", redtext("Get ready")); for (p = world; (p = find_client(p));) { if (p->ct == ctPlayer) { G_centerprint(p, "%s%s", txt, (p->ready ? "" : gr)); } else { G_centerprint(p, "%s", txt); } } self->s.v.nextthink = g_globalvars.time + 1; } void AdminForceStart(void) { gedict_t *mess; if (match_in_progress || match_over || !is_adm(self)) { return; } // no forcestart in practice mode if (k_practice) { G_sprint(self, 2, "%s\n", redtext("Server in practice mode")); return; } if ((self->ct == ctPlayer) && !self->ready) { PlayerReady(true); if (!self->ready) { G_sprint(self, 2, "Ready yourself first\n"); return; } } if (find(world, FOFCLSN, "mess")) { G_sprint(self, 2, "forcestart already in progress!\n"); return; } k_attendees = CountPlayers(); if (!isCanStart(self, true)) { G_sprint(self, 2, "Can't issue!\n"); return; } if (k_attendees) { G_bprint(2, "%s forces matchstart!\n", self->netname); k_force = 1; localcmd("serverinfo status Forcestart\n"); mess = spawn(); mess->classname = "mess"; mess->s.v.owner = EDICT_TO_PROG(self); mess->think = (func_t) ReadyThink; mess->s.v.nextthink = g_globalvars.time + 0.1; mess->attack_finished = 10 + 1; } else { G_sprint(self, 2, "Can't issue! More players needed.\n"); } } void AdminForceBreak(void) { if (is_adm(self) && (self->ct != ctPlayer) && !match_in_progress) { k_force = 0; localcmd("serverinfo status Standby\n"); return; } if (!is_adm(self) || !match_in_progress) { return; } if ((self->ct != ctPlayer) && (match_in_progress == 1)) { k_force = 0; StopTimer(1); return; } if (k_oldmaxspeed) // huh??? { cvar_fset("sv_maxspeed", k_oldmaxspeed); } G_bprint(2, "%s forces a break!\n", self->netname); EndMatch(0); } void AdminForceMap(void) { char map[128]; if (!is_adm(self)) { return; } if (!k_matchLess && match_in_progress) { G_sprint(self, 2, "Match currently in progress. Use %s or %s to terminate.\n", redtext("break"), redtext("forcebreak")); return; } if (trap_CmdArgc() < 2) { G_sprint(self, 2, "Usage: forcemap %s\n", redtext("")); return; } trap_CmdArgv(1, map, sizeof(map)); if (GetMapNum(map) <= 0) { G_sprint(self, 2, "Map %s not available on this server.\n", redtext(map)); return; } G_bprint(2, "%s forces a map change to %s!\n", self->netname, redtext(map)); changelevel(map); } void PlayerStopFire(gedict_t *p) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "-attack\n"); p->wreg_attack = 0; } void PlayersStopFire(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { PlayerStopFire(p); } } void TogglePreWar(void) { int k_prewar = bound(0, cvar("k_prewar"), 2); if (!is_adm(self)) { return; } if (++k_prewar > 2) { k_prewar = 0; } switch (k_prewar) { case 1: if (!match_in_progress) { G_bprint(2, "Players may fire before match\n"); } else { G_sprint(self, 2, "Players may fire before match\n"); } break; case 2: if (!match_in_progress) { G_bprint(2, "Players may fire and jump when %s\n", redtext("ready")); PlayersStopFire(); } else { G_sprint(self, 2, "Players may fire and jump when %s\n", redtext("ready")); } break; case 0: default: if (!match_in_progress) { G_bprint(2, "Players may %s fire before match\n", redtext("not")); PlayersStopFire(); } else { G_sprint(self, 2, "Players may %s fire before match\n", redtext("not")); } break; } cvar_fset("k_prewar", k_prewar); } void ToggleMapLock(void) { float tmp; if (!is_adm(self)) { return; } tmp = cvar("k_lockmap"); if (tmp) { cvar_fset("k_lockmap", 0); if (!match_in_progress) { G_bprint(2, "%s unlocks map\n", self->netname); } else { G_sprint(self, 2, "Map unlocked\n"); } return; } cvar_fset("k_lockmap", 1); if (!match_in_progress) { G_bprint(2, "%s locks map\n", self->netname); } else { G_sprint(self, 2, "Map is locked\n"); } } void ToggleFallBunny(void) { if (match_in_progress) { return; } if (isRACE()) { G_sprint(self, 2, "Command blocked because race mode is active\n"); return; } if (k_yawnmode) { G_sprint(self, 2, "Command blocked because yawnmode is active\n"); return; } cvar_toggle_msg(self, "k_fallbunny", redtext("fallbunny")); } void sv_lock(void) { int lock_time = 15; if (!k_sv_locktime) { G_bprint(2, "%s %s for %s seconds\n", getname(self), redtext("locked server"), dig3(lock_time)); k_sv_locktime = g_globalvars.time + lock_time; } else { G_bprint(2, "%s %s\n", getname(self), redtext("unlocked server")); k_sv_locktime = 0; } } // assuming kicker is admin qbool is_can_forcespec(gedict_t *victim, gedict_t *kicker) { if (VIP_IsFlags(victim, VIP_NOTKICKABLE) && !is_real_adm(kicker)) { G_sprint(kicker, 2, "You can't force_spec VIP \x8D %s as elected admin\n", (strnull(victim->netname) ? "!noname!" : victim->netname)); return false; } if (is_real_adm(victim) && !is_real_adm(kicker)) { G_sprint(kicker, 2, "You can't force_spec real admin \x8D %s as elected admin\n", (strnull(victim->netname) ? "!noname!" : victim->netname)); return false; } return true; } void do_force_spec(gedict_t *p, gedict_t *admin, qbool spec) { // If admin == NULL, was by vote if (admin != NULL && !is_can_forcespec(p, admin)) { return; } G_sprint(p, 2, "You were forced to reconnect as %s by the admin\n", spec ? "spectator" : "player"); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, spec ? "spectator 1\n" : "spectator \"\"\n"); if (!strnull(ezinfokey(p, "Qizmo"))) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "say ,:dis\nwait;wait;wait; say ,:reconnect\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "disconnect\nwait;wait;reconnect\n"); } } // ktpro (c) void force_spec(void) { qbool found = false; gedict_t *p = NULL; char *c_fs, arg_2[1024]; int i_fs, argc = trap_CmdArgc(); if (!is_adm(self)) { return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); c_fs = (argc >= 2 ? arg_2 : ezinfokey(self, "fs")); if (strnull(c_fs)) { G_sprint(self, 2, "set setinfo \"fs\" properly\n"); G_sprint(self, 2, "to force spec all not ready players\n"); G_sprint(self, 2, "type: %s\n", redtext("setinfo fs \"*\"")); G_sprint(self, 2, "or: %s to force spec specified player\n", redtext("setinfo fs \"playername\"")); G_sprint(self, 2, "or just: %s\n", redtext("/force_spec \"playername\"")); return; } if (streq(c_fs, "*") || streq(c_fs, "* ")) { //ok move all not ready players to specs for (p = world; (p = find_plr(p));) { if (p->ready || (p == self)) { continue; } found = true; do_force_spec(p, self, true); } } else { p = ((i_fs = atoi(c_fs)) < 0 ? spec_by_id(-i_fs) : SpecPlayer_by_IDorName(c_fs)); if (p) { found = true; do_force_spec(p, self, p->ct != ctSpec); } } if (!found) { G_sprint(self, 2, "can't find specified players\n"); } } QW-Group-ktx-d05d6ca/src/arena.c000066400000000000000000000375771475442401000164740ustar00rootroot00000000000000/* * Copyright (C) 1997 David 'crt' Wright * * $Id$ */ // arena.c - rocket arena stuff #include "g_local.h" void setnowep(gedict_t *anent); void SetWinner(gedict_t *p); void SetLoser(gedict_t *p); void SetNone(gedict_t *p); gedict_t *ra_que[MAX_CLIENTS]; void ra_init_que(void) { memset(ra_que, 0, sizeof(ra_que)); } // return first element in ra queue, return NULL if queue empty gedict_t* ra_que_first(void) { return ra_que[0]; } // add element to end of ra queue void ra_in_que(gedict_t *p) { int i; if (!p) { G_Error("ra_in_que: null"); } for (i = 0; i < MAX_CLIENTS; i++) { if (!ra_que[i]) { // ok, we found empty space, add ra_que[i] = p; p->ra_pt = raQue; // mark player - he in queue now if (CountPlayers() > 2) // if only two players, no reason of such messages { G_sprint(p, PRINT_HIGH, "You are %s in line\n", (!i ? "next" : "last")); } return; } } G_Error("ra_in_que: full"); } // remove element from ra queue void ra_out_que(gedict_t *p) { int i; if (!p) { G_Error("ra_out_que: null"); } for (i = 0; i < MAX_CLIENTS; i++) { if (ra_que[i] == p) { // ok, we found element SetNone(p); // mark player - he NOT in queue now for (; i < MAX_CLIENTS && ra_que[i]; i++) // move along other elements { ra_que[i] = ((i + 1 < MAX_CLIENTS) ? ra_que[i + 1] : NULL); } return; } } G_Error("ra_out_que: not found"); } // check if element is in ra queue qbool ra_isin_que(gedict_t *p) { int i; if (!p) { G_Error("ra_isin_que: null"); } for (i = 0; i < MAX_CLIENTS && ra_que[i]; i++) { if (ra_que[i] == p) // ok, we found { return true; } } return false; } // return element postion in ra queue, -1 if not in que int ra_pos_que(gedict_t *p) { int i; if (!p) { G_Error("ra_pos_que: null"); } for (i = 0; i < MAX_CLIENTS && ra_que[i]; i++) { if (ra_que[i] == p) // ok, we found { return i; } } return -1; } // ra is just modificator of duel qbool isRA(void) { return (isDuel() && cvar("k_rocketarena")); } qbool isWinner(gedict_t *p) { return (p->ra_pt == raWinner); } qbool isLoser(gedict_t *p) { return (p->ra_pt == raLoser); } gedict_t* getWinner(void) { gedict_t *p; for (p = g_edicts + 1; p <= g_edicts + MAX_CLIENTS; p++) { if ((p->ct == ctPlayer) && isWinner(p)) { return p; } } return NULL; } gedict_t* getLoser(void) { gedict_t *p; for (p = g_edicts + 1; p <= g_edicts + MAX_CLIENTS; p++) { if ((p->ct == ctPlayer) && isLoser(p)) { return p; } } return NULL; } void SetWinner(gedict_t *p) { p->ra_pt = raWinner; } void SetLoser(gedict_t *p) { p->ra_pt = raLoser; } void SetNone(gedict_t *p) { p->ra_pt = raNone; } void ra_ClientDisconnect(void) { gedict_t *p = NULL; if (!isRA()) { return; } if (isWinner(self)) { G_bprint(PRINT_HIGH, "The %s has left\n", redtext("winner")); if ((p = getLoser())) { p->s.v.takedamage = DAMAGE_NO; // no damage to loser since winner is left game } ra_match_fight = 0; } else if (isLoser(self)) { G_bprint(PRINT_HIGH, "The %s has left\n", redtext("challenger")); if ((p = getWinner())) { p->s.v.takedamage = DAMAGE_NO; // no damage to winner since loser is left game } ra_match_fight = 0; } else if (self == ra_que_first()) { G_bprint(PRINT_HIGH, "The %s has left\n", redtext("line leader")); } if (ra_isin_que(self)) // in the queue { ra_out_que(self); // remove from queue } SetNone(self); } void ra_ClientObituary(gedict_t *targ, gedict_t *attacker) { int ah, aa; gedict_t *loser, *winner; if (!isRA()) { return; } if (targ->ct != ctPlayer) { return; // so below targ is player } ra_match_fight = 0; if (attacker->ct != ctPlayer) { attacker = targ; // seems killed self } if ((loser = getLoser())) // stop them from attacking during countdown { loser->s.v.takedamage = DAMAGE_NO; PlayerStopFire(loser); } if ((winner = getWinner())) // stop them from attacking during countdown { winner->s.v.takedamage = DAMAGE_NO; PlayerStopFire(winner); } if (!loser || !winner) { // just wanna know is that possible somehow if (!loser) { G_bprint(PRINT_HIGH, "BUG: ra_ClientObituary without loser\n"); } if (!winner) { G_bprint(PRINT_HIGH, "BUG: ra_ClientObituary without winner\n"); } return; // require both } ah = attacker->s.v.health; aa = attacker->s.v.armorvalue; if (targ == winner) { winner->ps.loses += 1; loser->ps.wins += 1; G_bprint(PRINT_HIGH, "The %s %s has been defeated\n", redtext("winner"), getname(winner)); if (targ == attacker) { G_bprint(PRINT_HIGH, "by %s!\n", g_himself(winner)); // Self death gives the point to the opponent loser->s.v.frags += 1; } ra_in_que(winner); // move to que winner setfullwep(loser); } else if (targ == loser) { loser->ps.loses += 1; winner->ps.wins += 1; G_bprint(PRINT_HIGH, "The %s %s has failed\n", redtext("challenger"), getname(loser)); if (targ == attacker) { G_bprint(PRINT_HIGH, "because %s became bored with life!\n", g_he(loser)); // Self death gives the point to the opponent winner->s.v.frags += 1; } ra_in_que(loser); // move to que loser setfullwep(winner); } else { // just wanna know is that possible somehow G_bprint(PRINT_HIGH, "BUG: ra_ClientObituary unknown targ\n"); } if (attacker->ct == ctPlayer) { if (attacker != targ) { if ((ah == 100) && (aa == 200)) { G_bprint(PRINT_HIGH, "%s\n", redtext("FLAWLESS Victory!")); // TODO replace RA sounds (but world precached) //sound (world, CHAN_AUTO + CHAN_NO_PHS_ADD, "ra/flawless.wav", 1, ATTN_NONE); } else { G_bprint(PRINT_HIGH, "%s %s \x90%s\x91 %s \x90%s\x91 %s\n", redtext(getname(attacker)), redtext("had"), dig3(ah), redtext("health and"), dig3(aa), redtext("armor left")); if ((ah >= 75) && (aa >= 100)) { // TODO replace RA sounds (but world precached) //sound (world, CHAN_AUTO + CHAN_NO_PHS_ADD, "ra/excelent.wav", 1, ATTN_NONE); } } attacker->s.v.frags += 1; } logfrag(attacker, targ); } } void ra_PutClientInServer(void) { if (!isRA()) { return; } setnowep(self); // basic shit, even for qued player if (isWinner(self) || isLoser(self)) { VectorScale(g_globalvars.v_forward, 300, self->s.v.velocity); setfullwep(self); // shit for winner or loser } else { self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_NOCLIP; self->vw_index = 0; setmodel(self, ""); setorigin(self, PASSVEC3(self->s.v.origin)); } } void setnowep(gedict_t *anent) { gedict_t *swap; anent->s.v.ammo_shells = 10; // wtf 10 ? anent->s.v.ammo_nails = 0; anent->s.v.ammo_shells = 0; anent->s.v.ammo_rockets = 0; anent->s.v.ammo_cells = 0; anent->s.v.takedamage = DAMAGE_NO; anent->s.v.items = 0; anent->s.v.armorvalue = 0; anent->s.v.armortype = 0; anent->s.v.health = 100; anent->s.v.weapon = IT_AXE; //just to NOT have view_svmodel 0 forced on client anent->idletime = 0; anent->lasttime = 0; anent->laststattime = 0; swap = self; self = anent; // drop down to best weapon actually hold if (!((int)self->s.v.weapon & (int)self->s.v.items)) { self->s.v.weapon = W_BestWeapon(); } W_SetCurrentAmmo(); self = swap; } void setfullwep(gedict_t *anent) { gedict_t *swap; int i; qbool add = (match_start_time == g_globalvars.time ? false : true); // ammo anent->s.v.ammo_nails = min(200, (add ? anent->s.v.ammo_nails : 0) + 80); anent->s.v.ammo_shells = min(100, (add ? anent->s.v.ammo_shells : 0) + 30); anent->s.v.ammo_rockets = min(100, (add ? anent->s.v.ammo_rockets : 0) + 30); anent->s.v.ammo_cells = min(100, (add ? anent->s.v.ammo_cells : 0) + 30); // weapons anent->s.v.items = IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING; // armor anent->s.v.items = (int)anent->s.v.items | IT_ARMOR3; anent->s.v.armorvalue = 200; anent->s.v.armortype = 0.8; // health anent->s.v.health = 100; // powerups anent->super_damage_finished = 0; anent->super_time = 0; anent->radsuit_finished = 0; anent->rad_time = 0; anent->invisible_finished = 0; anent->invisible_time = 0; anent->invincible_finished = 0; anent->invincible_time = 0; anent->s.v.effects = 0; anent->lastwepfired = 0; for (i = itNONE; i < itMAX; i++) { adjust_pickup_time(&anent->it_pickup_time[i], &anent->ps.itm[i].time); } for (i = wpNONE; i < wpMAX; i++) { adjust_pickup_time(&anent->wp_pickup_time[i], &anent->ps.wpn[i].time); } swap = self; self = anent; // drop down to best weapon actually hold if (!((int)self->s.v.weapon & (int)self->s.v.items)) { self->s.v.weapon = W_BestWeapon(); } W_SetCurrentAmmo(); self = swap; } qbool readytostart(void) { if (!isRA()) { return true; } return (time_to_start && (g_globalvars.time >= time_to_start) && getWinner() && getLoser()); } void PrintStats(gedict_t *who) { int i, owner = EDICT_TO_PROG(who); char buf[1024] = { 0 }; gedict_t *winner = getWinner(), *loser = getLoser(), *motd; if (!winner || !loser) { return; } for (motd = world; (motd = find(motd, FOFCLSN, "motd"));) { if (owner == motd->s.v.owner) { break; // no centerprint stats while have motd } } if ((i = iKey(who, "lra")) > 0) { i = bound(0, i, sizeof(buf) - 1); memset((void*) buf, (int)'\n', i); buf[i] = 0; } strlcat(buf, va("%s%.10s %3d:%3d %.10s %3d:%3d ", buf, getname(winner), (int)winner->s.v.armorvalue, (int)winner->s.v.health, getname(loser), (int)loser->s.v.armorvalue, (int)loser->s.v.health), sizeof(buf)); if ((i = iKey(who, "lra")) < 0) { int offset = strlen(buf); i = bound(0, -i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)'\n', i); buf[i + offset] = 0; } if (!motd && match_in_progress != 1) { G_centerprint(who, "%s", buf); } if (winner->s.v.health > 0) { who->s.v.armorvalue = winner->s.v.health; } if (loser->s.v.health > 0) { who->s.v.health = loser->s.v.health; } who->s.v.currentammo = ra_pos_que(who) + 1; who->laststattime = g_globalvars.time + PLAYERSTATTIME; } void ra_Frame(void) { static int last_r; int r; gedict_t *winner, *loser, *p; if (!isRA() || match_over) { return; } winner = getWinner(); loser = getLoser(); if (!winner || !loser) { ra_match_fight = 0; if (!winner && loser) { // promote loser since winner not present for some reason winner = loser; loser = NULL; G_bprint(PRINT_HIGH, "The new %s is %s\n", redtext("winner"), getname(winner)); SetWinner(winner); } if (!winner && (winner = ra_que_first())) { // still lack of winner ra_out_que(winner); G_bprint(PRINT_HIGH, "The new %s is %s\n", redtext("winner"), getname(winner)); SetWinner(winner); k_respawn(winner, true); // respawn player } if (!loser && (loser = ra_que_first())) { // lack of loser ra_out_que(loser); G_bprint(PRINT_HIGH, "The new %s is %s\n", redtext("challenger"), getname(loser)); SetLoser(loser); k_respawn(loser, true); // respawn player } if (!winner || !loser) { return; } } if ((ra_match_fight == 2) || (match_in_progress != 2)) { return; } if (!ra_match_fight) { // ok start ra timer ra_match_fight = 1; // ra countdown last_r = 999999999; time_to_start = g_globalvars.time + 13; } r = Q_rint(time_to_start - g_globalvars.time); if (r <= 0) { char *fight = redtext("FIGHT!"); gedict_t *first = ra_que_first(); // TODO replace RA sounds (but world precached) //sound (world, CHAN_AUTO + CHAN_NO_PHS_ADD, "ra/fight.wav", 1, ATTN_NONE); G_bprint(PRINT_HIGH, "%s vs. %s\n", getname(winner), getname(loser)); if (first) { G_bprint(PRINT_HIGH, "%s is next in line\n", getname(first)); } winner->s.v.takedamage = DAMAGE_AIM; loser->s.v.takedamage = DAMAGE_AIM; G_centerprint(winner, "%s", fight); G_centerprint(loser, "%s", fight); ra_match_fight = 2; // rounding suck, so this force readytostart() return true right after FIGHT! is printed time_to_start = g_globalvars.time; } else if (r != last_r) { last_r = r; if (r < 6) { // TODO replace RA sounds (but world precached) //sound (world, CHAN_AUTO + CHAN_NO_PHS_ADD, va("ra/%d.wav", r), 1, ATTN_NONE); for (p = world; (p = find_client(p));) { stuffcmd(p, "play buttons/switch04.wav\n"); } } if (r < 11) { G_centerprint(winner, "New challenger: %s\n\n%d", getname(loser), r); G_centerprint(loser, "Challenge the winner: %s\n\n%d", getname(winner), r); } } } void RocketArenaPre(void) { if (!isRA()) { return; } if (self->idletime != 0) { int r = Q_rint(self->idletime - g_globalvars.time); if (r != self->lasttime) { self->lasttime = r; if (r == 60) { G_sprint(self, PRINT_HIGH, "You have 1 minute left\n" "%s to get back in line\n", redtext("ra_break")); stuffcmd(self, "play player/axhit1.wav\n"); } else if (r == 30) { G_sprint(self, PRINT_HIGH, "You have 30 seconds left\n" "%s to get back in line\n", redtext("ra_break")); stuffcmd(self, "play player/axhit1.wav\n"); } else if (r > 0 && r <= 10) { G_sprint(self, PRINT_HIGH, "You have %d second%s left to get in line\n", r, count_s(r)); stuffcmd(self, "play player/axhit1.wav\n"); } else if (r <= 0) { self->idletime = 0; G_sprint(self, PRINT_HIGH, "Sorry, your wait time has expired!\n"); G_bprint(PRINT_HIGH, "%s stood around too long\n", getname(self)); stuffcmd(self, "play player/death1.wav\n"); stuffcmd(self, "disconnect\n"); // FIXME: stupid way return; } } } if (!isWinner(self) && !isLoser(self) && (self->laststattime < g_globalvars.time)) { PrintStats(self); } } // { ra commands void ra_PlayerStats(void) { gedict_t *p; int i, pL = 0; if (!isRA()) { return; } if (match_in_progress != 2) { G_sprint(self, 2, "no game - no statistics\n"); return; } for (p = world; (p = find_plr(p));) { pL = max(pL, strlen(p->netname)); } pL = bound(strlen("Name"), pL, 10); G_sprint(self, 2, "%s:\n" "%.10s", redtext("Player statistics"), redtext("Name")); for (i = strlen("Name"); i < pL; i++) { G_sprint(self, 2, " "); // dynamically pad name } G_sprint(self, 2, " %s %s %s \217 %s\245\n", redtext("Frags"), redtext("Wins"), redtext("Loses"), redtext("Effi")); G_sprint( self, 2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236"); for (i = 0; i < pL; i++) { G_sprint(self, 2, "\236"); // dynamically pad name } G_sprint(self, 2, "\237\n"); for (p = world; (p = find_plr(p));) { G_sprint(self, 2, "%.10s", p->netname); // player name for (i = strlen(p->netname); i < pL; i++) { G_sprint(self, 2, " "); // dynamically pad name } G_sprint(self, 2, " %5d", (int)p->s.v.frags); // Frags G_sprint(self, 2, " %4d", p->ps.wins); // Wins G_sprint(self, 2, " %5d", p->ps.loses); // Loses p->efficiency = ((p->ps.loses + p->ps.wins) ? (p->ps.wins * 100.0f) / (p->ps.loses + p->ps.wins) : 0); G_sprint(self, 2, " \217 %6.1f\n", p->efficiency); // effi } } void ra_PrintPos(void) { int pos; if (!isRA() || isWinner(self) || isLoser(self)) { return; } if ((pos = ra_pos_que(self)) < 0) { G_sprint(self, PRINT_HIGH, "You are out of line\n" "%s to return\n", redtext("ra_break")); return; } if (!pos) { G_sprint(self, PRINT_HIGH, "You are next\n"); return; } if (pos == 1) { G_sprint(self, PRINT_HIGH, "There is 1 person ahead of you\n"); return; } if (pos > 1) { G_sprint(self, PRINT_HIGH, "There are %d people ahead of you\n", pos); return; } } void ra_break(void) { if (!isRA() || isWinner(self) || isLoser(self)) { return; } if (ra_isin_que(self)) // take OUT of line { G_sprint(self, PRINT_HIGH, "You can have up to a 5 minute break\n" "%s to get back in line\n", redtext("ra_break")); self->idletime = g_globalvars.time + MAXIDLETIME; ra_out_que(self); } else // put INTO line { self->idletime = 0; ra_in_que(self); } } QW-Group-ktx-d05d6ca/src/bg_lib.c000066400000000000000000000266121475442401000166100ustar00rootroot00000000000000/* * $Id$ */ // Copyright (C) 1999-2000 Id Software, Inc. // // bg_lib.c -- standard C library replacement routines used by code // compiled for the virtual machine #include "q_shared.h" #include "rng.h" size_t strlen(const char *string) { const char *s; s = string; while (*s) { s++; } return (s - string); } char* strcat(char *strDestination, const char *strSource) { char *s; s = strDestination; while (*s) { s++; } while (*strSource) { *s++ = *strSource++; } *s = 0; return strDestination; } char* strcpy(char *strDestination, const char *strSource) { char *s; s = strDestination; while (*strSource) { *s++ = *strSource++; } *s = 0; return strDestination; } char* strchr(const char *string, int c) { while (*string) { if (*string == c) { return (char*)string; } string++; } if (!c) { return (char*)string; } return (char*)0; } // qqshka: have no example, so do my'n own, dunno good or bad char* strrchr(const char *string, int c) { char *from = (char*) string + strlen(string); while (from >= string) { if (*from == c) { return from; } from--; } return (char*)0; } char* strstr(const char *string, const char *strCharSet) { while (*string) { int i; for (i = 0; strCharSet[i]; i++) { if (string[i] != strCharSet[i]) { break; } } if (!strCharSet[i]) { return (char*)string; } string++; } return (char*)0; } int tolower(int c) { if ((c >= 'A') && (c <= 'Z')) { c += 'a' - 'A'; } return c; } int toupper(int c) { if ((c >= 'a') && (c <= 'z')) { c += 'A' - 'a'; } return c; } void* memmove(void *dest, const void *src, size_t count) { int i; if (dest > src) { for (i = count - 1; i >= 0; i--) { ((char*) dest)[i] = ((char*) src)[i]; } } else { for (i = 0; i < (int)count; i++) { ((char*) dest)[i] = ((char*) src)[i]; } } return dest; } //===================================== double tan(double x) { return (sin(x) / cos(x)); } int abs(int n) { return (n < 0 ? -n : n); } double fabs(double x) { return (x < 0 ? -x : x); } //===================================== static RngState rng_state = { 0 }; void srand(unsigned seed) { rng_seed(&rng_state, (int)seed); } int rand(void) { return (int)rng_next(&rng_state); } //===================================== double atof(const char *string) { float sign; float value; int c; // skip whitespace while (*string <= ' ') { if (!*string) { return 0; } string++; } // check sign switch (*string) { case '+': string++; sign = 1; break; case '-': string++; sign = -1; break; default: sign = 1; break; } // read digits value = 0; c = string[0]; if (c != '.') { do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value = value * 10 + c; } while (1); } else { string++; } // check for decimal point if (c == '.') { double fraction; fraction = 0.1; do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value += c * fraction; fraction *= 0.1; } while (1); } // not handling 10e10 notation... return (value * sign); } double _atof(const char **stringPtr) { const char *string; float sign; float value; int c = '0'; // bk001211 - uninitialized use possible string = *stringPtr; // skip whitespace while (*string <= ' ') { if (!*string) { *stringPtr = string; return 0; } string++; } // check sign switch (*string) { case '+': string++; sign = 1; break; case '-': string++; sign = -1; break; default: sign = 1; break; } // read digits value = 0; if (string[0] != '.') { do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value = value * 10 + c; } while (1); } // check for decimal point if (c == '.') { double fraction; fraction = 0.1; do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value += c * fraction; fraction *= 0.1; } while (1); } // not handling 10e10 notation... *stringPtr = string; return (value * sign); } int atoi(const char *string) { int sign; int value; int c; // skip whitespace while (*string <= ' ') { if (!*string) { return 0; } string++; } // check sign switch (*string) { case '+': string++; sign = 1; break; case '-': string++; sign = -1; break; default: sign = 1; break; } // read digits value = 0; do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value = value * 10 + c; } while (1); // not handling 10e10 notation... return (value * sign); } int _atoi(const char **stringPtr) { int sign; int value; int c; const char *string; string = *stringPtr; // skip whitespace while (*string <= ' ') { if (!*string) { return 0; } string++; } // check sign switch (*string) { case '+': string++; sign = 1; break; case '-': string++; sign = -1; break; default: sign = 1; break; } // read digits value = 0; do { c = *string++; if ((c < '0') || (c > '9')) { break; } c -= '0'; value = value * 10 + c; } while (1); // not handling 10e10 notation... *stringPtr = string; return (value * sign); } //========================================================= #define ALT 0x00000001 /* alternate form */ #define HEXPREFIX 0x00000002 /* add 0x or 0X prefix */ #define LADJUST 0x00000004 /* left adjustment */ #define LONGDBL 0x00000008 /* long double */ #define LONGINT 0x00000010 /* long integer */ #define QUADINT 0x00000020 /* quad integer */ #define SHORTINT 0x00000040 /* short integer */ #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */ #define FPT 0x00000100 /* floating point number */ #define to_digit(c) ((c) - '0') #define is_digit(c) ((unsigned)to_digit(c) <= 9) #define to_char(n) ((n) + '0') void AddInt(char **buf_p, int val, int width, int flags) { char text[32]; int digits; int signedVal; char *buf; digits = 0; signedVal = val; if (val < 0) { val = -val; } do { text[digits++] = '0' + val % 10; val /= 10; } while (val); if (signedVal < 0) { text[digits++] = '-'; } buf = *buf_p; if (!(flags & LADJUST)) { while (digits < width) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; width--; } } while (digits--) { *buf++ = text[digits]; width--; } if (flags & LADJUST) { while (width--) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; } } *buf_p = buf; } void AddFloat(char **buf_p, float fval, int width, int prec, int flags) { char text[32]; int digits; int prec_len, len; float signedVal; char *buf; int val; // set sanity precison if ((prec < 0) || (prec > 6)) { prec = 6; } prec_len = prec ? (prec + 1) : 0; // get the sign signedVal = fval; if (fval < 0) { fval = -fval; } // write the float number digits = 0; val = (int)fval; do { text[digits++] = '0' + val % 10; val /= 10; } while (val); if (signedVal < 0) { text[digits++] = '-'; } buf = *buf_p; len = digits; if (!(flags & LADJUST)) { // right adjust while ((len + prec_len) < width) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; width--; } } while (digits--) { *buf++ = text[digits]; } *buf_p = buf; // write the fraction digits = 0; while (digits < prec) { fval -= (int)fval; fval *= 10.0; val = (int)fval; text[digits++] = '0' + val % 10; } if (digits > 0) { buf = *buf_p; *buf++ = '.'; for (prec = 0; prec < digits; prec++) { *buf++ = text[prec]; } *buf_p = buf; } if (flags & LADJUST) { // left adjust buf = *buf_p; while ((len + prec_len) < width) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; width--; } *buf_p = buf; } } void AddString(char **buf_p, char *string, int width, int prec, int flags) { int size; char *buf; buf = *buf_p; if (string == NULL) { string = "(null)"; prec = -1; } if (prec >= 0) { for (size = 0; size < prec; size++) { if (string[size] == '\0') { break; } } } else { size = strlen(string); } width -= size; if (!(flags & LADJUST)) { // right adjust while (width-- > 0) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; } } while (size--) { *buf++ = *string++; } if (flags & LADJUST) { // left adjust while (width-- > 0) { *buf++ = (flags & ZEROPAD) ? '0' : ' '; } } *buf_p = buf; } /* vsprintf I'm not going to support a bunch of the more arcane stuff in here just to keep it simpler. For example, the '*' and '$' are not currently supported. I've tried to make it so that it will just parse and ignore formats we don't support. */ int vsprintf(char *buffer, const char *fmt, va_list argptr) { int *arg; char *buf_p; char ch; int flags; int width; int prec; int n; char sign; buf_p = buffer; arg = (int*) argptr; while (true) { // run through the format string until we hit a '%' or '\0' for (ch = *fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) { *buf_p++ = ch; } if (ch == '\0') { goto done; } // skip over the '%' fmt++; // reset formatting state flags = 0; width = 0; prec = -1; sign = '\0'; rflag: ch = *fmt++; reswitch: switch (ch) { case '-': flags |= LADJUST; goto rflag; case '.': n = 0; while (is_digit((ch = *fmt++))) { n = 10 * n + (ch - '0'); } prec = n < 0 ? -1 : n; goto reswitch; case '0': flags |= ZEROPAD; goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + (ch - '0'); ch = *fmt++; } while (is_digit(ch)); width = n; goto reswitch; case 'c': *buf_p++ = (char) *arg; arg++; break; case 'd': case 'i': AddInt(&buf_p, *arg, width, flags); arg++; break; case 'f': AddFloat(&buf_p, *(double*) arg, width, prec, flags); #ifdef __LCC__ arg += 1; // everything is 32 bit in my compiler #else arg += 2; #endif break; case 's': AddString(&buf_p, (char*) *arg, width, prec, flags); arg++; break; case '%': *buf_p++ = ch; break; default: *buf_p++ = (char) *arg; arg++; break; } } done: *buf_p = 0; return (buf_p - buffer); } /* this is really crappy */ int sscanf(const char *buffer, const char *fmt, ...) { int cmd; int **arg; int count; arg = (int**) &fmt + 1; count = 0; while (*fmt) { if (fmt[0] != '%') { fmt++; continue; } cmd = fmt[1]; fmt += 2; switch (cmd) { case 'i': case 'd': case 'u': **arg = _atoi(&buffer); break; case 'f': *(float*) *arg = _atof(&buffer); break; } arg++; } return count; } // ignore count :( int Q_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) { int ret; if (!count) { return 0; } ret = vsprintf(buffer, format, argptr); buffer[count - 1] = 0; return ret; } // ignore count :( int snprintf(char *buffer, size_t count, char const *format, ...) { int ret; va_list argptr; if (!count) { return 0; } va_start(argptr, format); ret = Q_vsnprintf(buffer, count, format, argptr); // which is ignore count :( buffer[count - 1] = 0; va_end(argptr); return ret; } double fmod(double x, double y) { double result = x; if (y == 0.0) { return 0.0 / 0.0; // Undefined } while (result >= y) { result -= y; } while (result < 0) { result += y; } return result; } QW-Group-ktx-d05d6ca/src/bot_aim.c000066400000000000000000000320151475442401000167760ustar00rootroot00000000000000// bot_aim.c #ifdef BOT_SUPPORT #include "g_local.h" #define YAW_SNAP_THRESHOLD 4 #define PITCH_SNAP_THRESHOLD 6 #define ATTACK_RESPAWN_TIME 3 qbool DM6FireAtDoor(gedict_t *self, vec3_t rel_pos); static void BotsModifyAimAtPlayerLogic(gedict_t *self); static void BotSetDesiredAngles(gedict_t *self, vec3_t rel_pos) { vectoangles(rel_pos, self->fb.desired_angle); if (self->fb.desired_angle[0] > 180) { self->fb.desired_angle[0] = 360 - self->fb.desired_angle[0]; } else { self->fb.desired_angle[0] = 0 - self->fb.desired_angle[0]; } // FIXME if (self->fb.state & HURT_SELF) { self->fb.desired_angle[0] = 180; } if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd_flags(self, STUFFCMD_DEMOONLY, "//botcmd-desired %f %f %f %f\n", g_globalvars.time, PASSVEC3(self->fb.desired_angle)); } if (self->fb.look_object->ct == ctPlayer) { BotsModifyAimAtPlayerLogic(self); if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd_flags(self, STUFFCMD_DEMOONLY, "//botcmd-modified %f %f %f %f\n", g_globalvars.time, PASSVEC3(self->fb.desired_angle)); } } } static void BotStopFiring(gedict_t *bot) { qbool continuous = bot->fb.desired_weapon_impulse == 4 || bot->fb.desired_weapon_impulse == 5 || bot->fb.desired_weapon_impulse == 8; qbool correct_weapon = BotUsingCorrectWeapon(bot); qbool enemy_alive = bot->s.v.enemy && ISLIVE(&g_edicts[bot->s.v.enemy]); bot->fb.firing &= (continuous && correct_weapon && enemy_alive) || bot->fb.rocketJumping; } // Magic numbers here: 400 = 0.5 * sv_gravity static qbool PredictSpot(gedict_t *self, gedict_t *enemy_, vec3_t testplace, float rel_time, float fallheight) { VectorCopy(testplace, dropper->s.v.origin); dropper->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (walkmove(dropper, 0, 0)) { if (!droptofloor(dropper)) { testplace[2] = testplace[2] - 400 * (rel_time * rel_time) - 38; return false; } if (dropper->s.v.origin[2] < fallheight) { testplace[2] = testplace[2] - 400 * (rel_time * rel_time) - 38; return false; } return true; } VectorCopy(enemy_->s.v.origin, testplace); return false; } static float EstimateTimeBasedOnSkill(gedict_t *self, float original_time) { float dist = self->fb.skill.movement_estimate_error; return dist_random(original_time * (1 - dist), original_time * (1 + dist), 2); } static qbool PredictEnemyLocationInFuture(gedict_t *enemy, float rel_time) { vec3_t testplace; float fallheight = enemy->s.v.origin[2] - 56 + enemy->s.v.velocity[2] * EstimateTimeBasedOnSkill(self, rel_time); float old_solid = enemy->s.v.solid; qbool predicted = false; enemy->s.v.solid = SOLID_NOT; VectorMA(enemy->s.v.origin, rel_time, enemy->s.v.velocity, testplace); testplace[2] += 36; if (PredictSpot(self, enemy, testplace, rel_time, fallheight)) { VectorCopy(dropper->s.v.origin, self->fb.predict_origin); predicted = true; } else { vec3_t dir_forward; VectorSubtract(self->fb.predict_origin, enemy->s.v.origin, dir_forward); dir_forward[2] = 0; if ((vlen(dir_forward) > half_sv_maxspeed) || (DotProduct(dir_forward, enemy->s.v.velocity) <= 0)) { VectorCopy(testplace, self->fb.predict_origin); predicted = true; } } enemy->s.v.solid = old_solid; return predicted; } // This is when firing at buttons/doors etc static void BotsFireAtWorldLogic(gedict_t *self, vec3_t rel_pos, float *rel_dist) { VectorAdd(self->fb.look_object->s.v.absmin, self->fb.look_object->s.v.view_ofs, rel_pos); VectorSubtract(rel_pos, self->s.v.origin, rel_pos); *rel_dist = vlen(rel_pos); if (DM6FireAtDoor(self, rel_pos)) { return; } if (*rel_dist < 160) { vec3_t rel_pos2; VectorSet(rel_pos2, rel_pos[0], rel_pos[1], 0); VectorNormalize(rel_pos2); VectorScale(rel_pos2, 160, rel_pos2); rel_pos[0] = rel_pos2[0]; rel_pos[1] = rel_pos2[1]; *rel_dist = 160; } } /* static qbool IsHitscanWeapon (int impulse) { return impulse == 1 || impulse == 2 || impulse == 3 || impulse == 8; } */ static qbool IsVelocityWeapon(int impulse) { return (impulse == 4 || impulse == 5 || impulse == 6 || impulse == 7); } static qbool IsNailgun(int impulse) { return (impulse == 4 || impulse == 5); } // When firing at another player static void BotsAimAtPlayerLogic(gedict_t *self, vec3_t rel_pos, float *rel_dist) { float rel_time = 0; VectorSubtract(self->fb.look_object->s.v.origin, self->s.v.origin, rel_pos); *rel_dist = vlen(rel_pos); if (IsVelocityWeapon(self->fb.desired_weapon_impulse) && !AttackFinished(self)) { rel_time = *rel_dist / 1000; if (IsNailgun(self->fb.desired_weapon_impulse) && (self->ctf_flag & CTF_RUNE_HST)) { rel_time /= (cvar("k_ctf_rune_power_hst") / 2) + 1; } else if (self->fb.desired_weapon_impulse == 6) { rel_time = *rel_dist / 600; } else if (cvar("k_midair") && (self->super_damage_finished > g_globalvars.time)) { rel_time *= 0.5; } if (self->s.v.enemy && (self->fb.look_object == &g_edicts[self->s.v.enemy])) { if (PredictEnemyLocationInFuture(&g_edicts[self->s.v.enemy], rel_time)) { if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd(self, "//botpredict\n"); } VectorSubtract(self->fb.predict_origin, self->s.v.origin, rel_pos); } else if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd(self, "//bot-nonpredict-1\n"); } } else if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd(self, "//bot-nonpredict-2 (%s)\n", self->fb.look_object ? self->fb.look_object->classname : "//"); } } else if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd(self, "//bot-nonpredict-3 (desired %d)\n", self->fb.desired_weapon_impulse); } } static qbool HorizontalVelocityCheck(vec3_t velocity, float threshold) { float value = velocity[0] * velocity[0] + velocity[1] * velocity[1]; return (value > (threshold * threshold)); } static void CalculateVolatility(gedict_t *self) { float volatility = self->fb.skill.current_volatility; gedict_t *opponent = self->fb.look_object; int vol_flags = 0; if (opponent != self->fb.prev_look_object) { // Treat as if they hadn't seen player before volatility = self->fb.skill.initial_volatility; self->fb.min_fire_time = g_globalvars.time + self->fb.skill.awareness_delay; self->fb.last_rndaim_time = 0; vol_flags = 1; } else { vec3_t bot_direction; vec3_t enemy_direction; float same_direction = 0.0f; VectorCopy(self->s.v.velocity, bot_direction); VectorCopy(opponent->s.v.velocity, enemy_direction); volatility *= self->fb.skill.reduce_volatility; // Ownspeed penalty if (HorizontalVelocityCheck(self->s.v.velocity, self->fb.skill.ownspeed_volatility_threshold)) { volatility += self->fb.skill.ownspeed_volatility; vol_flags = 2; } // Speed penalty if (HorizontalVelocityCheck(opponent->s.v.velocity, self->fb.skill.enemyspeed_volatility_threshold)) { volatility += self->fb.skill.enemyspeed_volatility; vol_flags |= 4; } VectorNormalize(bot_direction); VectorNormalize(enemy_direction); same_direction = DotProduct(bot_direction, enemy_direction); // Direction penalty ... if we're going in same direction, no penalty volatility += (1 - same_direction) * (self->fb.skill.enemydirection_volatility / 2); vol_flags |= 8; // Pain penalty - if they are being attacked, not as accurate if (!lgc_enabled() && self->fb.last_hurt && ((g_globalvars.time - self->fb.last_hurt) < 1.0f)) { volatility += self->fb.skill.pain_volatility; } // Midair penalty - if we're in midair, not as accurate if (!((int)self->s.v.flags & FL_ONGROUND_PARTIALGROUND)) { volatility += self->fb.skill.self_midair_volatility; } if (!((int)opponent->s.v.flags & FL_ONGROUND_PARTIALGROUND)) { volatility += self->fb.skill.opponent_midair_volatility; } volatility = bound(self->fb.skill.min_volatility, volatility * self->fb.skill.reduce_volatility, self->fb.skill.max_volatility); } self->fb.skill.current_volatility = volatility; } static float anglefix(float angle) { if (angle >= 180) { angle -= 360; } else if (angle <= -180) { angle += 360; } return angle; } // Called after desired angles have been set to aim at the player static void BotsModifyAimAtPlayerLogic(gedict_t *self) { fb_botaim_t *pitch = &self->fb.skill.aim_params[PITCH]; fb_botaim_t *yaw = &self->fb.skill.aim_params[YAW]; float raw_pitch_diff = anglefix( anglemod(self->fb.desired_angle[PITCH]) - anglemod(self->s.v.angles[PITCH])); float raw_yaw_diff = anglefix( anglemod(self->fb.desired_angle[YAW]) - anglemod(self->s.v.angles[YAW])); float pitch_rnd, yaw_rnd; float threshold_time; // Run every frame so it decreases correctly (also resets last_rndaim_time) CalculateVolatility(self); threshold_time = self->fb.firing ? ((int)self->s.v.weapon & (IT_LIGHTNING | IT_EITHER_NAILGUN) ? self->s.v.nextthink : self->attack_finished) - g_globalvars.frametime : self->fb.last_rndaim_time + 0.3; if (g_globalvars.time > threshold_time) { float pitch_diff, yaw_diff; //float lg_percent = (float)self->ps.wpn[wpLG].hits / max(1, self->ps.wpn[wpLG].attacks); pitch_diff = bound(pitch->minimum, fabs(raw_pitch_diff) * pitch->scale, pitch->maximum); yaw_diff = bound(yaw->minimum, fabs(raw_yaw_diff) * yaw->scale, yaw->maximum); pitch_rnd = dist_random(-pitch_diff, pitch_diff, pitch->multiplier * self->fb.skill.current_volatility); yaw_rnd = dist_random(-yaw_diff, yaw_diff, yaw->multiplier * self->fb.skill.current_volatility); if (g_random() < 0.8) { // Randomise the amount but not the side that we're aiming on yaw_rnd = (self->fb.last_rndaim[YAW] > 0 ? 1 : -1) * fabs(yaw_rnd); pitch_rnd = (self->fb.last_rndaim[PITCH] > 0 ? 1 : -1) * fabs(pitch_rnd); } self->fb.last_rndaim_time = g_globalvars.time; self->fb.last_rndaim[YAW] = yaw_rnd; self->fb.last_rndaim[PITCH] = pitch_rnd; } else { yaw_rnd = self->fb.last_rndaim[YAW]; pitch_rnd = self->fb.last_rndaim[PITCH]; } self->fb.desired_angle[PITCH] = bound(-70, self->fb.desired_angle[PITCH] + pitch_rnd, 80); self->fb.desired_angle[YAW] += yaw_rnd; } // Aim lower over longer distances? // FIXME: we already allow for gravity in predicting where to fire - should this test for the enemy being on the ground? static void BotsAimAtFloor(gedict_t *self, vec3_t rel_pos, float rel_dist) { qbool is_midair = cvar("k_midair"); if ((self->fb.desired_weapon_impulse == 7) && (rel_dist > 96) && !is_midair) { // If clear space below player... traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 16, self->s.v.origin[0] + rel_pos[0], self->s.v.origin[1] + rel_pos[1], self->s.v.origin[2] + rel_pos[2] - 22, true, self); if (g_globalvars.trace_fraction == 1) { rel_pos[2] -= 38; } } else if (is_midair) { // Always aim for the feet when player is on ground // FIXME: BotsAimAtPlayerLogic already sets rel_pos to origin, then SetFireButton raises it again, but we artificially lower it here... argh! if ((int)self->fb.look_object->s.v.flags & FL_ONGROUND) { rel_pos[2] -= 20; } } } static void FireAtSpawnPoint(gedict_t *self) { gedict_t *resp; for (resp = world; (resp = trap_findradius(resp, self->s.v.origin, 1000));) { if (streq(resp->classname, "info_player_deathmatch")) { vec3_t test; VectorCopy(self->s.v.origin, test); test[2] += 16; if (VectorDistance(resp->s.v.origin, test) > 160) { if (VisibleEntity(resp)) { float ang1, ang2; vec3_t diff; self->fb.desired_weapon_impulse = 7; self->fb.look_object = resp; VectorCopy(resp->s.v.origin, self->fb.predict_origin); self->fb.predict_origin[2] += 16; self->fb.old_linked_marker = NULL; VectorSubtract(resp->s.v.origin, self->s.v.origin, diff); ang2 = vectoyaw(diff); ang1 = anglemod(self->s.v.angles[1] - ang2); self->fb.firing |= (ang1 < 20 || ang1 > 340); return; } } } } } // When duelling, try and spawn frag. static void AttackRespawns(gedict_t *self) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; qbool has_rl = ((int)self->s.v.items & IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets > 3; if (isRA() || isHoonyModeDuel() || !isDuel()) { return; } if (ISDEAD(enemy_)) { if (enemy_->fb.last_death + ATTACK_RESPAWN_TIME >= g_globalvars.time) { if (self->fb.skill.attack_respawns) { if (has_rl && !self->fb.rocketJumping) { if (g_random() > 0.15) { FireAtSpawnPoint(self); } } } } } } void BotsFireLogic(void) { vec3_t rel_pos; BotStopFiring(self); AttackRespawns(self); // a_attackfix() if (!self->fb.rocketJumping && (self->s.v.enemy == 0) && !(self->fb.state & SHOT_FOR_LUCK)) { self->fb.firing = false; } if (self->fb.look_object) { float rel_dist = 0; if (self->fb.look_object->ct == ctPlayer) { BotsAimAtPlayerLogic(self, rel_pos, &rel_dist); } else { BotsFireAtWorldLogic(self, rel_pos, &rel_dist); } BotsAimAtFloor(self, rel_pos, rel_dist); if (!self->fb.rocketJumping) { SetFireButton(self, rel_pos, rel_dist); } BotSetDesiredAngles(self, rel_pos); } } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_blocked.c000066400000000000000000000116261475442401000176400ustar00rootroot00000000000000#ifdef BOT_SUPPORT #include "g_local.h" /* Okay, some explanation required here. Previous Frogbot logic was: Entity list: PrePhysics, , PostPhysics Each entity processed in turn... PostPhysics would check all previous frogbots to see if they were obstructed, and move in different direction instead In PR2 bots, we each bot sends command to server, and physics then match standard player movement, no cheating This makes finding obstruction more difficult, so instead mvdsv runs user command then calls Blocked, giving the bot a chance to send a new command and execute that instead When blocked() function is called, velocity/position/flags of where the bot would have ended up are stored: origin: g_globalvars.trace_endpos velocity: g_globalvars.trace_plane_normal flags: g_globalvars.trace_allsolid This is temporary kludge until I work out better solution. Really the bot should do this calculation first, or perhaps extend API to have G_SIMULATE_COMMAND? This is very basic attempt to not break API, while effectively (under the covers) changing the API. Ho hum. Long term goal is to replace this kind of "try...fail...try-something-else" logic with a navigation mesh, there would still need to be some collision detection for colliding with other players tho. */ static qbool obstruction(gedict_t *self, vec3_t new_velocity, vec3_t new_origin, int newFlags, vec3_t velocity_normal); // Gives us a chance to replace bot's command with another. void BotBlocked(void) { vec3_t blocked_velocity; vec3_t blocked_position; vec3_t velocity_normal; int blocked_flags = (int)g_globalvars.trace_allsolid; VectorCopy(g_globalvars.trace_endpos, blocked_position); VectorCopy(g_globalvars.trace_plane_normal, blocked_velocity); // Detect if we were obstructed & should try to change direction if (obstruction(self, blocked_velocity, blocked_position, blocked_flags, velocity_normal)) { vec3_t new_velocity; float yaw = vectoyaw(self->fb.obstruction_normal); float dist = 0; //removed: seems to be just scaling velocity to see if we can find new spot... // old code set velocity specifically which we don't need to do (?) VectorAdd(blocked_velocity, velocity_normal, new_velocity); //dist = ((new_velocity * frametime) - (self.origin - self.oldorigin)) * self.obstruction_normal; { vec3_t temp, originDiff; VectorScale(new_velocity, g_globalvars.frametime, temp); VectorSubtract(blocked_position, self->s.v.origin, originDiff); VectorSubtract(temp, originDiff, temp); dist = DotProduct(temp, self->fb.obstruction_normal); } VectorCopy(self->s.v.origin, dropper->s.v.origin); dropper->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (walkmove(dropper, yaw, dist)) { // Replace the command with moving in new direction new_velocity[2] = 0; //G_bprint (2, ".. [%f %f %f]", PASSVEC3(self->fb.dir_move_)); SetDirectionMove(self, self->fb.obstruction_normal, "Obstruction"); //G_bprint (2, "> [%f %f %f]\n", PASSVEC3(self->fb.dir_move_)); VectorClear(self->fb.obstruction_normal); } else { AvoidHazards(self); } BotSetCommand(self); return; } } //Sets self.obstruction_normal to be horizontal normal direction into wall obstruction encountered // during quake physics (ie. between PlayerPreThink and PlayerPostThink) // static qbool obstruction(gedict_t *self, vec3_t new_velocity, vec3_t new_origin, int newFlags, vec3_t velocity_normal) { vec3_t old_velocity; qbool onGround = (newFlags & FL_ONGROUND); qbool waterJump = (newFlags & FL_WATERJUMP); vec3_t delta_velocity = { 0 }; VectorCopy(self->fb.last_cmd_direction, old_velocity); VectorClear(velocity_normal); VectorSubtract(old_velocity, new_velocity, delta_velocity); if ((fabs(delta_velocity[0]) < 0.1) && (fabs(delta_velocity[1]) < 0.1)) { VectorClear(self->fb.obstruction_normal); return false; } // In mid-air and not swimming? Nothing we can do about it, wait to hit the ground... if (!onGround && ((!self->s.v.waterlevel) || waterJump)) { VectorClear(self->fb.obstruction_normal); return false; } // If not hitting ground... if (fabs(delta_velocity[2]) < 0.1) { vec3_t hor_velocity; VectorCopy(new_velocity, hor_velocity); hor_velocity[2] = 0; if ((hor_velocity[0] != 0) || (hor_velocity[1] != 0)) { VectorSubtract(old_velocity, hor_velocity, velocity_normal); velocity_normal[2] = 0; normalize(velocity_normal, self->fb.obstruction_normal); return true; } VectorCopy(old_velocity, hor_velocity); hor_velocity[2] = 0; if ((hor_velocity[0] != 0) || (hor_velocity[1] != 0)) { float cross_product = DotProduct(self->fb.obstruction_normal, old_velocity); VectorMA(old_velocity, -cross_product, self->fb.obstruction_normal, velocity_normal); velocity_normal[2] = 0; normalize(velocity_normal, self->fb.obstruction_normal); return true; } } // No obstruction VectorClear(self->fb.obstruction_normal); return false; } #endif QW-Group-ktx-d05d6ca/src/bot_botenemy.c000066400000000000000000000114611475442401000200540ustar00rootroot00000000000000/* bot/botenemy.qc Copyright (C) 1997-1999 Robert 'Frog' Field */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // Removes the look object for the given player void ClearLookObject(gedict_t *player) { player->fb.look_object = NULL; } // Sets the look object for the player void LookEnemy(gedict_t *player, gedict_t *enemy) { player->fb.look_object = enemy; VectorCopy(enemy->s.v.origin, player->fb.predict_origin); self->fb.old_linked_marker = NULL; } // Called when a player inflicts damage on another void BotDamageInflictedEvent(gedict_t *attacker, gedict_t *targ) { targ->fb.last_hurt = g_globalvars.time; if (targ->isBot) { // in dmm4, there's a chance taking damage will reset move direction if ((deathmatch >= 4) && (g_random() < targ->fb.skill.wiggle_toggle) && (abs(targ->fb.wiggle_run_dir) > (self->fb.skill.wiggle_run_limit / 2))) { targ->fb.wiggle_run_dir = targ->fb.wiggle_run_dir < 0 ? 1 : -1; } // if object we're looking at has less firepower than us... if (targ->fb.look_object && (targ->fb.look_object->fb.firepower < attacker->fb.firepower)) { if (attacker != targ) { // look at the attacker targ->fb.look_object = attacker; VectorCopy(attacker->s.v.origin, targ->fb.predict_origin); if (!SameTeam(attacker, targ)) { if (targ->s.v.goalentity == targ->s.v.enemy) { targ->fb.goal_refresh_time = 0; } targ->fb.enemy_time = g_globalvars.time + 1; targ->s.v.enemy = NUM_FOR_EDICT(attacker); } else { targ->fb.enemy_time = g_globalvars.time + 2.5; } } } } } // Triggered whenever an entity makes a noise void BotsSoundMadeEvent(gedict_t *entity) { if (entity && entity->ct == ctPlayer) { gedict_t *plr; // Find all bots which has this entity as enemy for (plr = world; (plr = find_plr(plr));) { if (plr->isBot && !(plr->fb.state & NOTARGET_ENEMY)) { if ((NUM_FOR_EDICT(entity) == plr->s.v.enemy) && (entity != plr->fb.look_object)) { vec3_t temp; VectorSubtract(entity->s.v.origin, plr->s.v.origin, temp); // Did the bot hear it? if (VectorLength(temp) < 1000) { if (Visible_360(plr, entity)) { // Look directly at the player plr->fb.look_object = entity; } else if (isDuel()) { if (entity->fb.touch_marker && Visible_360(plr, entity->fb.touch_marker)) { plr->fb.look_object = entity->fb.touch_marker; } else { // TODO: Look at the closest possible point // (think of picking up mega on DM4, humans would look at mega exit) // (find route from noise -> player, look at last visible marker?) } } } } } } } } // FIXME: Globals (from_marker, to_marker, etc) // Evaluates a potential enemy (globals: path_normal) static void BestEnemy_apply(gedict_t *test_enemy, float *best_score, gedict_t **enemy_, float *predict_dist) { float enemy_score; path_normal = true; look_marker = SightFromMarkerFunction(from_marker, to_marker); if (look_marker != NULL) { ZoneMarker(from_marker, look_marker, path_normal, test_enemy->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, look_marker, test_enemy->fb.canRocketJump); enemy_score = traveltime + g_random(); } else { look_marker = SightMarker(from_marker, to_marker, 0, 0); enemy_score = look_traveltime + g_random(); } if (enemy_score < *best_score) { vec3_t marker_view; vec3_t to_marker_view; VectorAdd(look_marker->s.v.absmin, look_marker->s.v.view_ofs, marker_view); VectorAdd(to_marker->s.v.absmin, to_marker->s.v.view_ofs, to_marker_view); *best_score = enemy_score; *enemy_ = test_enemy; *predict_dist = VectorDistance(marker_view, to_marker_view); } } // Selects best enemy from all players. // Evaluates based on time from respective last-touched markers // FIXME: evaluates in either direction (ease vs risk? fix) qbool BotsPickBestEnemy(gedict_t *self) { float best_score = 1000000; gedict_t *enemy_ = NULL; float predict_dist = 600; gedict_t *test_enemy; int old_enemy = self->s.v.enemy; qbool team_game = isTeam(); for (test_enemy = world; (test_enemy = find_plr(test_enemy));) { if ((!team_game || ISLIVE(test_enemy)) && !SameTeam(self, test_enemy)) { from_marker = test_enemy->fb.touch_marker; if (from_marker) { to_marker = self->fb.touch_marker; BestEnemy_apply(test_enemy, &best_score, &enemy_, &predict_dist); to_marker = from_marker; from_marker = self->fb.touch_marker; BestEnemy_apply(test_enemy, &best_score, &enemy_, &predict_dist); } } } self->fb.enemy_time = g_globalvars.time + 1; self->s.v.enemy = (enemy_ == NULL ? 0 : NUM_FOR_EDICT(enemy_)); self->fb.enemy_dist = predict_dist; return (self->s.v.enemy != old_enemy); } #endif QW-Group-ktx-d05d6ca/src/bot_botgoals.c000066400000000000000000000321351475442401000200450ustar00rootroot00000000000000/* bot/botgoals.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 2000-2001 DMSouL Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" //static float best_score; #define BACKPACK_CLASSNAME "backpack" #define FROGBOT_CHANCE_HELP_TEAMMATE 0.25 // FIXME: Local Globals static float best_respawn_time = 0; qbool POVDMM4DontWalkThroughDoor(gedict_t *goal_entity); qbool DM6DoorLogic(gedict_t *self, gedict_t *goal_entity); void SUB_regen(void); void SUB_regen_powerups(void); qbool WaitingToRespawn(gedict_t *ent) { return (((ent->s.v.nextthink >= g_globalvars.time) && (ent->think == (func_t)SUB_regen_powerups)) || ((ent->s.v.nextthink >= g_globalvars.time) && (ent->think == (func_t)SUB_regen))) && strnull(ent->model); } // If an item is picked up, all bots heading for that item should re-evaluate their goals void UpdateGoalEntity(gedict_t *item, gedict_t *taker) { gedict_t *plr; int item_entity = NUM_FOR_EDICT(item); for (plr = world; (plr = find_plr(plr));) { // if the same team, pretend bot read a 'took' notification qbool same_team = SameTeam(plr, taker); qbool heard_it = VectorDistance(plr->s.v.origin, item->s.v.origin) < 1000; float delay = (same_team || heard_it ? 0 : g_random()); if (plr->s.v.goalentity == item_entity) { plr->fb.goal_refresh_time = min(plr->fb.goal_refresh_time, g_globalvars.time + delay); ResetGoalEntity(plr); } } } // If teammate is sitting on item, leave for them // FIXME: If teammate is considerably weaker and bot needs/wants item, shout COMING instead static qbool GoalLeaveForTeammate(gedict_t *self, gedict_t *goal_entity) { if ((g_globalvars.time < goal_entity->fb.touchPlayerTime) && goal_entity->fb.touchPlayer && (goal_entity->fb.touchPlayer != self)) { if (WaitingToRespawn(goal_entity) && SameTeam(goal_entity->fb.touchPlayer, self)) { goal_entity->fb.saved_goal_desire = 0; return true; } } return false; } // Evaluates a goal void EvalGoal(gedict_t *self, gedict_t *goal_entity) { float goal_desire = goal_entity && goal_entity->fb.desire ? goal_entity->fb.desire(self, goal_entity) : 0; float goal_time = 0.0f; if (!goal_entity) { return; } if (self->fb.fixed_goal != NULL) { goal_desire = (self->fb.fixed_goal == goal_entity ? 1000 : 0); } goal_entity->fb.saved_goal_desire = goal_desire; if (goal_desire > 0) { if (POVDMM4DontWalkThroughDoor(goal_entity)) { return; } // If one person on a team is sitting waiting for an item to respawn if (GoalLeaveForTeammate(self, goal_entity)) { return; } // If item isn't going to respawn before match end if (match_end_time && goal_entity->fb.goal_respawn_time > match_end_time) { goal_entity->fb.saved_goal_desire = 0; return; } // Calculate travel time to the goal from_marker = self->fb.touch_marker; to_marker = goal_entity->fb.touch_marker; ZoneMarker(from_marker, to_marker, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, self->fb.canRocketJump); goal_time = traveltime; if (self->fb.goal_enemy_repel) { // Time for our enemy to get there from_marker = g_edicts[self->s.v.enemy].fb.touch_marker; ZoneMarker(from_marker, to_marker, path_normal, g_edicts[self->s.v.enemy].fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, g_edicts[self->s.v.enemy].fb.canRocketJump); // If enemy will get there much faster than we will... if (traveltime <= (goal_time - 1.25)) { goal_desire += self->fb.goal_enemy_repel; goal_entity->fb.saved_goal_desire = goal_desire; if (goal_desire <= 0) { return; } } } if (DM6DoorLogic(self, goal_entity)) { return; } goal_entity->fb.saved_respawn_time = (goal_entity->fb.goal_respawn_time - g_globalvars.time) + (goal_time * self->fb.skill.prediction_error * g_random()); if (goal_entity->fb.G_ == 18) { G_sprint( self, PRINT_HIGH, "Goal18: [%3.1f vs %3.1f] Eval(%s) = max(gt=%3.1f, respawn=%3.1f, srespawn=%3.1f)\n", g_globalvars.time, match_end_time, goal_entity->classname, goal_time, goal_entity->fb.goal_respawn_time, goal_entity->fb.saved_respawn_time); } goal_time = max(goal_time, goal_entity->fb.saved_respawn_time); goal_entity->fb.saved_goal_time = goal_time; if (self->fb.bot_evade) { if (self->fb.goal_enemy_repel) { qbool rl_routes = g_edicts[self->s.v.enemy].fb.canRocketJump; from_marker = g_edicts[self->s.v.enemy].fb.touch_marker; ZoneMarker(from_marker, to_marker, path_normal, rl_routes); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, rl_routes); goal_entity->fb.saved_enemy_time_squared = traveltime * traveltime; } if (goal_time * goal_time >= goal_entity->fb.saved_enemy_time_squared) { goal_entity->fb.saved_goal_desire = 0; return; } } // If the bot can think far enough ahead... if (goal_time < self->fb.skill.lookahead_time) { float goal_score = goal_desire * (self->fb.skill.lookahead_time - goal_time) / (goal_time + 5); if (goal_score > self->fb.best_goal_score) { self->fb.best_goal_score = goal_score; self->fb.best_goal = goal_entity; } } } } // FIXME: parameters static void EvalGoal2(gedict_t *goal_entity, gedict_t *best_goal_marker, qbool canRocketJump) { float goal_desire = 0.0f; float traveltime2 = 0.0f; if (goal_entity == NULL) { return; } goal_desire = goal_entity->fb.saved_goal_desire; if (goal_desire > 0) { float goal_time2 = goal_entity->fb.saved_goal_time; if (goal_time2 <= 5) { gedict_t *goal_marker2 = goal_entity->fb.touch_marker; from_marker = goal_marker2; ZoneMarker(from_marker, best_goal_marker, path_normal, canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, best_goal_marker, canRocketJump); traveltime2 = max(best_respawn_time, goal_time2 + traveltime); if (self->fb.bot_evade && self->fb.goal_enemy_repel) { if (traveltime2 * traveltime2 >= self->fb.best_goal->fb.saved_enemy_time_squared) { traveltime2 = 1000000; } } if (traveltime2 < self->fb.skill.lookahead_time) { float goal_score2 = (goal_desire * (self->fb.skill.lookahead_time - goal_time2) / (goal_time2 + 5)) + (self->fb.best_goal->fb.saved_goal_desire * (self->fb.skill.lookahead_time - traveltime2) / (traveltime2 + 5)); if (goal_score2 > self->fb.best_score2) { self->fb.best_score2 = goal_score2; self->fb.best_goal2 = goal_entity; } } from_marker = best_goal_marker; ZoneMarker(from_marker, goal_marker2, path_normal, canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, goal_marker2, canRocketJump); traveltime2 = max(self->fb.best_goal_time + traveltime, goal_entity->fb.saved_respawn_time); if (self->fb.bot_evade && self->fb.goal_enemy_repel) { if (traveltime2 * traveltime2 >= goal_entity->fb.saved_enemy_time_squared) { return; } } if (traveltime2 < self->fb.skill.lookahead_time) { float goal_score2 = self->fb.best_goal_score + (goal_desire * (self->fb.skill.lookahead_time - traveltime2) / (traveltime2 + 5)); if (goal_score2 > self->fb.best_score2) { self->fb.best_score2 = goal_score2; self->fb.best_goal2 = self->fb.best_goal; } } } } } static void EnemyGoalLogic(gedict_t *self) { float best_goal_desire = self->fb.best_goal->fb.saved_goal_desire; float best_goal_time = self->fb.best_goal->fb.saved_goal_time; gedict_t *best_goal_marker = self->fb.best_goal->fb.touch_marker; best_respawn_time = self->fb.best_goal->fb.saved_respawn_time; self->fb.best_goal->fb.saved_goal_desire = 0; if (self->fb.goal_enemy_desire > 0) { float goal_time2 = g_edicts[self->s.v.enemy].fb.saved_goal_time; if (goal_time2 <= 5) { // Work out time to enemy marker gedict_t *goal_marker2 = g_edicts[self->s.v.enemy].fb.touch_marker; float traveltime2 = 0.0f; from_marker = goal_marker2; ZoneMarker(from_marker, best_goal_marker, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, best_goal_marker, self->fb.canRocketJump); traveltime2 = max(goal_time2 + traveltime, best_respawn_time); if (traveltime2 < self->fb.skill.lookahead_time) { float goal_score2 = (self->fb.goal_enemy_desire * (self->fb.skill.lookahead_time - goal_time2) / (goal_time2 + 5)) + (best_goal_desire * (self->fb.skill.lookahead_time - traveltime2) / (traveltime2 + 5)); if (goal_score2 > self->fb.best_score2) { self->fb.best_score2 = goal_score2; self->fb.best_goal2 = &g_edicts[self->s.v.enemy]; } } // Work out time to best goal marker from_marker = best_goal_marker; ZoneMarker(from_marker, goal_marker2, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, goal_marker2, self->fb.canRocketJump); traveltime2 = max(best_goal_time + traveltime, g_edicts[self->s.v.enemy].fb.saved_respawn_time); if (traveltime2 < self->fb.skill.lookahead_time) { float goal_score2 = self->fb.best_goal_score + (self->fb.goal_enemy_desire * (self->fb.skill.lookahead_time - traveltime2) / (traveltime2 + 5)); if (goal_score2 > self->fb.best_score2) { self->fb.best_score2 = goal_score2; self->fb.best_goal2 = self->fb.best_goal; } } } } } void UpdateGoal(gedict_t *self) { int i = 0; gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; gedict_t *goal_entity = 0; char *dropped_powerup_names[] = { "item_artifact_invulnerability", "item_artifact_invisibility", "item_artifact_super_damage" }; self->fb.goal_refresh_time = g_globalvars.time + 2 + g_random(); if (self->fb.fixed_goal) { self->s.v.goalentity = NUM_FOR_EDICT(self->fb.fixed_goal); self->fb.goal_refresh_time = g_globalvars.time + 2 + g_random(); return; } self->fb.best_goal_score = 0; self->fb.best_goal = NULL; self->fb.goal_enemy_repel = self->fb.goal_enemy_desire = 0; BotEvadeLogic(self); if (enemy_->fb.touch_marker) { self->fb.virtual_enemy = enemy_; self->fb.goal_enemy_desire = enemy_ && enemy_->fb.desire ? enemy_->fb.desire(self, enemy_) : 0; if (self->fb.goal_enemy_desire > 0) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; // Time from here to the enemy's last marker from_marker = self->fb.touch_marker; ZoneMarker(from_marker, enemy->fb.touch_marker, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, enemy->fb.touch_marker, self->fb.canRocketJump); enemy_->fb.saved_respawn_time = 0; enemy_->fb.saved_goal_time = traveltime; if (traveltime < self->fb.skill.lookahead_time) { float goal_score = self->fb.goal_enemy_desire * (self->fb.skill.lookahead_time - traveltime) / (traveltime + 5); if (goal_score > self->fb.best_goal_score) { self->fb.best_goal_score = goal_score; self->fb.best_goal = enemy_; enemy_->fb.saved_goal_desire = self->fb.goal_enemy_desire; } } } else if (enemy_->s.v.enemy == NUM_FOR_EDICT(self)) { // our enemy is after us... self->fb.goal_enemy_repel = self->fb.goal_enemy_desire; } } else { self->fb.virtual_enemy = dropper; } for (i = 0; i < NUMBER_GOALS; ++i) { EvalGoal(self, self->fb.touch_marker->fb.goals[i].next_marker->fb.virtual_goal); } // Dropped backpacks for (goal_entity = world; (goal_entity = ez_find(goal_entity, BACKPACK_CLASSNAME));) { if (goal_entity->fb.touch_marker) { EvalGoal(self, goal_entity); } } // Dropped powerups for (i = 0; i < sizeof(dropped_powerup_names) / sizeof(dropped_powerup_names[0]); ++i) { for (goal_entity = world; (goal_entity = ez_find(goal_entity, dropped_powerup_names[i]));) { if ((goal_entity->cnt > g_globalvars.time) && goal_entity->fb.touch_marker) { EvalGoal(self, goal_entity); } } } if (teamplay && !isRA()) { gedict_t *search_entity = HelpTeammate(); if (search_entity && (g_random() < FROGBOT_CHANCE_HELP_TEAMMATE)) { self->fb.best_goal = search_entity; } } if (self->fb.best_goal) { gedict_t *goal_entity; self->fb.best_goal2 = self->fb.best_goal; self->fb.best_score2 = self->fb.best_goal_score; EnemyGoalLogic(self); for (i = 0; i < NUMBER_GOALS; ++i) { gedict_t *next = self->fb.touch_marker->fb.goals[i].next_marker; if (next && (next != world) && (next != dropper)) { EvalGoal2(self->fb.touch_marker->fb.goals[i].next_marker->fb.virtual_goal, self->fb.best_goal->fb.touch_marker, self->fb.canRocketJump); } } for (goal_entity = world; (goal_entity = ez_find(goal_entity, BACKPACK_CLASSNAME));) { if (goal_entity->fb.touch_marker) { EvalGoal2(goal_entity, self->fb.best_goal->fb.touch_marker, self->fb.canRocketJump); } } self->s.v.goalentity = NUM_FOR_EDICT(self->fb.best_goal2); self->fb.goal_respawn_time = g_globalvars.time + self->fb.best_goal2->fb.saved_respawn_time; } else { self->s.v.goalentity = NUM_FOR_EDICT(world); } } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_bothazd.c000066400000000000000000000745211475442401000176730ustar00rootroot00000000000000/* bot/bothazd.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 2003 3d[Power] Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // A lot of this is the bot 'cheating'?.. #define ARROW_TIME_AFTER_TELEPORT 0.20 // was 0.5 void GrenadeExplode(void); void BotPathCheck(gedict_t *self, gedict_t *touch_marker); // FIXME: Local globals static float first_trace_fraction = 0; static vec3_t first_trace_plane_normal = { 0 }; static const char* FallType(int fallType) { const char *fallNames[] = { "FALSE", "BLOCKED", "LAND", "DEATH", "???" }; return fallNames[(int)bound(0, fallType, sizeof(fallNames) / sizeof(fallNames[0]))]; } static float StandardFallHeight(gedict_t *self) { // Calculate fall height float fallheight = self->s.v.origin[2] - 38; // FIXME: Why 38 if (self->fb.linked_marker) { float min_second = self->fb.linked_marker->s.v.absmin[2] + self->fb.linked_marker->s.v.view_ofs[2] - 36; // FIXME: Why 36? fallheight = min(min_second, fallheight); } return fallheight; } // Input globals: first_trace_fraction, output: first_trace_fraction & first_trace_plane_normal static void TestTopBlock(gedict_t *self, vec3_t last_clear_point, vec3_t testplace) { float xDelta[4] = { -16, 16, -16, 16 }; float yDelta[4] = { -16, -16, 16, 16 }; int i = 0; for (i = 0; i < 4; ++i) { traceline(last_clear_point[0] + xDelta[i], last_clear_point[1] + yDelta[i], last_clear_point[2] + 32, testplace[0] + xDelta[i], testplace[1] + yDelta[i], testplace[2] + 32, true, self); if (g_globalvars.trace_fraction != 1) { if (g_globalvars.trace_plane_normal[2] <= 0) { if (first_trace_fraction > g_globalvars.trace_fraction) { first_trace_fraction = g_globalvars.trace_fraction; VectorCopy(g_globalvars.trace_plane_normal, first_trace_plane_normal); } } } } } // Input globals first_trace_fraction, output first_trace_fraction & first_trace_plane_normal static void TestBottomBlock(gedict_t *self, vec3_t last_clear_point, vec3_t testplace) { float xDelta[4] = { -16, 16, -16, 16 }; float yDelta[4] = { -16, -16, 16, 16 }; int i = 0; for (i = 0; i < 4; ++i) { traceline(last_clear_point[0] + xDelta[i], last_clear_point[1] + yDelta[i], last_clear_point[2] - 24, testplace[0] + xDelta[i], testplace[1] + yDelta[i], testplace[2] - 24, true, self); if (g_globalvars.trace_fraction != 1) { if (g_globalvars.trace_plane_normal[2] >= 0) { if (first_trace_fraction > g_globalvars.trace_fraction) { first_trace_fraction = g_globalvars.trace_fraction; VectorCopy(g_globalvars.trace_plane_normal, first_trace_plane_normal); } } } } } // static void AvoidEdge(gedict_t *self) { vec3_t dir_forward; VectorCopy(self->fb.oldvelocity, dir_forward); dir_forward[2] = 0; if (dir_forward[0] || dir_forward[1] || dir_forward[2]) { vec3_t dir_move; self->fb.oldvelocity[0] = self->fb.oldvelocity[1] = 0; // lavacheat always enabled VectorScale(dir_forward, -1, dir_move); NewVelocityForArrow(self, dir_move, "AvoidEdge"); self->fb.arrow_time2 = self->fb.arrow_time; } } static void HazardTeleport(gedict_t *teleport, gedict_t *teleported_player) { gedict_t *plr; teleport->fb.arrow_time = max(teleport->fb.arrow_time, g_globalvars.time + ARROW_TIME_AFTER_TELEPORT); teleport->fb.arrow_time_setby = teleported_player; // If teleported bot already has flag set, don't set for others // (otherwise two bots can keep triggering the same logic and blocking each other) if (teleported_player->fb.path_state & DELIBERATE_BACKUP) { return; } // Make all other bots wait a brief period before going through tele for (plr = world; (plr = find_plr(plr));) { // Tell other bots directly next to the teleport to back up a while if (plr->isBot && (plr != teleported_player) && (plr->fb.linked_marker == teleport)) { plr->fb.path_state |= DELIBERATE_BACKUP; plr->fb.linked_marker_time = g_globalvars.time + 0.1; } } } // This sets arrow_time on closest markers, to indicate danger static void ExplodeAlert(vec3_t org, float next_time) { gedict_t *marker; gedict_t *tele; // Find all map markers close to this point for (marker = world; (marker = trap_findradius(marker, org, 256));) { if (marker->fb.fl_marker) { // Would the grenade hurt the marker? traceline(org[0], org[1], org[2], marker->s.v.absmin[0] + marker->s.v.view_ofs[0], marker->s.v.absmin[1] + marker->s.v.view_ofs[1], marker->s.v.absmin[2] + marker->s.v.view_ofs[2], true, marker); if (g_globalvars.trace_fraction == 1) { // Mark the current time marker->fb.arrow_time = next_time; for (tele = world; (tele = ez_find(tele, "trigger_teleport"));) { // If this teleport takes us to the marker close to the grenade, set arrow_time if (!strnull(tele->target)) { gedict_t *target = find(world, FOFS(targetname), tele->target); if (target == marker) { tele->fb.arrow_time = max(tele->fb.arrow_time, next_time); } } } } } } } // This is essentially just to call ExplodeAlert(origin) every 0.05s, until the grenade explodes static void GrenadeAlert(void) { self->s.v.nextthink = g_globalvars.time + 0.05; self->think = (func_t) GrenadeAlert; if (self->fb.frogbot_nextthink <= g_globalvars.time) { self->think = (func_t) GrenadeExplode; self->s.v.nextthink = g_globalvars.time; } ExplodeAlert(self->s.v.origin, self->s.v.nextthink); } static void Missile_Remove(void) { self->s.v.owner = NUM_FOR_EDICT(world); ent_remove(self); } static void RocketAlert(void) { vec3_t end_point; self->s.v.nextthink = g_globalvars.time + 0.5; if (self->fb.frogbot_nextthink <= g_globalvars.time) { self->think = (func_t) Missile_Remove; } VectorMA(self->s.v.origin, 600, self->s.v.velocity, end_point); traceline(PASSVEC3(self->s.v.origin), PASSVEC3(end_point), true, PROG_TO_EDICT(self->s.v.owner)); ExplodeAlert(g_globalvars.trace_endpos, 0.5); } // static qbool JumpInWater(vec3_t testpoint) { return (trap_pointcontents(testpoint[0], testpoint[1], testpoint[2] - 64) == CONTENT_WATER); } static int FallSpotGround(vec3_t testplace, float fallheight) { VectorCopy(testplace, dropper->s.v.origin); dropper->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (walkmove(dropper, 0, 0)) { int content; if (dropper->s.v.origin[2] <= MapDeathHeight()) return FALL_DEATH; // If we didn't fall into water... if (!JumpInWater(dropper->s.v.origin) && !droptofloor(dropper)) { VectorCopy(testplace, dropper->s.v.origin); dropper->s.v.origin[2] -= 256; if (!droptofloor(dropper)) { return FALL_DEATH; } } // Check we didn't fall into lava... content = trap_pointcontents(dropper->s.v.origin[0], dropper->s.v.origin[1], dropper->s.v.origin[2] - 24); if (content == CONTENT_LAVA) { return FALL_DEATH; } if (dropper->s.v.origin[2] < fallheight) { return FALL_LAND; } return FALL_FALSE; } if (dropper->s.v.origin[2] <= MapDeathHeight()) { return FALL_DEATH; } return FALL_BLOCKED; } static int FallSpotAir(gedict_t *self, vec3_t testplace, float fallheight) { vec3_t final_origin; int content; VectorCopy(testplace, dropper->s.v.origin); dropper->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (walkmove(dropper, 0, 0)) { if (dropper->s.v.origin[2] <= MapDeathHeight()) { return FALL_DEATH; } if (!JumpInWater(dropper->s.v.origin) && (dropper->s.v.origin[2] > testplace[2])) { return FALL_BLOCKED; } } else { return FALL_BLOCKED; } if (!JumpInWater(dropper->s.v.origin) && !(droptofloor(dropper))) { VectorCopy(testplace, dropper->s.v.origin); dropper->s.v.origin[2] -= 256; if (!droptofloor(dropper)) { return FALL_DEATH; } } VectorCopy(dropper->s.v.origin, final_origin); content = trap_pointcontents(final_origin[0], final_origin[1], final_origin[2] - 24); if (content == CONTENT_LAVA) { return FALL_DEATH; } if (final_origin[2] <= MapDeathHeight()) { return FALL_DEATH; } if (dropper->s.v.origin[2] < fallheight) { return FALL_LAND; } return FALL_FALSE; } // last_clear_point is output variable static qbool CanJumpOver(gedict_t *self, vec3_t jump_origin, vec3_t jump_velocity, float fallheight, int current_fallspot) { int tries = 0; float last_clear_hor_speed = 0; vec3_t last_clear_hor_velocity; vec3_t last_clear_point; vec3_t last_clear_velocity; vec3_t accel_direction; VectorCopy(jump_origin, last_clear_point); VectorCopy(jump_velocity, last_clear_velocity); VectorCopy(last_clear_velocity, last_clear_hor_velocity); last_clear_hor_velocity[2] = 0; last_clear_hor_speed = vlen(last_clear_hor_velocity); normalize(last_clear_hor_velocity, accel_direction); last_clear_velocity[2] = jump_velocity[2] - (12800 / last_clear_hor_speed); // 12800 = sv_gravity * 16? //G_bprint (2, "CanJumpOver([%d %d %d], [%d %d %d], %f)\n", PASSINTVEC3 (jump_origin), PASSINTVEC3 (jump_velocity), fallheight); for (tries = 0; tries < 20; ++tries) { int fall = 0; vec3_t testplace; //G_bprint (2, "%02d: last_clear_point = %f %f %f\n", tries, PASSVEC3(last_clear_point)); if (last_clear_point[2] < fallheight) { //G_bprint (2, " last_clear_point_z < fallheight (%f), quitting\n", fallheight); return false; } VectorMA(last_clear_point, (32 / last_clear_hor_speed), last_clear_velocity, testplace); fall = FallSpotAir(self, testplace, fallheight); //G_bprint (2, " Testplace: %d %d %d = %s\n", PASSINTVEC3 (testplace), FallType(fall)); if (fall == FALL_BLOCKED) { first_trace_fraction = 1; TestTopBlock(self, last_clear_point, testplace); TestBottomBlock(self, last_clear_point, testplace); if (first_trace_fraction != 1) { float dotProduct; // If we didn't hit anything above/below then it was a side-on collision, so keep going VectorMA(last_clear_point, (first_trace_fraction * 32 / last_clear_hor_speed), last_clear_velocity, testplace); dotProduct = DotProduct(first_trace_plane_normal, last_clear_velocity); VectorMA(last_clear_velocity, -dotProduct, first_trace_plane_normal, last_clear_velocity); VectorCopy(last_clear_velocity, last_clear_hor_velocity); last_clear_hor_velocity[2] = 0; last_clear_hor_speed = vlen(last_clear_hor_velocity); normalize(last_clear_hor_velocity, accel_direction); VectorMA(testplace, (32 / last_clear_hor_speed) * (1 - first_trace_fraction), last_clear_velocity, testplace); } fall = FallSpotAir(self, testplace, fallheight); //G_bprint (2, " Blocked testplace: %f %f %f = %d\n", PASSVEC3 (testplace), fall); } if (fall == FALL_BLOCKED) { return false; } if (fall > current_fallspot) { last_clear_velocity[2] = last_clear_velocity[2] - (25600 / last_clear_hor_speed); VectorCopy(testplace, last_clear_point); } else { if ((int)self->s.v.flags & FL_ONGROUND) { gedict_t *ent; for (ent = world; (ent = findradius_ignore_solid(ent, testplace, 84));) { if (ent->fb.T & UNREACHABLE) { return false; } } } return true; } // Air-control (FIXME: looks like this function runs simulation at 10fps VectorMA(last_clear_velocity, 7 * 5.0f, accel_direction, last_clear_velocity); VectorMA(last_clear_hor_velocity, 7 * 5.0f, accel_direction, last_clear_hor_velocity); last_clear_hor_speed = vlen(last_clear_hor_velocity); } return false; } /* // This code removed - was called at end of main loop of CanJumpOver static void ApplyTurningAccel (void) { if (self->fb.turning_speed) { vec3_t last_clear_angle; vectoangles(last_clear_velocity, last_clear_angle); last_clear_angle[0] = 0 - last_clear_angle[0]; last_clear_angle[1] = last_clear_angle[1] + (self->fb.turning_speed * 32 / last_clear_hor_speed); trap_makevectors(last_clear_angle); VectorScale(g_globalvars.v_forward, vlen(last_clear_velocity), last_clear_velocity); } }*/ // This code removed.... because ledge_backup fires based on velocity, this fires too often when bot is in midair, // reversing the direction and causing the bot to go back to platform. static void LedgeBackupLogic(gedict_t *self, vec3_t rel_pos, vec3_t new_velocity) { qbool ledge_backup = (rel_pos[2] > 0); if (new_velocity[2] >= 0) { ledge_backup = ((new_velocity[2] * new_velocity[2] * 0.000625) < rel_pos[2]);// 0.000625 = 0.5 / sv_gravity } if (self->fb.debug_path) { G_bprint(2, "jl2: new_vel %f %f %f\n", PASSVEC3(new_velocity)); G_bprint(2, " : rel_pos %f %f %f\n", PASSVEC3(rel_pos)); } if (ledge_backup) { if (self->fb.ledge_backup_time) { if (g_globalvars.time >= self->fb.ledge_backup_time) { vec3_t dir_move; VectorScale(rel_pos, -1, dir_move); dir_move[2] = 0; NewVelocityForArrow(self, dir_move, "JumpLedge2"); self->fb.ledge_backup_time = 0; } } else { self->fb.ledge_backup_time = g_globalvars.time + 0.15; } } } static qbool LedgeJumpLogic(gedict_t *self, vec3_t rel_pos, vec3_t new_velocity) { vec3_t rel_hor_dir; qbool try_jump_ledge = true; qbool being_blocked = false; if (vlen(self->fb.oldvelocity) <= 100) { VectorCopy(rel_pos, rel_hor_dir); rel_hor_dir[2] = 0; try_jump_ledge = (vlen(rel_hor_dir) <= 80); VectorNormalize(rel_hor_dir); being_blocked = (DotProduct(self->fb.obstruction_normal, rel_hor_dir) > 0.5); } if (try_jump_ledge && rel_pos[2] > 18) { float jumpspeed = new_velocity[2] + JUMPSPEED; if ((jumpspeed * jumpspeed * 0.000625) >= rel_pos[2]) { // 0.000625 = 0.5 / sv_gravity SetJumpFlag(self, true, "LedgeJumpLogic"); self->fb.path_state |= WAIT_GROUND; self->fb.ledge_backup_time = 0; return true; } } if (being_blocked && g_globalvars.time > self->fb.arrow_time) { if (self->fb.ledge_backup_time) { if (g_globalvars.time >= self->fb.ledge_backup_time) { vec3_t dir_move; VectorMA(rel_hor_dir, -DotProduct(self->fb.obstruction_normal, rel_hor_dir), self->fb.obstruction_normal, dir_move); if ((dir_move[0] == 0) && (dir_move[1] == 0) && (dir_move[2] == 0)) { VectorScale(self->fb.obstruction_normal, -1, dir_move); NewVelocityForArrow(self, dir_move, "JumpLedge(dir_move 0)"); } else if (g_random() < 0.5) { VectorScale(dir_move, -1, dir_move); NewVelocityForArrow(self, dir_move, "JumpLedge(random)"); } else { NewVelocityForArrow(self, dir_move, "JumpLedge"); } self->fb.ledge_backup_time = 0; } } else { self->fb.ledge_backup_time = g_globalvars.time + 0.15; } } return false; } // Only called if self->fb.path_state & JUMP_LEDGE static qbool JumpLedgeLogic(gedict_t *self, vec3_t new_velocity) { if (g_globalvars.time > self->fb.arrow_time2) { vec3_t rel_pos; VectorAdd(self->fb.linked_marker->s.v.absmin, self->fb.linked_marker->s.v.view_ofs, rel_pos); VectorSubtract(rel_pos, self->s.v.origin, rel_pos); VectorCopy(rel_pos, self->fb.obstruction_direction); if ((int)self->s.v.flags & FL_ONGROUND) { if (LedgeJumpLogic(self, rel_pos, new_velocity)) { return true; } } else if (g_globalvars.time > self->fb.arrow_time) { LedgeBackupLogic(self, rel_pos, new_velocity); } } if (g_globalvars.time >= (self->fb.ledge_backup_time + 0.15)) { self->fb.ledge_backup_time = 0; } return false; } // Called only if current path isn't flagged as JUMP_LEDGE, but obstruction_normal still set static void ObstructionLogic(gedict_t *self, vec3_t new_velocity) { // not being stationary if (self->fb.linked_marker != self->fb.touch_marker) { if (vlen(self->fb.oldvelocity) <= 32) { vec3_t dir_move; VectorMA(new_velocity, -DotProduct(self->fb.obstruction_normal, new_velocity), self->fb.obstruction_normal, dir_move); //G_bprint (PRINT_HIGH, "NV %3d %3d %3d, ON %3.2f %3.2f %3.2f, DM %3d %3d %3d\n", PASSINTVEC3 (new_velocity), PASSVEC3 (self->fb.obstruction_normal), PASSINTVEC3 (dir_move)); if ((dir_move[0] == 0) && (dir_move[1] == 0)) { VectorScale(self->fb.obstruction_normal, -1, dir_move); self->fb.path_state |= STUCK_PATH; } else if ((self->fb.oldvelocity[0] == 0) && (self->fb.oldvelocity[1] == 0)) { // maybe stuck in a corner if (g_random() < 0.5) { VectorScale(dir_move, -1, dir_move); } self->fb.path_state |= STUCK_PATH; } else if ((int)self->fb.path_state & STUCK_PATH) { // vec3_t norm_new_velocity; VectorNormalize(dir_move); normalize(new_velocity, norm_new_velocity); VectorAdd(dir_move, norm_new_velocity, dir_move); } else { VectorMA(self->fb.dir_move_, -0.5 * DotProduct(self->fb.obstruction_normal, self->fb.dir_move_), self->fb.obstruction_normal, dir_move); } dir_move[2] = 0; NewVelocityForArrow(self, dir_move, "Obstruct"); } } VectorMA(new_velocity, -DotProduct(self->fb.obstruction_normal, new_velocity), self->fb.obstruction_normal, new_velocity); } static void DumpDebugLines(char lines[10][128], int count, const char *explanation) { #if 0 int i; for (i = 0; i < count; ++i) { G_bprint(PRINT_HIGH, "%s", lines[i]); } G_bprint(PRINT_HIGH, " %s\n", explanation); #endif } static void AvoidHazardsOnGround(gedict_t *self, float hor_speed, vec3_t new_origin, vec3_t new_velocity, vec3_t dir_forward) { int fall = 0; int new_fall = 0; vec3_t jump_origin = { 0, 0, 0 }; vec3_t last_clear_point = { 0, 0, 0 }; vec3_t jump_velocity; vec3_t testplace; float fallheight = StandardFallHeight(self); char debug[10][128] = { { 0 } }; int line = 0; if (new_velocity[2] < 0) { new_velocity[2] = 0; } VectorCopy(self->s.v.origin, last_clear_point); VectorMA(last_clear_point, (16 / hor_speed), new_velocity, testplace); fall = FallSpotGround(testplace, fallheight); snprintf(debug[line++], sizeof(debug[0]), "AvoidHazardsOnGround(origin [%d %d %d], vel [%d %d %d])\n", PASSINTVEC3(new_origin), PASSINTVEC3(new_velocity)); snprintf(debug[line++], sizeof(debug[0]), "> FallSpotGround([%d %d %d], %f) = %s\n", PASSINTVEC3(testplace), fallheight, FallType(fall)); if (fall == FALL_BLOCKED) { first_trace_fraction = 1; TestTopBlock(self, last_clear_point, testplace); if (first_trace_fraction != 1) { vec3_t hor_velocity; VectorMA(last_clear_point, (16 / hor_speed) * first_trace_fraction, new_velocity, testplace); VectorMA(new_velocity, -DotProduct(first_trace_plane_normal, new_velocity), first_trace_plane_normal, new_velocity); VectorCopy(new_velocity, hor_velocity); hor_velocity[2] = 0; hor_speed = vlen(hor_velocity); VectorMA(testplace, (16 / hor_speed) * (1 - first_trace_fraction), new_velocity, testplace); } fall = FallSpotGround(testplace, fallheight); snprintf(debug[line++], sizeof(debug[0]), "> FallSpotGround([%d %d %d], %f) = %s\n", PASSINTVEC3(testplace), fallheight, FallType(fall)); } if (fall >= FALL_LAND && (self->fb.path_state & BOTPATH_CURLJUMP_HINT)) { snprintf(debug[line++], sizeof(debug[0]), "> CurlJumpHint(%d)... jumping\n", self->fb.angle_hint); DumpDebugLines(debug, line, "CurlJumpHint\n"); SetJumpFlag(self, true, "AvoidHazards(CurlJump)"); self->fb.path_state |= DELIBERATE_AIR_WAIT_GROUND; return; } if (fall >= FALL_LAND) { VectorCopy(testplace, jump_origin); new_fall = fall; VectorCopy(new_origin, testplace); fall = FallSpotGround(testplace, fallheight); snprintf(debug[line++], sizeof(debug[0]), "> 2: FallSpotGround([%d %d %d], %f) = %s\n", PASSINTVEC3(testplace), fallheight, FallType(fall)); if ((int)self->fb.path_state & DELIBERATE_AIR) { if (fall < FALL_LAND) { DumpDebugLines(debug, line, "Deliberate_Air detected\n"); return; } self->fb.path_state &= ~DELIBERATE_AIR; } if (new_fall > fall) { //G_bprint (2, "%s: %d (%s) -> %d (%s)\n", self->netname, self->fb.touch_marker->fb.index + 1, self->fb.touch_marker->classname, self->fb.linked_marker->fb.index, self->fb.linked_marker->classname); if (g_globalvars.time > self->fb.arrow_time2) { // if (CanFallAndGetAcrossHazard(self, new_velocity)) VectorCopy(new_velocity, jump_velocity); jump_velocity[2] = jump_velocity[2] - (6400 / hor_speed); // 6400 = sv_gravity * 8 jump_origin[2] = jump_origin[2] + (jump_velocity[2] * (16 / hor_speed)); jump_velocity[2] = jump_velocity[2] + (6400 / hor_speed); // 6400 = sv_gravity * 8 (was -) if (CanJumpOver(self, jump_origin, jump_velocity, fallheight, fall)) { DumpDebugLines(debug, line, "CanFallAcross()\n"); self->fb.path_state |= DELIBERATE_AIR_WAIT_GROUND; return; } // if (CanJumpAcrossHazard(self, new_velocity)) VectorCopy(new_origin, jump_origin); VectorCopy(new_velocity, jump_velocity); jump_velocity[2] += JUMPSPEED; snprintf(debug[line++], sizeof(debug[0]), "> CanJumpOver([%d %d %d], [%d %d %d], %f, %s)\n", PASSINTVEC3(jump_origin), PASSINTVEC3(jump_velocity), fallheight, FallType(fall)); if (CanJumpOver(self, jump_origin, jump_velocity, fallheight, fall)) { //G_bprint (2, " CanJumpOver(jumpo[%f %f %f] v[%f %f %f] %f %d %f)\n", PASSVEC3 (new_origin), PASSVEC3(jump_velocity), fallheight, fall, hor_speed); DumpDebugLines(debug, line, "CanJumpOver() => Jumping\n"); SetJumpFlag(self, true, "AvoidHazards(CanJumpAcrossHzd)"); self->fb.path_state |= DELIBERATE_AIR_WAIT_GROUND; return; } //G_bprint (2, " Failed CanJumpOver tests: [%f %f %f, %f %f %f, %f, %d, %f]\n", PASSVEC3(new_origin), PASSVEC3(jump_velocity), fallheight, fall, hor_speed); } else { //G_bprint (2, " Not trying, arrow_time2 %f (%f, now %f)\n", self->fb.arrow_time2, self->fb.arrow_time, g_globalvars.time); } AvoidEdge(self); } return; } VectorMA(testplace, 8 / hor_speed, new_velocity, new_origin); VectorMA(testplace, 16 / hor_speed, new_velocity, testplace); fall = FallSpotGround(testplace, fallheight); snprintf(debug[line++], sizeof(debug[0]), "> 3: FallSpotGround([%d %d %d], %f) = %s\n", PASSINTVEC3(testplace), fallheight, FallType(fall)); if (fall >= FALL_LAND && (self->fb.path_state & BOTPATH_CURLJUMP_HINT)) { snprintf(debug[line++], sizeof(debug[0]), "> CurlJumpHint(%d)... jumping\n", self->fb.angle_hint); DumpDebugLines(debug, line, "CurlJumpHint\n"); SetJumpFlag(self, true, "AvoidHazards(CurlJumpHint2)"); self->fb.path_state |= DELIBERATE_AIR_WAIT_GROUND; return; } if (fall >= FALL_LAND) { new_fall = fall; VectorCopy(testplace, jump_origin); VectorCopy(self->s.v.origin, testplace); fall = FallSpotGround(testplace, fallheight); snprintf(debug[line++], sizeof(debug[0]), "> 4: FallSpotGround([%d %d %d], %f) = %s\n", PASSINTVEC3(testplace), fallheight, FallType(fall)); if ((int)self->fb.path_state & DELIBERATE_AIR) { if (fall < FALL_LAND) { DumpDebugLines(debug, line, "Deliberate_Air detected\n"); return; } self->fb.path_state &= ~DELIBERATE_AIR; } if (new_fall > fall) { float normal_comp = 0; vec3_t edge_normal; if (g_globalvars.time > self->fb.arrow_time2) { VectorCopy(new_velocity, jump_velocity); jump_velocity[2] = jump_velocity[2] - (6400 / hor_speed); jump_origin[2] = jump_origin[2] + (jump_velocity[2] * (16 / hor_speed)); jump_velocity[2] = jump_velocity[2] - (6400 / hor_speed); snprintf(debug[line++], sizeof(debug[0]), "> CanJumpOver([%d %d %d], [%d %d %d], %f, %s)\n", PASSINTVEC3(jump_origin), PASSINTVEC3(jump_velocity), fallheight, FallType(fall)); if (CanJumpOver(self, jump_origin, jump_velocity, fallheight, fall)) { DumpDebugLines(debug, line, "CanFallOver2\n"); self->fb.path_state |= NO_DODGE; return; } VectorCopy(new_origin, jump_origin); VectorCopy(new_velocity, jump_velocity); jump_velocity[2] += JUMPSPEED; snprintf(debug[line++], sizeof(debug[0]), "> CanJumpOver([%d %d %d], [%d %d %d], %f, %s)\n", PASSINTVEC3(jump_origin), PASSINTVEC3(jump_velocity), fallheight, FallType(fall)); if (CanJumpOver(self, jump_origin, jump_velocity, fallheight, fall)) { DumpDebugLines(debug, line, "CanJumpOver2\n"); self->fb.path_state |= NO_DODGE; SetJumpFlag(self, true, "AvoidHazards(CanJumpOver2)"); return; } } traceline(self->s.v.origin[0] + (dir_forward[0] * 32), self->s.v.origin[1] + (dir_forward[1] * 32), self->s.v.origin[2] + (dir_forward[2] * 32) - 24.1, self->s.v.origin[0] - (dir_forward[0] * 16), self->s.v.origin[1] - (dir_forward[1] * 16), self->s.v.origin[2] - (dir_forward[2] * 16) - 24.1, true, world); g_globalvars.trace_plane_normal[2] = 0; if ((g_globalvars.trace_plane_normal[0] == 0) && (g_globalvars.trace_plane_normal[1] == 0) && (g_globalvars.trace_plane_normal[2] == 0)) { AvoidEdge(self); DumpDebugLines(debug, line, "AvoidingEdge1\n"); return; } normalize(g_globalvars.trace_plane_normal, edge_normal); normal_comp = DotProduct(edge_normal, dir_forward); if (normal_comp <= 0) { AvoidEdge(self); DumpDebugLines(debug, line, "AvoidingEdge2\n"); return; } { vec3_t dir_move; VectorMA(dir_forward, -2 * normal_comp, edge_normal, dir_move); dir_move[2] = 0; NewVelocityForArrow(self, dir_move, "AvoidHzds"); DumpDebugLines(debug, line, "BackingUp...\n"); if (normal_comp > 0.5) { self->fb.arrow_time2 = self->fb.arrow_time; } } } } } static void AvoidHazardsInAir(gedict_t *self, float hor_speed, vec3_t new_origin, vec3_t new_velocity, vec3_t last_clear_point) { float fallheight = StandardFallHeight(self); vec3_t testplace; int fall; // Don't change trajectory on rocket jump while ascending if (self->fb.path_state & BOTPATH_RJ_IN_PROGRESS) { return; } VectorMA(new_origin, 32 / hor_speed, new_velocity, testplace); // FIXME: Why 32? (10 fps?) fall = FallSpotAir(self, testplace, fallheight); if (fall >= FALL_LAND) { int new_fall = fall; VectorCopy(new_origin, testplace); fall = FallSpotAir(self, testplace, fallheight); if (self->fb.path_state & DELIBERATE_AIR) { if (fall < FALL_LAND) { if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(self, PRINT_HIGH, "AvoidHazardsInAir: DELIBERATE_AIR [%s/%s]\n", FallType(new_fall), FallType(fall)); } return; } self->fb.path_state &= ~DELIBERATE_AIR; } if (new_fall > fall) { VectorMA(new_origin, (16 / hor_speed), new_velocity, testplace); fall = FallSpotAir(self, testplace, fallheight); if (new_fall > fall) { vec3_t jump_origin, jump_velocity; VectorCopy(new_origin, jump_origin); VectorCopy(new_velocity, jump_velocity); if (CanJumpOver(self, jump_origin, jump_velocity, fallheight, fall)) { if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(self, PRINT_HIGH, "AvoidHazardsInAir: CanJumpOver [%s/%s]\n", FallType(new_fall), FallType(fall)); } return; } if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(self, PRINT_HIGH, "AvoidHazardsInAir: AvoidingEdge [%s/%s]\n", FallType(new_fall), FallType(fall)); } AvoidEdge(self); } } else if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(self, PRINT_HIGH, "AvoidHazardsInAir: Ignored [%s/%s]\n", FallType(new_fall), FallType(fall)); } } else if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(self, PRINT_HIGH, "AvoidHazardsInAir: Ignored [%s]\n", FallType(fall)); } } // FIXME: Globals. // FIXME: Magic numbers all over the place. void AvoidHazards(gedict_t *self) { float hor_speed = 0; vec3_t new_origin = { 0 }; vec3_t new_velocity = { 0 }; vec3_t hor_velocity = { 0 }; vec3_t dir_forward; vec3_t testplace; // FIXME: should this be current velocity or proposed velocity (self->fb.dir_move_, scaled by speed?) VectorCopy(self->s.v.velocity, new_velocity); //VectorScale (self->fb.dir_move_, , new_velocity); if (self->fb.path_state & JUMP_LEDGE) { if (JumpLedgeLogic(self, new_velocity)) { return; } } else if (self->fb.obstruction_normal[0] || self->fb.obstruction_normal[1] || self->fb.obstruction_normal[2]) { if ((g_globalvars.time > self->fb.arrow_time) && ((int)self->s.v.flags & FL_WATERJUMP)) { return; } else if (g_globalvars.time > self->fb.arrow_time) { ObstructionLogic(self, new_velocity); } //G_bprint (2, "Unhandled obstruction..."); } if (self->s.v.waterlevel) { return; } // Reduce to horizontal velocity only VectorCopy(new_velocity, hor_velocity); hor_velocity[2] = 0; hor_speed = vlen(hor_velocity); if (!hor_speed) { return; // falling straight down } VectorCopy(self->s.v.origin, new_origin); if ((int)self->s.v.flags & FL_ONGROUND) { normalize(hor_velocity, dir_forward); AvoidHazardsOnGround(self, hor_speed, new_origin, new_velocity, dir_forward); } else { AvoidHazardsInAir(self, hor_speed, new_origin, new_velocity, testplace); } } // Called after a grenade has been spawned void BotsGrenadeSpawned(gedict_t *newmis) { if (!bots_enabled()) { return; } // Call GrenadeAlert() repeatedly so we can avoid the grenade newmis->fb.frogbot_nextthink = newmis->s.v.nextthink; newmis->s.v.nextthink = g_globalvars.time + 0.05; // New newmis->think = (func_t) GrenadeAlert; } // Called after a rocket has been spawned void BotsRocketSpawned(gedict_t *newmis) { if (!bots_enabled()) { return; } // Call RocketAlert() repeatedly so we can avoid the rocket newmis->fb.frogbot_nextthink = newmis->s.v.nextthink; newmis->think = (func_t) RocketAlert; newmis->s.v.nextthink = 0.001; // Store spawn time so we don't avoid too early newmis->fb.missile_spawntime = g_globalvars.time; // Store rocket direction VectorCopy(g_globalvars.v_forward, newmis->fb.missile_forward); VectorCopy(g_globalvars.v_right, newmis->fb.missile_right); } qbool BotsPreTeleport(gedict_t *self, gedict_t *other) { if (NoItemTouch(self, other)) { if (IsMarkerFrame()) { HazardTeleport(self, other); } return true; } if (HasSavedMarker()) { return true; } return false; } void BotsPostTeleport(gedict_t *teleport_trigger, gedict_t *player, gedict_t *teleport_destination) { if (player->isBot) { //if (teamplay != 0) // say_team_report_teleport(other, t); player->fb.wiggle_run_dir = 0; BotPathCheck(player, teleport_trigger); } player->fb.frogbot_nextthink = g_globalvars.time; if (player->fb.linked_marker == teleport_trigger) { SetLinkedMarker(player, teleport_destination, "BotsPostTeleport"); } HazardTeleport(teleport_trigger, player); SetMarker(player, teleport_destination); } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_bothelp.c000066400000000000000000000112401475442401000176620ustar00rootroot00000000000000/* bot/bothelp.qc Copyright (C) 1999-2000 Numb Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // Checks if self > point is not blocked static qbool PointVisible(vec3_t vec) { traceline(PASSVEC3(self->s.v.origin), PASSVEC3(vec), true, self); if ((g_globalvars.trace_fraction == 1) && !(g_globalvars.trace_inopen && g_globalvars.trace_inwater)) { return true; } return false; } // FIXME: Doesn't take view offset into consideration when tracing // FIXME: Don't run extra traces if they are further away gedict_t* IdentifyMostVisibleTeammate(gedict_t *me) { gedict_t *p, *g = NULL; float closeness = -1; vec3_t diff, point; float currclose; byte visible[MAX_CLIENTS]; visible_to(me, g_edicts + 1, MAX_CLIENTS, visible); for (p = g_edicts + 1; p <= g_edicts + MAX_CLIENTS; p++) { if ((me != p) && p->ct == ctPlayer && visible[p - (g_edicts + 1)] && SameTeam(me, p)) { // Find difference in angles between aim & aiming at teammate VectorSubtract(p->s.v.origin, me->s.v.origin, diff); VectorNormalize(diff); normalize(me->s.v.angles, point); VectorSubtract(diff, point, diff); currclose = vlen(diff); // If we have direct visibility traceline(PASSVEC3(me->s.v.origin), PASSVEC3(p->s.v.origin), false, me); if (PROG_TO_EDICT(g_globalvars.trace_ent) == p) { if (closeness == -1) { closeness = currclose; g = p; } else if (currclose < closeness) { closeness = currclose; g = p; } } } } return (g ? g : world); } qbool VisibleEntity(gedict_t *ent) { vec3_t vec; if (PointVisible(ent->s.v.origin)) { return true; } VectorCopy(ent->s.v.origin, vec); vec[2] = ent->s.v.absmin[2]; if (PointVisible(vec)) { return true; } vec[2] = ent->s.v.absmax[2]; return PointVisible(vec); } gedict_t* HelpTeammate(void) { gedict_t *goalent; gedict_t *head, *selected1, *selected2; float d, bdist, best_dist1, best_dist2; if (!teamplay) { return NULL; } if (self->fb.state & WAIT) { return NULL; } if (self->fb.state & RUNAWAY) { return NULL; } if (self->fb.state & NOTARGET_ENEMY) { return NULL; } goalent = &g_edicts[self->s.v.goalentity]; if (goalent->s.v.goalentity == NUM_FOR_EDICT(self)) { return NULL; } if ((goalent->ct == ctPlayer) && (goalent != self)) { if (SameTeam(goalent, self)) { if ((goalent->s.v.health < 30) && !((int)goalent->s.v.items & IT_INVULNERABILITY) && (goalent->s.v.waterlevel == 0)) { if (((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) && (self->s.v.health > 65)) { if ((self->s.v.ammo_rockets > 2) || (self->s.v.ammo_cells > 10)) { if (VisibleEntity(goalent)) { self->fb.state |= HELP_TEAMMATE; return goalent; } } } } } } bdist = 500; if (g_globalvars.time < self->fb.help_teammate_time) { return NULL; } self->fb.help_teammate_time = g_globalvars.time + 20 + 3 * g_random(); selected1 = NULL; selected2 = NULL; best_dist1 = 10e+32; best_dist2 = 10e+32; for (head = world; (head = trap_findradius(head, self->s.v.origin, bdist));) { if (head->ct == ctPlayer) { if (SameTeam(head, self)) { if (head != self) { d = VectorDistance(head->s.v.origin, self->s.v.origin); if (NUM_FOR_EDICT(self) != head->s.v.goalentity) { if (d < best_dist1) { if (VisibleEntity(head) && !((int)head->s.v.items & IT_INVULNERABILITY) && (head->s.v.health < 40) && (head->s.v.armorvalue < 11) && (head->s.v.waterlevel == 0)) { if ((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) { if ((self->s.v.ammo_cells > 10) || (self->s.v.ammo_rockets > 2)) { selected1 = head; self->fb.state |= HELP_TEAMMATE; best_dist1 = d; } } } } } if (SameTeam(head, self)) { if (NUM_FOR_EDICT(self) != head->s.v.goalentity) { if (d < best_dist2) { if (VisibleEntity(head) && !((int)head->s.v.items & IT_INVULNERABILITY) && (head->s.v.health < 30) && (head->s.v.armorvalue < 20) && (head->s.v.waterlevel == 0)) { if ((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) { if ((self->s.v.ammo_cells > 10) || (self->s.v.ammo_rockets > 2)) { selected2 = head; self->fb.state |= HELP_TEAMMATE; best_dist2 = d; } } } } } } } } } } if (selected1) { return selected1; } else if (selected2) { return selected2; } return NULL; } #endif QW-Group-ktx-d05d6ca/src/bot_botimp.c000066400000000000000000000330671475442401000175320ustar00rootroot00000000000000/* bot/botimp.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 1999-2000 Numb Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" #define FB_CVAR_DODGEFACTOR "k_fbskill_movement_dodgefactor" #define FB_CVAR_LOOKANYWHERE "k_fbskill_aim_lookanywhere" #define FB_CVAR_LOOKAHEADTIME "k_fbskill_goallookaheadtime" #define FB_CVAR_PREDICTIONERROR "k_fbskill_goalpredictionerror" #define FB_CVAR_DISTANCEERROR "k_fbskill_distanceerror" #define FB_CVAR_VISIBILITY "k_fbskill_visibility" #define FB_CVAR_LGPREF "k_fbskill_aim_lgpref" #define FB_CVAR_ACCURACY "k_fbskill_aim_accuracy" #define FB_CVAR_YAW_MIN_ERROR "k_fbskill_aim_yaw_min" #define FB_CVAR_YAW_MAX_ERROR "k_fbskill_aim_yaw_max" #define FB_CVAR_YAW_MULTIPLIER "k_fbskill_aim_yaw_multiplier" #define FB_CVAR_YAW_SCALE "k_fbskill_aim_yaw_scale" #define FB_CVAR_PITCH_MIN_ERROR "k_fbskill_aim_pitch_min" #define FB_CVAR_PITCH_MAX_ERROR "k_fbskill_aim_pitch_max" #define FB_CVAR_PITCH_MULTIPLIER "k_fbskill_aim_pitch_multiplier" #define FB_CVAR_PITCH_SCALE "k_fbskill_aim_pitch_scale" #define FB_CVAR_ATTACK_RESPAWNS "k_fbskill_aim_attack_respawns" #define FB_CVAR_REACTION_TIME "k_fbskill_reactiontime" #define FB_CVAR_REACTION_MOVETIME "k_fbskill_reactionmovetime" #define FB_CVAR_MIN_VOLATILITY "k_fbskill_vol_min" #define FB_CVAR_MAX_VOLATILITY "k_fbskill_vol_max" #define FB_CVAR_INITIAL_VOLATILITY "k_fbskill_vol_init" #define FB_CVAR_REDUCE_VOLATILITY "k_fbskill_vol_reduce" #define FB_CVAR_OWNSPEED_VOLATILITY_THRESHOLD "k_fbskill_vol_ownvel" #define FB_CVAR_OWNSPEED_VOLATILITY_INCREASE "k_fbskill_vol_ownvel_incr" #define FB_CVAR_ENEMYSPEED_VOLATILITY_THRESHOLD "k_fbskill_vol_oppvel" #define FB_CVAR_ENEMYSPEED_VOLATILITY_INCREASE "k_fbskill_vol_oppvel_incr" #define FB_CVAR_ENEMYDIRECTION_VOLATILITY_INCREASE "k_fbskill_vol_oppdir_incr" #define FB_CVAR_PAIN_VOLATILITY_INCREASE "k_fbskill_vol_pain_incr" #define FB_CVAR_SELF_MIDAIR_VOLATILITY_INCREASE "k_fbskill_vol_bot_midair_incr" #define FB_CVAR_OPPONENT_MIDAIR_VOLATILITY_INCREASE "k_fbskill_vol_opp_midair_incr" #define FB_CVAR_MOVEMENT_SKILL "k_fbskill_movement" #define FB_CVAR_MOVEMENT_DMM4WIGGLE "k_fbskill_dmm4wiggle" #define FB_CVAR_MOVEMENT_DMM4WIGGLETOGGLE "k_fbskill_dmm4wiggletoggle" #define FB_CVAR_MOVEMENT_WIGGLEFRAMES "k_fbskill_wiggleframes" #define FB_CVAR_COMBATJUMP_CHANCE "k_fbskill_combatjump" #define FB_CVAR_MISSILEDODGE_TIME "k_fbskill_missiledodge" static float RangeOverSkill(int skill_level, float minimum, float maximum) { float skill = skill_level * 1.0f / (MAX_FROGBOT_SKILL - MIN_FROGBOT_SKILL); return (minimum + skill * (maximum - minimum)); } void RunRandomTrials(float min, float max, float mult) { int i = 0; int trials = 1000; float frac = (max - min) / 6; int hits[] = { 0, 0, 0, 0, 0, 0 }; for (i = 0; i < trials; ++i) { float result = dist_random(min, max, mult); if (result < (min + frac)) { ++hits[0]; } else if (result < (min + (frac * 2))) { ++hits[1]; } else if (result < (min + (frac * 3))) { ++hits[2]; } else if (result < (min + (frac * 4))) { ++hits[3]; } else if (result < (min + (frac * 5))) { ++hits[4]; } else { ++hits[5]; } } G_bprint(2, "Randomisation trials: %f to %f, %f\n", min, max, mult); for (i = 0; i < 6; ++i) { G_bprint(2, " < %2.3f: %4d %3.2f%%\n", min + frac * (i + 1), hits[i], hits[i] * 100.0f / trials); } } void RegisterSkillVariables(void) { extern qbool RegisterCvar(const char *var); RegisterCvar(FB_CVAR_DODGEFACTOR); RegisterCvar(FB_CVAR_LOOKANYWHERE); RegisterCvar(FB_CVAR_LOOKAHEADTIME); RegisterCvar(FB_CVAR_PREDICTIONERROR); RegisterCvar(FB_CVAR_VISIBILITY); RegisterCvar(FB_CVAR_LGPREF); RegisterCvar(FB_CVAR_ACCURACY); RegisterCvar(FB_CVAR_YAW_MIN_ERROR); RegisterCvar(FB_CVAR_YAW_MAX_ERROR); RegisterCvar(FB_CVAR_YAW_MULTIPLIER); RegisterCvar(FB_CVAR_YAW_SCALE); RegisterCvar(FB_CVAR_PITCH_MIN_ERROR); RegisterCvar(FB_CVAR_PITCH_MAX_ERROR); RegisterCvar(FB_CVAR_PITCH_MULTIPLIER); RegisterCvar(FB_CVAR_PITCH_SCALE); RegisterCvar(FB_CVAR_ATTACK_RESPAWNS); RegisterCvar(FB_CVAR_REACTION_TIME); RegisterCvar(FB_CVAR_REACTION_MOVETIME); RegisterCvar(FB_CVAR_MIN_VOLATILITY); RegisterCvar(FB_CVAR_MAX_VOLATILITY); RegisterCvar(FB_CVAR_INITIAL_VOLATILITY); RegisterCvar(FB_CVAR_REDUCE_VOLATILITY); RegisterCvar(FB_CVAR_OWNSPEED_VOLATILITY_THRESHOLD); RegisterCvar(FB_CVAR_OWNSPEED_VOLATILITY_INCREASE); RegisterCvar(FB_CVAR_ENEMYSPEED_VOLATILITY_THRESHOLD); RegisterCvar(FB_CVAR_ENEMYSPEED_VOLATILITY_INCREASE); RegisterCvar(FB_CVAR_ENEMYDIRECTION_VOLATILITY_INCREASE); RegisterCvar(FB_CVAR_MOVEMENT_SKILL); RegisterCvar(FB_CVAR_MOVEMENT_DMM4WIGGLE); RegisterCvar(FB_CVAR_MOVEMENT_WIGGLEFRAMES); RegisterCvar(FB_CVAR_MOVEMENT_DMM4WIGGLETOGGLE); RegisterCvar(FB_CVAR_COMBATJUMP_CHANCE); RegisterCvar(FB_CVAR_MISSILEDODGE_TIME); RegisterCvar(FB_CVAR_DISTANCEERROR); RegisterCvar(FB_CVAR_PAIN_VOLATILITY_INCREASE); RegisterCvar(FB_CVAR_SELF_MIDAIR_VOLATILITY_INCREASE); RegisterCvar(FB_CVAR_OPPONENT_MIDAIR_VOLATILITY_INCREASE); } qbool SetAttributesBasedOnSkill(int skill) { char *cfg_name; qbool customised = false; int aimskill; skill = bound(MIN_FROGBOT_SKILL, skill, MAX_FROGBOT_SKILL); aimskill = bound(MIN_FROGBOT_SKILL, skill, MAX_FROGBOT_AIM_SKILL); // Old frogbot settings (items generally) cvar_fset(FB_CVAR_ACCURACY, 45 - min(skill, 10) * 2.25); cvar_fset(FB_CVAR_DODGEFACTOR, RangeOverSkill(skill, 0.0f, 1.0f)); cvar_fset(FB_CVAR_LOOKANYWHERE, RangeOverSkill(skill, 0.0f, 1.0f)); cvar_fset(FB_CVAR_LOOKAHEADTIME, RangeOverSkill(skill, 5.0f, 30.0f)); cvar_fset(FB_CVAR_PREDICTIONERROR, RangeOverSkill(skill, 1.0f, 0.0f)); cvar_fset(FB_CVAR_DISTANCEERROR, RangeOverSkill(skill, 0.15f, 0.0f)); // Old, but used to be global cvar_fset(FB_CVAR_LGPREF, RangeOverSkill(skill, 0.2f, 1.0f)); cvar_fset(FB_CVAR_VISIBILITY, 0.7071067f - (0.02f * min(skill, 10))); // equivalent of 90 => 120 fov cvar_fset(FB_CVAR_YAW_MIN_ERROR, RangeOverSkill(aimskill, 1.5, 1)); cvar_fset(FB_CVAR_YAW_MAX_ERROR, RangeOverSkill(aimskill, 4.5, 3)); cvar_fset(FB_CVAR_YAW_MULTIPLIER, RangeOverSkill(aimskill, 4, 2.5)); cvar_fset(FB_CVAR_YAW_SCALE, RangeOverSkill(aimskill, 5, 2)); cvar_fset(FB_CVAR_PITCH_MIN_ERROR, RangeOverSkill(aimskill, 1.5, 1)); cvar_fset(FB_CVAR_PITCH_MAX_ERROR, RangeOverSkill(aimskill, 4.5, 3)); cvar_fset(FB_CVAR_PITCH_MULTIPLIER, RangeOverSkill(aimskill, 4, 2)); cvar_fset(FB_CVAR_PITCH_SCALE, RangeOverSkill(aimskill, 5, 2)); cvar_fset(FB_CVAR_ATTACK_RESPAWNS, skill >= 15 ? 1 : 0); cvar_fset(FB_CVAR_REACTION_TIME, RangeOverSkill(skill, 0.75f, 0.3f)); cvar_fset(FB_CVAR_REACTION_MOVETIME, RangeOverSkill(skill, 0.3f, 0.1f)); // Volatility cvar_fset(FB_CVAR_MIN_VOLATILITY, 1.0f); cvar_fset(FB_CVAR_MAX_VOLATILITY, RangeOverSkill(skill, 4.0f, 2.5f)); cvar_fset(FB_CVAR_INITIAL_VOLATILITY, RangeOverSkill(skill, 3.0f, 1.4f)); cvar_fset(FB_CVAR_REDUCE_VOLATILITY, RangeOverSkill(skill, 0.98f, 0.96f)); cvar_fset(FB_CVAR_OWNSPEED_VOLATILITY_THRESHOLD, RangeOverSkill(skill, 360, 450)); cvar_fset(FB_CVAR_OWNSPEED_VOLATILITY_INCREASE, RangeOverSkill(skill, 0.2f, 0.1f)); cvar_fset(FB_CVAR_ENEMYSPEED_VOLATILITY_THRESHOLD, RangeOverSkill(skill, 360, 450)); cvar_fset(FB_CVAR_ENEMYSPEED_VOLATILITY_INCREASE, RangeOverSkill(skill, 0.4f, 0.2f)); cvar_fset(FB_CVAR_ENEMYDIRECTION_VOLATILITY_INCREASE, RangeOverSkill(skill, 0.6f, 0.4f)); cvar_fset(FB_CVAR_PAIN_VOLATILITY_INCREASE, RangeOverSkill(skill, 0.5f, 0.1f)); cvar_fset(FB_CVAR_SELF_MIDAIR_VOLATILITY_INCREASE, RangeOverSkill(skill, 1.0f, 0.0f)); cvar_fset(FB_CVAR_OPPONENT_MIDAIR_VOLATILITY_INCREASE, RangeOverSkill(skill, 1.0f, 0.0f)); // Movement cvar_fset(FB_CVAR_MOVEMENT_SKILL, RangeOverSkill(skill, 0.3f, 1.0f)); cvar_fset(FB_CVAR_MOVEMENT_DMM4WIGGLE, skill > 10 ? 1 : 0); cvar_fset(FB_CVAR_MOVEMENT_DMM4WIGGLETOGGLE, skill > 10 ? RangeOverSkill((skill - 10) * 2, 0.0f, 0.25f) : 0); cvar_fset(FB_CVAR_MOVEMENT_WIGGLEFRAMES, RangeOverSkill(skill, 30, 20)); cvar_fset(FB_CVAR_COMBATJUMP_CHANCE, RangeOverSkill(skill, 0.03f, 0.1f)); cvar_fset(FB_CVAR_MISSILEDODGE_TIME, RangeOverSkill(skill, 1.0f, 0.5f)); // Customise { char buf[1024 * 4]; cfg_name = va("bots/configs/skill_all.cfg"); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); customised = true; } cfg_name = va("bots/configs/skill_%02d.cfg", skill); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); customised = true; } } return customised; } // TODO: Exchange standard attributes for different bot characters/profiles void SetAttribs(gedict_t *self, qbool customised) { self->fb.skill.accuracy = bound(0, cvar( FB_CVAR_ACCURACY), 45); self->fb.skill.dodge_amount = bound(0, cvar( FB_CVAR_DODGEFACTOR), 1); self->fb.skill.look_anywhere = bound(0, cvar( FB_CVAR_LOOKANYWHERE), 1); self->fb.skill.lookahead_time = bound(0, cvar( FB_CVAR_LOOKAHEADTIME), 45); self->fb.skill.prediction_error = bound(0, cvar(FB_CVAR_PREDICTIONERROR), 1); self->fb.skill.movement_estimate_error = bound(0, cvar(FB_CVAR_DISTANCEERROR), 0.25); self->fb.skill.lg_preference = bound(0, cvar( FB_CVAR_LGPREF), 1); self->fb.skill.visibility = bound(0.5, cvar( FB_CVAR_VISIBILITY), 0.7071067f); // fov 90 (0.707) => fov 120 (0.5) self->fb.skill.aim_params[YAW].minimum = bound(0, cvar(FB_CVAR_YAW_MIN_ERROR), 1); self->fb.skill.aim_params[YAW].maximum = bound(0, cvar(FB_CVAR_YAW_MAX_ERROR), 10); self->fb.skill.aim_params[YAW].multiplier = bound(0, cvar(FB_CVAR_YAW_MULTIPLIER), 10); self->fb.skill.aim_params[YAW].scale = bound(0, cvar(FB_CVAR_YAW_SCALE), 5); self->fb.skill.aim_params[PITCH].minimum = bound(0, cvar(FB_CVAR_PITCH_MIN_ERROR), 10); self->fb.skill.aim_params[PITCH].maximum = bound(0, cvar(FB_CVAR_PITCH_MAX_ERROR), 10); self->fb.skill.aim_params[PITCH].multiplier = bound(0, cvar(FB_CVAR_PITCH_MULTIPLIER), 10); self->fb.skill.aim_params[PITCH].scale = bound(0, cvar(FB_CVAR_PITCH_SCALE), 5); self->fb.skill.attack_respawns = cvar(FB_CVAR_ATTACK_RESPAWNS) > 0; // Volatility self->fb.skill.min_volatility = bound(0, cvar(FB_CVAR_MIN_VOLATILITY), 5.0f); self->fb.skill.max_volatility = bound(0, cvar(FB_CVAR_MAX_VOLATILITY), 5.0f); self->fb.skill.initial_volatility = bound(0, cvar(FB_CVAR_INITIAL_VOLATILITY), 5.0f); self->fb.skill.reduce_volatility = bound(0, cvar(FB_CVAR_REDUCE_VOLATILITY), 1.0f); self->fb.skill.ownspeed_volatility_threshold = bound( 0, cvar(FB_CVAR_OWNSPEED_VOLATILITY_THRESHOLD), 1000); self->fb.skill.ownspeed_volatility = bound(0, cvar(FB_CVAR_OWNSPEED_VOLATILITY_INCREASE), 5.0f); self->fb.skill.enemyspeed_volatility_threshold = bound( 0, cvar(FB_CVAR_ENEMYSPEED_VOLATILITY_THRESHOLD), 1000); self->fb.skill.enemyspeed_volatility = bound(0, cvar(FB_CVAR_ENEMYSPEED_VOLATILITY_INCREASE), 5.0f); self->fb.skill.enemydirection_volatility = bound( 0, cvar(FB_CVAR_ENEMYDIRECTION_VOLATILITY_INCREASE), 5.0f); self->fb.skill.awareness_delay = bound(0, cvar(FB_CVAR_REACTION_TIME), 1.0f); self->fb.skill.spawn_move_delay = bound(0, cvar(FB_CVAR_REACTION_MOVETIME), 1.0f); self->fb.skill.pain_volatility = bound(0, cvar(FB_CVAR_PAIN_VOLATILITY_INCREASE), 2.0f); self->fb.skill.self_midair_volatility = bound(0, cvar(FB_CVAR_SELF_MIDAIR_VOLATILITY_INCREASE), 2.0f); self->fb.skill.opponent_midair_volatility = bound( 0, cvar(FB_CVAR_OPPONENT_MIDAIR_VOLATILITY_INCREASE), 2.0f); // Movement self->fb.skill.movement = bound(0, cvar(FB_CVAR_MOVEMENT_SKILL), 1.0f); self->fb.skill.wiggle_run_dmm4 = bound(0, (int)cvar(FB_CVAR_MOVEMENT_DMM4WIGGLE), 1.0f); self->fb.skill.wiggle_run_limit = bound(0, (int)cvar(FB_CVAR_MOVEMENT_WIGGLEFRAMES), 45.0f); self->fb.skill.wiggle_toggle = bound(0, cvar(FB_CVAR_MOVEMENT_DMM4WIGGLETOGGLE), 1.0f); self->fb.skill.combat_jump_chance = bound(0, cvar(FB_CVAR_COMBATJUMP_CHANCE), 1.0f); self->fb.skill.missile_dodge_time = bound(0, cvar(FB_CVAR_MISSILEDODGE_TIME), 1.5f); self->fb.skill.customised = customised; } char* BotNameEnemy(int botNumber) { char *names[] = { ": Timber", ": Sujoy", ": Nightwing", ": Cenobite", ": Thresh", ": Frick", ": Unholy", ": Reptile", ": Nikodemus", ": Paralyzer", ": Xenon", ": Spice" ": Kornelia", ": Rix", ": Batch", ": Gollum" }; char *custom_name = cvar_string(va("k_fb_name_enemy_%d", botNumber)); if (strnull(custom_name)) { return names[(int)bound(0, botNumber, sizeof(names) / sizeof(names[0]) - 1)]; } return custom_name; } char* BotNameFriendly(int botNumber) { char *names[] = { "> MrJustice", "> DanJ", "> Gunner", "> Tele", "> Jakey", "> Parrais", "> Thurg", "> Kool", "> Zaphod", "> Dreamer", "> Mandrixx", "> Skill5", "> Vid", "> Soul99", "> Jon", "> Gaz" }; char *custom_name = cvar_string(va("k_fb_name_team_%d", botNumber)); if (strnull(custom_name)) { return names[(int)bound(0, botNumber, sizeof(names) / sizeof(names[0]) - 1)]; } return custom_name; } char* BotNameGeneric(int botNumber) { char *names[] = { "/ bro", "/ goldenboy", "/ tincan", "/ grue", "/ dizzy", "/ daisy", "/ denzil", "/ dora", "/ shortie", "/ machina", "/ gudgie", "/ scoosh", "/ frazzle", "/ pop", "/ junk", "/ overflow" }; char *hf_names[] = { "mutilator", "drejfus", "griffin", "heddan", "legio", "wigorf", "madmax", "mrlame", "aptiva", "nepra", "nikke", "parasite", "rushing", "lipton", "xorcist" }; char *custom_name = cvar_string(va("k_fb_name_%d", botNumber)); if (strnull(custom_name)) { return tot_mode_enabled() ? hf_names[(int)bound(0, botNumber, sizeof(hf_names) / sizeof(hf_names[0]) - 1)] : names[(int)bound(0, botNumber, sizeof(names) / sizeof(names[0]) - 1)]; } return custom_name; } #endif QW-Group-ktx-d05d6ca/src/bot_botjump.c000066400000000000000000000310731475442401000177130ustar00rootroot00000000000000/* bot/botjump.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2001 Justice Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void DemoMark(void); #define FB_LAVAJUMP_NOT 0 // not lava-jumping #define FB_LAVAJUMP_SINK 1 // deliberately sinking, waiting for waterlevel == 3 #define FB_LAVAJUMP_RISE 2 // ready to fire on first sign of waterlevel == 2 static vec3_t straight_up = { 0, 0, 1 }; static vec3_t straight_down = { 0, 0, -1 }; /* // Returns true if the bot is travelling in the 'right' direction (with 90 degrees of target) static qbool right_direction(gedict_t* self) { vec3_t test_direction, direction_to_test_marker; float current_direction, desired_direction; float min_one, min_two; // current direction normalize(self->fb.oldvelocity, test_direction); current_direction = vectoyaw(test_direction); // desired direction VectorSubtract(self->fb.linked_marker->s.v.origin, self->s.v.origin, direction_to_test_marker); normalize(direction_to_test_marker, test_direction); desired_direction = vectoyaw(test_direction); min_one = fabs(desired_direction - current_direction); // Reduce angle size and try again, incase one was 20 and the other was 340.. if (desired_direction >= 180) { desired_direction -= 360; } if (current_direction >= 180) { current_direction -= 360; } min_two = fabs(desired_direction - current_direction); return (qbool)(min(min_one, min_two) <= 90); }*/ // Returns true if space above bot static float BotCheckSpaceAbove(gedict_t *self) { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 140, true, self); return (g_globalvars.trace_fraction == 1); } /* // Returns true if ground directly in front of bot static float checkground(gedict_t* self) { trap_makevectors(self->s.v.v_angle); g_globalvars.v_forward[2] = 0; VectorNormalize(g_globalvars.v_forward); VectorScale(g_globalvars.v_forward, 10, g_globalvars.v_forward); traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0] + g_globalvars.v_forward[0], self->s.v.origin[1] + g_globalvars.v_forward[1], self->s.v.origin[2] + g_globalvars.v_forward[2] - 40, true, self); return (g_globalvars.trace_fraction != 1); } */ void BotCanRocketJump(gedict_t *self) { qbool has_quad = self->super_damage_finished > g_globalvars.time; qbool tp_damage = teamplay != 1 && teamplay != 5; //float health_after = TotalStrengthAfterDamage(self->s.v.health, self->s.v.armorvalue, self->s.v.armortype, tp_damage ? 55 * (has_quad ? 4 : 1) : 0); qbool has_rl = (qbool)(((int)self->s.v.items & IT_ROCKET_LAUNCHER) && (self->s.v.ammo_rockets >= 1)); qbool has_pent = (qbool)((int)self->s.v.items & IT_INVULNERABILITY); qbool will_pickup = self->fb.linked_marker && !WaitingToRespawn(self->fb.linked_marker); qbool onground = (int)self->s.v.flags & FL_ONGROUND; if (self->fb.debug_path) { self->fb.canRocketJump = self->fb.debug_path_rj; } else if (has_rl && (self->s.v.waterlevel > 1) && (trap_pointcontents(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2]) == CONTENT_LAVA)) { // In lava, is our main priority... self->fb.canRocketJump = true; } else if (!has_rl || self->fb.be_quiet || !onground) { self->fb.canRocketJump = false; } else if (has_pent) { // If invincible, can always rocket jump self->fb.canRocketJump = true; } else { // work out how much health we'll have in next marker float health_after = TotalStrengthAfterDamage(self->s.v.health, self->s.v.armorvalue, self->s.v.armortype, tp_damage ? 55 * (has_quad ? 4 : 1) : 0); if ((health_after >= 0) && will_pickup) { // FIXME: This is broken, need to know how much health/armor they'd have left after initial impact // Also take into account the goal entity, not just next link in path if (self->fb.linked_marker->tp_flags & (it_mh | it_health)) { health_after += 50; } } // FIXME: this threshold should be flexible depending on fuzzy logic // - depending on enemy status (maybe higher or lower depending on strength of enemy) // - might be higher or lower depending on running away from enemy // - might be lower if we need to beat enemy to item (quad for instance) self->fb.canRocketJump = health_after > 110; } } /* // FIXME: If teammate is strong (RA etc), fire anyway? Also if boomsticker and we are strong // FIXME: Use find_radius? Currently ignores teammates behind them. static qbool CouldHurtNearbyTeammate(gedict_t* me) { gedict_t* p; // if the bot can't kill them, then don't worry about it if (teamplay != 2) { return false; } p = IdentifyMostVisibleTeammate(me); return VectorDistance(p->s.v.origin, me->s.v.origin) < 140; } */ // Checks that (x=>z, y=>z) direction is sufficiently similar static qbool DirectionCheck(vec3_t start, vec3_t end, vec3_t vel, float threshold) { vec3_t path, hor_vel; VectorSubtract(end, start, path); path[2] = 0; VectorCopy(vel, hor_vel); hor_vel[2] = 0; VectorNormalize(path); VectorNormalize(hor_vel); return (DotProduct(path, hor_vel) >= threshold); } static void BotLavaJumpRise(gedict_t *self) { self->fb.arrow = BACK; NewVelocityForArrow(self, straight_up, "LavaJump1"); self->fb.path_state |= ROCKET_JUMP; self->fb.lavaJumpState = FB_LAVAJUMP_RISE; self->fb.desired_angle[PITCH] = 78.25; } static void BotLavaJumpSink(gedict_t *self) { self->fb.swim_arrow = DOWN; self->fb.rocketJumping = false; NewVelocityForArrow(self, straight_down, "LavaJump3"); // Moving backwards... self->fb.lavaJumpState = FB_LAVAJUMP_SINK; self->fb.desired_angle[PITCH] = 78.25; self->fb.up_finished = 0; } static void SetRocketJumpAngles(gedict_t *self) { if (self->fb.path_state & ROCKET_JUMP) { if (self->fb.rocketJumpAngles[PITCH] > 0) { self->fb.desired_angle[PITCH] = self->fb.rocketJumpAngles[PITCH]; } else { self->fb.desired_angle[PITCH] = 78.25; } if (self->fb.rocketJumpAngles[YAW] > 0) { self->fb.desired_angle[YAW] = self->fb.rocketJumpAngles[YAW]; } } } static void BotPerformLavaJump(gedict_t *self) { vec3_t point; int content; VectorSet(point, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] - 24); content = self->s.v.waterlevel > 1 ? trap_pointcontents(PASSVEC3(point)) : CONTENT_EMPTY; // Have fired but still in lava if ((self->fb.path_state & BOTPATH_RJ_IN_PROGRESS) && (content == CONTENT_LAVA)) { BotLavaJumpRise(self); self->fb.desired_angle[PITCH] = 78.25; return; } // Waiting to fire, still in lava if ((content == CONTENT_LAVA) && self->fb.rocketJumpFrameDelay) { BotLavaJumpRise(self); self->fb.desired_angle[PITCH] = 78.25; return; } if (self->fb.canRocketJump && (content == CONTENT_LAVA)) { switch (self->fb.lavaJumpState) { case FB_LAVAJUMP_NOT: if ((self->s.v.waterlevel >= 2) && BotCheckSpaceAbove(self)) { vec3_t linked_direction; float best_yaw = 0; // Face away from target VectorSubtract(self->s.v.origin, self->fb.linked_marker->s.v.origin, linked_direction); best_yaw = vectoyaw(linked_direction); if (self->s.v.waterlevel == 3) { BotLavaJumpRise(self); self->fb.desired_angle[YAW] = best_yaw; } else { BotLavaJumpSink(self); self->fb.desired_angle[YAW] = best_yaw; } } else { // Move as standard, hopefully to somewhere with space return; } break; case FB_LAVAJUMP_SINK: if ((self->s.v.waterlevel == 3) || (self->s.v.velocity[2] == 0)) { // That's far enough, start rising again BotLavaJumpRise(self); } else { // Keep going BotLavaJumpSink(self); } break; case FB_LAVAJUMP_RISE: if (self->fb.up_finished && (g_globalvars.time > self->fb.up_finished)) { // Lava jump failed, back to sinking... BotLavaJumpSink(self); } else if (self->s.v.waterlevel == 3) { BotLavaJumpRise(self); } else { // Broken surface, time to fire... queue up a delay... vec3_t explosion_point; float distance_frac; float frames_to_explosion; SetRocketJumpAngles(self); FindRocketExplosionPoint(self->s.v.origin, self->fb.desired_angle, explosion_point, &distance_frac); BotLavaJumpRise(self); frames_to_explosion = (VectorDistance(self->s.v.origin, explosion_point) / 1000) / g_globalvars.frametime; self->fb.rocketJumping = true; self->fb.rocketJumpFrameDelay = 12 - (int)frames_to_explosion; self->fb.lavaJumpState = FB_LAVAJUMP_NOT; self->fb.up_finished = g_globalvars.time + 0.1; } break; } } } // Performs rocket jump void BotPerformRocketJump(gedict_t *self) { if (!(self->fb.touch_marker && self->fb.linked_marker)) { return; } BotPerformLavaJump(self); if (self->fb.rocketJumping) { // In middle of rocket jumping --self->fb.rocketJumpFrameDelay; } else if (self->fb.canRocketJump && ((int)self->s.v.flags & FL_ONGROUND)) { qbool path_is_rj = self->fb.path_state & ROCKET_JUMP; qbool ok_to_rj = match_in_progress == 2 || (self->fb.debug_path && self->fb.debug_path_rj); float touch_dist = VectorDistance(self->s.v.origin, self->fb.touch_marker->s.v.origin); // Close enough to marker qbool ok_distance = touch_dist >= 10 && touch_dist <= 100; // Travelling towards target qbool ok_direction = DirectionCheck(self->fb.touch_marker->s.v.origin, self->fb.linked_marker->s.v.origin, self->s.v.velocity, 0.8f); // FIXME: TODO // Going at reasonable pace qbool ok_vel = VectorLength(self->s.v.velocity) > sv_maxspeed * 0.9; // Fire will trigger (technically we could jump anyway if framedelay enabled, but leave for now) qbool ok_to_fire = !self->s.v.button0 && self->attack_finished < g_globalvars.time; // FIXME: TODO: Also used to check they wouldn't kill teammate, but think that should be fuzzy logic qbool can_start_rj = ok_to_rj && path_is_rj && ok_distance && ok_direction && ok_to_fire && ok_vel; if (can_start_rj) { // Perform the jump //G_bprint (PRINT_HIGH, "rocket-jumping: %s, distance %s, dir %s, fire %s\n", path_is_rj ? "yes" : "no", ok_distance ? "yes" : "no", ok_direction ? "yes" : "no", ok_to_fire ? "yes" : "no"); SetJumpFlag(self, true, "RocketJump"); self->fb.rocketJumping = true; self->fb.rocketJumpFrameDelay = self->fb.rocketJumpPathFrameDelay; self->fb.path_state |= DELIBERATE_AIR_WAIT_GROUND; if (FrogbotOptionEnabled(FB_OPTION_DEMOMARK_ROCKETJUMPS)) { DemoMark(); } } else if (self->fb.debug_path && ok_to_rj) { //G_bprint (PRINT_HIGH, "path_is_rj: %s, distance %s, dir %s, fire %s\n", path_is_rj ? "yes" : "no", ok_distance ? "yes" : "no", ok_direction ? "yes" : "no", ok_to_fire ? "yes" : "no"); } } // Is it time to fire if (self->fb.rocketJumping) { if (self->fb.rocketJumpFrameDelay <= 0) { SetRocketJumpAngles(self); self->fb.desired_weapon_impulse = 7; self->fb.firing = true; // Finish rocket jumping self->fb.rocketJumping = false; self->fb.path_state &= ROCKET_JUMP; self->fb.path_state |= BOTPATH_RJ_IN_PROGRESS; } else { // Make sure we don't start firing self->fb.firing = false; } } } static qbool PlayerFiringLG(gedict_t *player) { return (player && player->s.v.button0 && ((int)player->s.v.weapon & IT_LIGHTNING) && (player->s.v.ammo_cells > 0)); } void CheckCombatJump(gedict_t *self) { qbool inWater = self->s.v.waterlevel && self->fb.allowedMakeNoise; qbool onGround = ((int)self->s.v.flags & FL_ONGROUND); qbool lookingAtEnemy = self->fb.look_object && NUM_FOR_EDICT(self->fb.look_object) == self->s.v.enemy; qbool lookObjectFiringLG = PlayerFiringLG(self->fb.look_object); // Never combat jump when debugging route execution if (self->fb.debug_path) { return; } // Or immediately after spawning... if (FUTURE(min_fire_time)) { return; } // Or during prewar (noisy) if (match_in_progress < 2) { return; } // If jumping makes sense... if (!onGround || inWater) { return; } // Never jump in midair if (cvar("k_midair")) { return; } // Rocket jumping decisions made elsewhere if (self->fb.rocketJumping) { return; } // If path is expecting an edge then no combat jump... if (self->fb.path_state & (JUMP_LEDGE | BOTPATH_CURLJUMP_HINT)) { return; } // If surprised or player firing LG, don't jump if (!lookingAtEnemy || lookObjectFiringLG) { return; } // Now just down to bot characteristics SetJumpFlag(self, (g_random() < self->fb.skill.combat_jump_chance), "CombatJump"); } #endif QW-Group-ktx-d05d6ca/src/bot_botpath.c000066400000000000000000000352551475442401000177020ustar00rootroot00000000000000/* bot/botpath.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2001 DMSouL Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void DM3CampLogic(void); void DM4CampLogic(void); void DM6CampLogic(void); void DM6MarkerTouchLogic(gedict_t *self, gedict_t *goalentity_marker); qbool DM6LookAtDoor(gedict_t *self); static qbool HasItem(gedict_t *player, int mask) { return ((int)player->s.v.items & mask); } // FIXME: Globals static void BotWaitLogic(gedict_t *self, int *new_path_state) { gedict_t *touch_marker = self->fb.touch_marker; gedict_t *look_object = self->fb.look_object; // if we're not looking at a player if (look_object->ct != ctPlayer) { vec3_t linkedPos, lookPos; VectorAdd(self->fb.linked_marker->s.v.absmin, self->fb.linked_marker->s.v.view_ofs, linkedPos); VectorAdd(look_object->s.v.absmin, look_object->s.v.view_ofs, lookPos); traceline(linkedPos[0], linkedPos[1], linkedPos[2] + 32, lookPos[0], lookPos[1], lookPos[2] + 32, true, self); if (g_globalvars.trace_fraction != 1) { SetLinkedMarker(self, touch_marker, "BotWaitLogic"); *new_path_state = 0; } } else { // stop waiting self->fb.state &= ~WAIT; } } static void EvalLook(gedict_t *self, float *best_score, vec3_t dir_look, vec3_t linked_marker_origin) { vec3_t temp; float look_score; VectorAdd(from_marker->s.v.absmin, from_marker->s.v.view_ofs, temp); VectorSubtract(temp, linked_marker_origin, temp); VectorNormalize(temp); look_score = DotProduct(dir_look, temp); look_score = look_score + g_random(); // FIXME: Skill if (look_score > *best_score) { *best_score = look_score; self->fb.look_object = from_marker; } } static void EvalCloseRunAway(float runaway_time, gedict_t *enemy_touch_marker, float look_traveltime_squared, float *best_away_score, gedict_t **best_away_marker, gedict_t *touch_marker) { float test_away_score = 0; float traveltime2; from_marker = enemy_touch_marker; ZoneMarker(from_marker, to_marker, path_normal, false); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, false); traveltime2 = traveltime; from_marker = touch_marker; ZoneMarker(from_marker, to_marker, path_normal, false); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, false); if (look_traveltime) { test_away_score = g_random() * runaway_time * ((traveltime2 * traveltime2) - (look_traveltime_squared + (traveltime * traveltime))) / (look_traveltime * traveltime); } else { test_away_score = g_random() * runaway_time * (traveltime2 - traveltime); } if (test_away_score > *best_away_score) { *best_away_marker = to_marker; *best_away_score = test_away_score; } } static qbool CheckForRocketEnemyAim(gedict_t *self) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; if ((enemy_ != world) && HasItem(enemy_, IT_ROCKET_LAUNCHER) && !HasItem(self, IT_INVULNERABILITY)) { // FIXME: random() call to determine behaviour, move threshold to bot's skill if ((enemy_->attack_finished <= (g_globalvars.time + 0.2)) && enemy_->s.v.ammo_rockets && (g_random() < 0.5)) { vec3_t src; VectorCopy(enemy_->s.v.origin, src); src[2] += 16; traceline(src[0], src[1], src[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], true, self); // Fixme: Only avoid rocket aim if there's a direct line, rather than if they are within range of the explosion... if (g_globalvars.trace_fraction != 1) { trap_makevectors(enemy_->s.v.v_angle); traceline(src[0], src[1], src[2], src[0] + g_globalvars.v_forward[0] * 500, src[1] + g_globalvars.v_forward[1] * 500, src[2] + g_globalvars.v_forward[2] * 500, true, self); VectorCopy(g_globalvars.trace_endpos, self->fb.rocket_endpos); return true; } } } return false; } static qbool OnLift(gedict_t *self) { if (streq(self->fb.touch_marker->classname, "door") && (self->deathtype == dtSQUISH)) { if ((self->fb.linked_marker->s.v.absmin[2] + self->fb.linked_marker->s.v.view_ofs[2]) > (self->s.v.origin[2] + 18)) { if (teamplay) { self->fb.state &= ~HELP_TEAMMATE; } if (self->s.v.absmin[0] >= self->fb.touch_marker->s.v.absmin[0]) { if (self->s.v.absmax[0] <= self->fb.touch_marker->s.v.absmax[0]) { if (self->s.v.absmin[1] >= self->fb.touch_marker->s.v.absmin[1]) { if (self->s.v.absmax[1] <= self->fb.touch_marker->s.v.absmax[1]) { SetLinkedMarker(self, self->fb.touch_marker, "OnLift"); self->fb.path_state = 0; self->fb.linked_marker_time = g_globalvars.time + 5; self->fb.old_linked_marker = NULL; } } } } return true; } } return false; } static qbool LookingAtPlayer(gedict_t *self) { return (self->fb.look_object && (self->fb.look_object->ct == ctPlayer)); } qbool WaitingToHitGround(gedict_t *self) { return (self->fb.path_state & WAIT_GROUND) && !((int)self->s.v.flags & FL_ONGROUND); } static qbool WalkTowardsDroppedItem(gedict_t *self) { gedict_t *goalentity_ = &g_edicts[self->s.v.goalentity]; if (streq(goalentity_->classname, "backpack") && VisibleEntity(goalentity_)) { SetLinkedMarker(self, goalentity_, "ProcNewLinked(backpack)"); self->fb.linked_marker_time = g_globalvars.time + 5; self->fb.old_linked_marker = self->fb.touch_marker; return true; } else if (goalentity_->cnt) { SetLinkedMarker(self, goalentity_, "ProcNewLinked(dropped-powerup)"); self->fb.linked_marker_time = g_globalvars.time + 5; self->fb.old_linked_marker = self->fb.touch_marker; return true; } return false; } // FIXME: Move to bot_aim static qbool PredictionShotLogic(gedict_t *self, gedict_t *goalentity_marker) { if ((match_in_progress == 2) && (g_random() < self->fb.skill.look_anywhere)) { gedict_t *from_marker = g_edicts[self->s.v.enemy].fb.touch_marker; from_marker = (from_marker ? from_marker : goalentity_marker); if (from_marker) { gedict_t *to_marker = self->fb.linked_marker; look_marker = SightFromMarkerFunction(from_marker, to_marker); if (look_marker) { path_normal = true; ZoneMarker(from_marker, look_marker, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, look_marker, self->fb.canRocketJump); look_traveltime = traveltime; } else { look_marker = SightMarker(from_marker, to_marker, 0, 0); } if (look_marker) { to_marker = from_marker; from_marker = self->fb.linked_marker; path_normal = true; ZoneMarker(from_marker, to_marker, path_normal, self->fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to_marker, self->fb.canRocketJump); if (look_traveltime < traveltime) { self->fb.look_object = look_marker; self->fb.predict_shoot = true; return true; } } } } return false; } void ProcessNewLinkedMarker(gedict_t *self) { gedict_t *goalentity_ = &g_edicts[self->s.v.goalentity]; gedict_t *goalentity_marker = (goalentity_ == world || (self->fb.state & RUNAWAY) ? NULL : goalentity_->fb.touch_marker); qbool trace_bprint = self->fb.debug; qbool rocket_jump_routes_allowed = self->fb.canRocketJump; qbool rocket_alert = false; float best_score = PATH_SCORE_NULL; vec3_t player_direction; gedict_t *new_linked_marker; int new_path_state = 0; int new_angle_hint = 0; int new_rj_delay = 0; float new_rj_angles[2] = { 0, 0 }; if (WaitingToHitGround(self)) { return; } if (self->fb.linked_marker == self->fb.touch_marker) { if (goalentity_ == self->fb.touch_marker) { if (!WaitingToRespawn(self->fb.touch_marker)) { // Have arrived at goal entity but not quite touched it yet return; } } else if (goalentity_marker == self->fb.touch_marker && WalkTowardsDroppedItem(self)) { return; } } else { new_path_state = 0; if (ExistsPath(self->fb.old_linked_marker, self->fb.touch_marker, &new_path_state)) { if (ExistsPath(self->fb.touch_marker, self->fb.linked_marker, &new_path_state)) { self->fb.path_state = new_path_state; return; } } self->fb.state &= ~HURT_SELF; } self->fb.path_normal_ = true; if (self->fb.state & RUNAWAY) { gedict_t *enemy_touch_marker = g_edicts[self->s.v.enemy].fb.touch_marker; if (enemy_touch_marker) { int i = 0; float best_away_score = 0; float look_traveltime_squared = 0; gedict_t *best_away_marker = NULL; to_marker = self->fb.touch_marker; look_traveltime = SightFromTime(enemy_touch_marker, to_marker); look_traveltime_squared = look_traveltime * look_traveltime; path_normal = true; for (i = 0; i < NUMBER_PATHS; ++i) { to_marker = self->fb.touch_marker->fb.runaway[i].next_marker; if (to_marker) { EvalCloseRunAway(self->fb.touch_marker->fb.runaway[i].time, enemy_touch_marker, look_traveltime_squared, &best_away_score, &best_away_marker, self->fb.touch_marker); } } self->fb.goal_respawn_time = 0; goalentity_marker = (best_away_marker ? best_away_marker : self->fb.touch_marker); self->fb.path_normal_ = true; } } // FIXME: have RL and weaker than enemy... set goal entity to marker on edge of zone that the bot can see? // Almost looks like this is picking a rocket-spam location? if (g_random() < 0.5) { qbool have_rl = HasItem(self, IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets; gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; if (have_rl) { if ((self->fb.firepower < enemy_->fb.firepower) && (self->s.v.armorvalue < enemy_->s.v.armorvalue)) { // Not avoiding enemy's rocket... if (!self->fb.avoiding && enemy_->fb.touch_marker) { gedict_t *look_marker = HigherSightFromFunction(self->fb.touch_marker, enemy_->fb.touch_marker); if (!look_marker) { look_marker = SightMarker(self->fb.touch_marker, enemy_->fb.touch_marker, 1000.0f, 40.0f); } if (look_marker) { goalentity_marker = look_marker; } } } } } // FIXME: what is this doing? Opponent has GL, close & firing... then do nothing? // Picking a grenade-spam location/direction? But it's checking if opponent has GL... if (isDuel()) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; qbool enemy_has_gl = HasItem(enemy_, IT_GRENADE_LAUNCHER) && enemy_->s.v.ammo_rockets > 6; if (enemy_has_gl) { if ((self->s.v.origin[2] + 18) < (enemy_->s.v.absmin[2] + enemy_->s.v.view_ofs[2])) { vec3_t diff; VectorSubtract(self->s.v.origin, enemy_->s.v.origin, diff); if (vlen(diff) < 200) { if (enemy_->s.v.button0 && enemy_->fb.touch_marker) { gedict_t *look_marker = HigherSightFromFunction(self->fb.touch_marker, enemy_->fb.touch_marker); if (!look_marker) { look_marker = SightMarker(self->fb.touch_marker, enemy_->fb.touch_marker, 1000.0f, 40.0f); } if (look_marker) { goalentity_marker = look_marker; } } } } } } rocket_alert = CheckForRocketEnemyAim(self); normalize(self->s.v.velocity, player_direction); self->fb.be_quiet = (self->s.v.enemy && &g_edicts[self->s.v.enemy] != self->fb.look_object && !self->fb.allowedMakeNoise); new_linked_marker = self->fb.linked_marker; PathScoringLogic(self->fb.goal_respawn_time, self->fb.be_quiet, self->fb.skill.lookahead_time, self->fb.path_normal_, self->s.v.origin, player_direction, self->fb.touch_marker, goalentity_marker, rocket_alert, rocket_jump_routes_allowed, trace_bprint, self, &best_score, &new_linked_marker, &new_path_state, &new_angle_hint, &new_rj_delay, new_rj_angles); SetLinkedMarker(self, new_linked_marker, "ProcNewLinked(std)"); // "check if fully on lift - if not then continue moving to linked_marker_" if (OnLift(self)) { return; } if (self->fb.state & WAIT) { BotWaitLogic(self, &new_path_state); } // FIXME: Map specific waiting points if (!self->fb.debug_path) { if (streq(mapname, "dm3")) { DM3CampLogic(); } else if (streq(mapname, "dm4")) { DM4CampLogic(); } else if (streq(mapname, "dm6")) { DM6CampLogic(); } } self->fb.path_state = new_path_state; self->fb.angle_hint = new_angle_hint; self->fb.rocketJumpFrameDelay = new_rj_delay; self->fb.rocketJumpAngles[PITCH] = new_rj_angles[PITCH]; self->fb.rocketJumpAngles[YAW] = new_rj_angles[YAW]; self->fb.linked_marker_time = g_globalvars.time + (self->fb.touch_marker == self->fb.linked_marker ? 0.3 : 5); self->fb.old_linked_marker = self->fb.touch_marker; // Logic past this point appears to be deciding what to look at... DM6MarkerTouchLogic(self, goalentity_marker); self->fb.state &= ~NOTARGET_ENEMY; if (((int)self->s.v.flags & FL_ONGROUND) && self->fb.wasinwater) { self->fb.wasinwater = false; self->fb.path_state &= ~WATERJUMP_; self->fb.state &= ~NOTARGET_ENEMY; } if (self->fb.path_state & WATERJUMP_) { self->fb.wasinwater = true; self->fb.state |= NOTARGET_ENEMY; self->fb.look_object = self->fb.linked_marker; SetJumpFlag(self, true, "WaterJump"); self->fb.waterjumping = true; self->fb.arrow_time = g_globalvars.time + 0.02; return; } // FIXME: Map-specific if (DM6LookAtDoor(self) || LookingAtPlayer(self)) { return; } // When treading water, look at the next waypoint if ((self->s.v.waterlevel == 2) || (self->s.v.waterlevel == 1)) { self->fb.look_object = self->fb.linked_marker; return; } if (PredictionShotLogic(self, goalentity_marker)) { return; } // Either look at the next marker or the marker after that... if (self->fb.linked_marker) { vec3_t dir_look = { 0 }; if (self->fb.touch_marker != self->fb.linked_marker) { vec3_t diff, linked_marker_origin; VectorAdd(self->fb.linked_marker->s.v.absmin, self->fb.linked_marker->s.v.view_ofs, linked_marker_origin); VectorSubtract(linked_marker_origin, self->s.v.origin, diff); normalize(diff, dir_look); } // Average of velocity, look angle and direction to next marker { vec3_t temp; trap_makevectors(self->s.v.v_angle); VectorScale(self->s.v.velocity, inv_sv_maxspeed, temp); VectorAdd(temp, g_globalvars.v_forward, temp); VectorAdd(temp, dir_look, temp); normalize(temp, dir_look); } // Look at the next marker... { int i = 0; vec3_t linked_marker_origin = { 0 }; float best_score = PATH_SCORE_NULL; VectorAdd(self->fb.linked_marker->s.v.absmin, self->fb.linked_marker->s.v.view_ofs, linked_marker_origin); for (i = 0; i < NUMBER_PATHS; ++i) { from_marker = self->fb.linked_marker->fb.paths[i].next_marker; if (from_marker) { EvalLook(self, &best_score, dir_look, linked_marker_origin); } } } } self->fb.predict_shoot = false; } #endif QW-Group-ktx-d05d6ca/src/bot_botphys.c000066400000000000000000000043521475442401000177230ustar00rootroot00000000000000/* bot/botphys.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" static float unstick_time = 0; static qbool no_bots_stuck = 0; int NumberOfClients(void) { int count = 0; gedict_t *plr = NULL; for (plr = world; (plr = find_plr(plr));) { if (plr->ct == ctPlayer) { ++count; } } return count; } void FrogbotPrePhysics1(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { if (p->isBot && p->s.v.takedamage) { VectorCopy(p->s.v.velocity, p->fb.oldvelocity); } } } void BotDetectTrapped(gedict_t *self) { // This tries to detect stuck bots, and fixes the situation by either jumping or committing suicide vec3_t point; int content1; VectorSet(point, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] - 24); content1 = trap_pointcontents(PASSVEC3(point)); if (content1 == CONTENT_EMPTY) { self->fb.oldwaterlevel = 0; self->fb.oldwatertype = CONTENT_EMPTY; } else if (content1 == CONTENT_SOLID) { unstick_time = unstick_time + g_globalvars.frametime; if (unstick_time <= NumberOfClients()) { no_bots_stuck = false; SetJumpFlag(self, true, "Trapped1"); } else { self->fb.botchose = true; self->fb.next_impulse = CLIENTKILL; } } else { int content2 = trap_pointcontents(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 4); if (content2 == CONTENT_EMPTY) { self->fb.oldwaterlevel = 1; self->fb.oldwatertype = content1; } else { int content3 = trap_pointcontents(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 22); if (content3 == CONTENT_EMPTY) { self->fb.oldwaterlevel = 2; self->fb.oldwatertype = content2; } else { self->fb.oldwaterlevel = 3; self->fb.oldwatertype = content3; } } } } void FrogbotPrePhysics2(void) { no_bots_stuck = true; for (self = world; (self = find_plr(self));) { if (self->isBot) { BotDetectTrapped(self); if (self->s.v.takedamage) { VectorCopy(self->s.v.origin, self->s.v.oldorigin); } } } if (no_bots_stuck) { unstick_time = 0; } } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_botstat.c000066400000000000000000000136231475442401000177140ustar00rootroot00000000000000/* bot/botstat.qc Copyright (C) 1997-1999 Robert 'Frog' Field */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // FIXME: Copy/paste from combat.c #ifndef Q3_VM // qvm have some bugs/round problem as i get from SD-Angel, so this trick float newceil(float f) { return ceil(((int)(f * 1000.0)) / 1000.0); } #else // native use lib ceil function #define newceil ceil #endif float TotalStrength(float health, float armorValue, float armorType) { if (match_in_progress < 2) { return 1000.0f; } return max(0, min(health / (1 - armorType), health + armorValue)); } float TotalStrengthAfterDamage(float health, float armorValue, float armorType, float damage) { float damage_saved = newceil(damage * armorType); if (damage_saved > armorValue) { // lost all armor damage_saved = armorValue; armorType = 0; } damage = newceil(damage - damage_saved); health -= damage; return (health <= 0 ? 0 : TotalStrength(health, armorValue, armorType)); } // Called every time the player's statistics change (item pickups etc) // Evaluate desire for armor, health etc based on the improvement it would cause void FrogbotSetHealthArmour(gedict_t *client) { client->fb.total_armor = client->s.v.armortype * client->s.v.armorvalue; client->fb.total_damage = TotalStrength(client->s.v.health, client->s.v.armorvalue, client->s.v.armortype); client->fb.desire_armor1 = client->fb.desire_armor2 = client->fb.desire_armorInv = 0; if (client->fb.total_armor < 160) { client->fb.desire_armorInv = max( 0, TotalStrength(client->s.v.health, 200.0f, 0.8f) - client->fb.total_damage); if (client->fb.total_armor < 90) { client->fb.desire_armor2 = max( 0, TotalStrength(client->s.v.health, 150.0f, 0.6f) - client->fb.total_damage); if (client->fb.total_armor < 30) { client->fb.desire_armor1 = max( 0, 2 * (TotalStrength(client->s.v.health, 100, 0.3f) - client->fb.total_damage)); } } } client->fb.desire_health0 = client->fb.desire_mega_health = 0; if (client->s.v.health < 250) { float new_health = min(client->s.v.health + 100, 250); client->fb.desire_mega_health = TotalStrength(new_health, client->s.v.armorvalue, client->s.v.armortype) - client->fb.total_damage; client->fb.desire_health0 = 0; if (client->s.v.health < 100) { new_health = min(client->s.v.health + 25, 100); client->fb.desire_health0 = 2 * (TotalStrength(new_health, client->s.v.armorvalue, client->s.v.armortype) - client->fb.total_damage); } } if ((int)client->ctf_flag & CTF_RUNE_RES) { client->fb.total_damage *= (cvar("k_ctf_rune_power_res") / 2) + 1; } } void FrogbotSetFirepower(gedict_t *self) { int items_ = (int)self->s.v.items; float firepower_ = 100.0f; int attackbonus = 0; self->fb.weapon_refresh_time = 1000000; if (deathmatch != 4) { firepower_ = 0; if (items_ & IT_ROCKET_LAUNCHER) { firepower_ = self->s.v.ammo_rockets * 8; if (self->s.v.ammo_rockets) { attackbonus = 50; } } else if (items_ & IT_GRENADE_LAUNCHER) { firepower_ = self->s.v.ammo_rockets * 6; if (firepower_ > 50) { firepower_ = 50; } } if (items_ & IT_LIGHTNING) { firepower_ = firepower_ + self->s.v.ammo_cells; if (self->s.v.ammo_cells >= 10) { attackbonus = attackbonus + 50; } } if (items_ & IT_EITHER_NAILGUN) { firepower_ = firepower_ + (self->s.v.ammo_nails * 0.1); } if (items_ & IT_SUPER_SHOTGUN) { if (self->s.v.ammo_shells >= 50) { firepower_ = firepower_ + 20; } else { firepower_ = firepower_ + self->s.v.ammo_shells * 0.4; } } else { if (self->s.v.ammo_shells >= 25) { firepower_ = firepower_ + 10; } else { firepower_ = firepower_ + self->s.v.ammo_shells * 0.4; } } firepower_ = min(firepower_, 100); self->fb.desire_rockets = max(5, 20 - self->s.v.ammo_rockets); self->fb.desire_cells = max(2.5, (50 - self->s.v.ammo_cells) * 0.2); self->fb.desire_rocketlauncher = max(100 - firepower_, self->fb.desire_rockets); self->fb.desire_lightning = max(self->fb.desire_rocketlauncher, self->fb.desire_cells); if (items_ & IT_ROCKET_LAUNCHER) { self->fb.desire_rockets = self->fb.desire_grenadelauncher = self->fb.desire_rocketlauncher; } else { self->fb.desire_grenadelauncher = 0; if (firepower_ < 50) { self->fb.desire_grenadelauncher = 50 - firepower_; } if (self->fb.desire_grenadelauncher < self->fb.desire_rockets) { self->fb.desire_grenadelauncher = self->fb.desire_rockets; } if (items_ & IT_GRENADE_LAUNCHER) { self->fb.desire_rockets = self->fb.desire_grenadelauncher; } } if (items_ & IT_LIGHTNING) { self->fb.desire_cells = self->fb.desire_lightning; } self->fb.desire_nails = self->fb.desire_shells = 0; if (firepower_ < 20) { self->fb.desire_nails = 2.5 - (self->s.v.ammo_nails * 0.0125); if (self->s.v.ammo_shells < 50) { self->fb.desire_shells = 2.5 - (self->s.v.ammo_shells * 0.05); } } self->fb.desire_supershotgun = max(0, 20 - firepower_); self->fb.desire_nailgun = self->fb.desire_supernailgun = max(self->fb.desire_supershotgun, self->fb.desire_nails); self->fb.desire_supershotgun = max(self->fb.desire_supershotgun, self->fb.desire_shells); if (items_ & IT_EITHER_NAILGUN) { self->fb.desire_nails = self->fb.desire_supernailgun; } if (items_ & IT_SUPER_SHOTGUN) { self->fb.desire_shells = self->fb.desire_supershotgun; } firepower_ = bound(0, firepower_ + attackbonus, 100); } if (self->super_damage_finished > g_globalvars.time) { firepower_ *= (deathmatch == 4 ? 8 : 4); } if (self->ctf_flag & CTF_RUNE_STR) { firepower_ *= (cvar("k_ctf_rune_power_str") / 2) + 1; } self->fb.firepower = firepower_; } void FrogbotWeaponFiredEvent(gedict_t *self) { self->fb.weapon_refresh_time = min(g_globalvars.time + 1, self->fb.weapon_refresh_time); } #endif QW-Group-ktx-d05d6ca/src/bot_botthink.c000066400000000000000000000257641475442401000200670ustar00rootroot00000000000000/* bot/botthink.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void AMPHI2BotInLava(void); // FIXME: Move to bot.skill #define CHANCE_EVADE_DUEL 0.08 #define CHANCE_EVADE_NONDUEL 0.1 void Bot_Print_Thinking(void); static void PeriodicAllClientLogic(void); void FrogbotEditorMarkerTouched(gedict_t *marker); static void SetNextThinkTime(gedict_t *ent) { if (!((int)ent->s.v.flags & FL_ONGROUND)) { ent->fb.frogbot_nextthink += 0.15 + (0.015 * g_random()); if (PAST(frogbot_nextthink)) { ent->fb.frogbot_nextthink = g_globalvars.time + 0.16; } } } static void AvoidLookObjectsMissile(gedict_t *self) { gedict_t *rocket; self->fb.missile_dodge = NULL; if (self->fb.look_object && (self->fb.look_object->ct == ctPlayer)) { for (rocket = world; (rocket = ez_find(rocket, "rocket"));) { if (rocket->s.v.owner == EDICT_TO_PROG(self->fb.look_object)) { self->fb.missile_dodge = rocket; break; } } } } static void LookingAtEnemyLogic(gedict_t *self) { if (Visible_360(self, self->fb.look_object)) { if (self->fb.look_object == &g_edicts[self->s.v.enemy]) { self->fb.enemy_dist = VectorDistance(self->fb.look_object->s.v.origin, self->s.v.origin); } else if (PAST(enemy_time)) { ClearLookObject(self); } } else { ClearLookObject(self); } } static void NewlyPickedEnemyLogic(void) { gedict_t *goalentity_ = &g_edicts[self->s.v.goalentity]; gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; if (self->s.v.goalentity == self->s.v.enemy) { if (Visible_360(self, goalentity_)) { LookEnemy(self, goalentity_); } else if (PAST(enemy_time)) { if (BotsPickBestEnemy(self)) { self->fb.goal_refresh_time = 0; } } } else { if (Visible_infront(self, enemy_)) { LookEnemy(self, enemy_); } else if (PAST(enemy_time)) { BotsPickBestEnemy(self); } } } static void TargetEnemyLogic(gedict_t *self) { self->fb.missile_dodge = NULL; if (!(self->fb.state & NOTARGET_ENEMY)) { if (self->fb.look_object && (self->fb.look_object->ct == ctPlayer)) { // Interesting - they only avoid missiles from players they are looking at? AvoidLookObjectsMissile(self); LookingAtEnemyLogic(self); } else if (self->s.v.enemy) { NewlyPickedEnemyLogic(); } else { BotsPickBestEnemy(self); } } } static void BotDodgeMovement(gedict_t *self, vec3_t dir_move, float dodge_factor) { if (dodge_factor) { if (dodge_factor < 0) { ++dodge_factor; } else { --dodge_factor; } trap_makevectors(self->s.v.v_angle); VectorMA(dir_move, g_random() * self->fb.skill.dodge_amount * dodge_factor, g_globalvars.v_right, dir_move); } } static void BotOnGroundMovement(gedict_t *self, vec3_t dir_move) { float dodge_factor = 0; if ((int)self->s.v.flags & FL_ONGROUND) { if (!(self->fb.path_state & NO_DODGE)) { // Dodge a rocket our enemy is firing at us if (self->fb.missile_dodge && ((g_globalvars.time - self->fb.missile_dodge->fb.missile_spawntime) >= self->fb.skill.missile_dodge_time)) { if (PROG_TO_EDICT(self->fb.missile_dodge->s.v.owner)->ct == ctPlayer) { vec3_t rel_pos; VectorSubtract(self->s.v.origin, self->fb.missile_dodge->s.v.origin, rel_pos); if (DotProduct(rel_pos, self->fb.missile_dodge->fb.missile_forward) > 0.7071067) { vec3_t temp; normalize(rel_pos, temp); dodge_factor = DotProduct(temp, self->fb.missile_dodge->fb.missile_right); } } else { self->fb.missile_dodge = NULL; } } // Not dodging a missile, dodge away from the player instead if (self->fb.look_object && (self->fb.look_object->ct == ctPlayer)) { if (!dodge_factor) { vec3_t rel_pos; VectorSubtract(self->s.v.origin, self->fb.look_object->s.v.origin, rel_pos); trap_makevectors(self->fb.look_object->s.v.v_angle); if (DotProduct(rel_pos, g_globalvars.v_forward) > 0) { vec3_t temp; normalize(rel_pos, temp); dodge_factor = DotProduct(temp, g_globalvars.v_right); } } } BotDodgeMovement(self, dir_move, dodge_factor); } } // If we're not in water, cannot have vertical direction (think of markers heading up stairs) if (self->s.v.waterlevel <= 1) { dir_move[2] = 0; } } static void BotMoveTowardsLinkedMarker(gedict_t *self, vec3_t dir_move) { vec3_t temp; gedict_t *goalentity_ = &g_edicts[self->s.v.goalentity]; gedict_t *linked = self->fb.linked_marker; qbool onGround = ((int)self->s.v.flags & FL_ONGROUND); qbool curlJump = ((int)self->fb.path_state & BOTPATH_CURLJUMP_HINT); VectorAdd(linked->s.v.absmin, linked->s.v.view_ofs, temp); VectorSubtract(temp, self->s.v.origin, temp); normalize(temp, dir_move); if (curlJump && (onGround || (self->s.v.velocity[2] > 0))) { vec3_t up = { 0, 0, 1 }; if (self->isBot && self->fb.debug_path) { G_bprint(PRINT_HIGH, "%3.2f: Moving %3d > %3d, dir %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.touch_marker->fb.index + 1, self->fb.linked_marker->fb.index + 1, PASSVEC3(dir_move)); } RotatePointAroundVector(dir_move, up, dir_move, self->fb.angle_hint); if (self->isBot && self->fb.debug_path) { G_bprint(PRINT_HIGH, "%3.2f: Rotating %d, %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.angle_hint, PASSVEC3(dir_move)); } } if (self->isBot && self->fb.debug_path) { //G_bprint (PRINT_HIGH, "%3.2f: Moving %3d > %3d, dir %3.1f %3.1f %3.1f\n", g_globalvars.time, self->fb.touch_marker->fb.index + 1, self->fb.linked_marker->fb.index + 1, PASSVEC3 (dir_move)); } if (self->fb.path_state & DELIBERATE_BACKUP) { if (linked->fb.arrow_time > g_globalvars.time) { VectorInverse(dir_move); } else { self->fb.path_state &= ~DELIBERATE_BACKUP; } } else if (linked == self->fb.touch_marker) { if (goalentity_ == self->fb.touch_marker) { if (WaitingToRespawn(self->fb.touch_marker)) { VectorClear(dir_move); } } else { VectorClear(dir_move); } } } // Called when the bot has a touch marker set static void BotTouchMarkerLogic(void) { TargetEnemyLogic(self); if (PAST(goal_refresh_time)) { UpdateGoal(self); } if (self->fb.path_state & BOTPATH_RJ_IN_PROGRESS) { if (self->s.v.velocity[2] <= 0) { self->fb.path_state &= ~BOTPATH_RJ_IN_PROGRESS; } } if (!(self->fb.path_state & BOTPATH_RJ_IN_PROGRESS)) { if (PAST(linked_marker_time)) { self->fb.old_linked_marker = NULL; } if (self->fb.old_linked_marker != self->fb.touch_marker) { ProcessNewLinkedMarker(self); } } if (FUTURE(arrow_time)) { if (self->isBot && self->fb.debug_path) { G_bprint(PRINT_HIGH, "%3.2f: arrow_time is %3.2f\n", g_globalvars.time, self->fb.arrow_time); } if (FUTURE(arrow_time2)) { if (g_random() < 0.5) { SetLinkedMarker(self, self->fb.touch_marker, "BotTouchMarkerLogic"); self->fb.old_linked_marker = self->fb.linked_marker; self->fb.path_state = 0; self->fb.linked_marker_time = g_globalvars.time + 0.3; } } } else if (self->fb.linked_marker) { vec3_t dir_move; BotMoveTowardsLinkedMarker(self, dir_move); BotOnGroundMovement(self, dir_move); SetDirectionMove(self, dir_move, ((int)self->s.v.flags & FL_ONGROUND) ? "OnGround" : "InAir"); } else { // The map is, imo, broken at this point, but some old fbca maps are missing links // and at this point would use 'world' // Deliberately don't move and hope that the fall gets us somewhere vec3_t dir_move = { 0, 0, 0 }; SetDirectionMove(self, dir_move, "NoLinkedMarker!"); } SelectWeapon(); } // Called when a human player touches a marker static void HumanTouchMarkerLogic(void) { if (PAST(enemy_time)) { BotsPickBestEnemy(self); } if (FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { FrogbotEditorMarkerTouched(self->fb.touch_marker); } } void BotPathCheck(gedict_t *self, gedict_t *touch_marker) { if (self->fb.debug_path && (self->fb.fixed_goal == touch_marker)) { G_bprint(2, "at goal, path complete. %4.3f seconds\n", g_globalvars.time - self->fb.debug_path_start); self->fb.fixed_goal = NULL; self->fb.debug_path = false; self->fb.debug_path_start = 0; cvar_fset(FB_CVAR_DEBUG, 0); } } static void PeriodicAllClientLogic(void) { SetNextThinkTime(self); self->fb.prev_touch_marker = self->fb.touch_marker; if (PAST(weapon_refresh_time)) { FrogbotSetFirepower(self); } // If we haven't touched a marker in a while, find closest marker if (PAST(touch_marker_time)) { SetMarker(self, LocateMarker(self->s.v.origin)); } if (self->fb.touch_marker) { BotPathCheck(self, self->fb.touch_marker); if (self->fb.state & AWARE_SURROUNDINGS) { if (self->isBot) { BotTouchMarkerLogic(); } else { HumanTouchMarkerLogic(); } } else { self->fb.goal_refresh_time = 0; self->fb.state |= AWARE_SURROUNDINGS; self->fb.old_linked_marker = (self->isBot ? NULL : self->fb.old_linked_marker); } } } void BotEvadeLogic(gedict_t *self) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; self->fb.bot_evade = false; if (deathmatch <= 3 && !isRA()) { if (isDuel() && g_random() < CHANCE_EVADE_DUEL) { if ((self->s.v.origin[2] + 18) > (enemy_->s.v.absmin[2] + enemy_->s.v.view_ofs[2])) { if (((int)self->s.v.items & IT_ROCKET_LAUNCHER) && (self->s.v.ammo_rockets > 4)) { if (!self->s.v.waterlevel) { self->fb.bot_evade = (qbool)(self->s.v.health > 70) && (self->s.v.armorvalue > 100) && !self->fb.enemy_visible; } } } } else if (!isDuel() && g_random() < CHANCE_EVADE_NONDUEL) { if ((self->s.v.origin[2] + 18) > (enemy_->s.v.absmin[2] + enemy_->s.v.view_ofs[2])) { if (((int)self->s.v.items & IT_ROCKET_LAUNCHER) || ((int)self->s.v.items & IT_LIGHTNING)) { if ((self->s.v.ammo_cells >= 20) || (self->s.v.ammo_rockets > 3)) { if (!self->s.v.waterlevel) { if ((self->s.v.health > 70) && (self->s.v.armorvalue > 90)) { self->fb.bot_evade = (qbool)(!((int)self->s.v.items & (IT_INVULNERABILITY | IT_INVISIBILITY | IT_QUAD))); } } } } } } } } // Logic that gets called for every player void BotsThinkTime(gedict_t *self) { self->fb.jumping = false; // Don't call SetJumpFlag here if (self->fb.prev_touch_marker != self->fb.touch_marker || PAST(frogbot_nextthink)) { PeriodicAllClientLogic(); if (self->isBot) { CheckCombatJump(self); AMPHI2BotInLava(); } } if (self->isBot && FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT)) { stuffcmd_flags(self, STUFFCMD_DEMOONLY, "//botcmd %f %d %d %d | %d %d %d\n", g_globalvars.time, PASSINTVEC3(self->s.v.v_angle), PASSINTVEC3(self->fb.predict_origin)); } } // Sets a client's last marker void SetMarker(gedict_t *client, gedict_t *marker) { client->fb.touch_distance = 0; client->fb.touch_marker = marker; client->fb.Z_ = marker ? marker->fb.Z_ : 0; client->fb.touch_marker_time = g_globalvars.time + 5; } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_botwater.c000066400000000000000000000112151475442401000200560ustar00rootroot00000000000000/* bot/botwater.qc Copyright (C) 1999-2000 Numb */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" #define BOT_DROWN_SAFETY_TIME 2 // Time before air running out that the bot starts searching for air static qbool BotCanReachMarker(gedict_t *self) { vec3_t spot1, spot2; VectorCopy(self->fb.linked_marker->s.v.origin, spot2); VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); traceline(spot1[0], spot1[1], spot1[2], spot2[0], spot2[1], spot2[2], true, self); return (g_globalvars.trace_fraction == 1); } static qbool BotSwimDown(gedict_t *self) { return (self->fb.linked_marker->s.v.origin[2] < self->s.v.origin[2]); } static qbool BotSwimUp(gedict_t *self) { return (self->fb.linked_marker->s.v.origin[2] >= self->s.v.origin[2]); } static qbool BotGoUpForAir(gedict_t *self, vec3_t dir_move) { vec3_t temp; if (g_globalvars.time > (self->air_finished - BOT_DROWN_SAFETY_TIME)) { vec3_t new_velocity; traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 64, true, self); if (g_globalvars.trace_fraction == 1) { return (self->fb.swim_arrow = UP); } VectorCopy(self->s.v.velocity, new_velocity); VectorNormalize(dir_move); VectorCopy(new_velocity, temp); VectorNormalize(temp); VectorAdd(dir_move, temp, dir_move); dir_move[2] = 0; NewVelocityForArrow(self, dir_move, "UpForAir"); // Drowning... if (g_globalvars.time > self->air_finished) { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 32, true, self); if (g_globalvars.trace_fraction != 1) { return (self->fb.swim_arrow = UP); } } } return false; } static void SwimAwayFromWall(gedict_t *self, vec3_t dir_move) { if (DotProduct(self->fb.obstruction_normal, self->fb.obstruction_direction) > 0.5) { VectorScale(dir_move, -1, dir_move); } traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0] + g_globalvars.v_right[0] * 20, self->s.v.origin[1] + g_globalvars.v_right[1] * 20, self->s.v.origin[2] + g_globalvars.v_right[2] * 20, true, self); if (g_globalvars.trace_fraction != 1) { vec3_t temp; VectorNormalize(dir_move); VectorScale(g_globalvars.v_right, g_random() * -32, temp); VectorAdd(temp, dir_move, temp); normalize(temp, dir_move); } traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0] + g_globalvars.v_right[0] * (-20), self->s.v.origin[1] + g_globalvars.v_right[1] * (-20), self->s.v.origin[2] + g_globalvars.v_right[2] * (-20), true, self); if (g_globalvars.trace_fraction != 1) { vec3_t temp; VectorNormalize(dir_move); VectorScale(g_globalvars.v_right, g_random() * 32, temp); VectorAdd(temp, dir_move, temp); normalize(temp, dir_move); } NewVelocityForArrow(self, dir_move, "SwimAway"); } void BotWaterMove(gedict_t *self) { vec3_t dir_move; //if ((self->s.v.watertype == CONTENT_LAVA || self->s.v.watertype == CONTENT_SLIME) && escape_marker_count > 0) { //} self->fb.swim_arrow = 0; if ((self->s.v.waterlevel <= 2) || FUTURE(frogwatermove_time)) { return; } VectorCopy(self->fb.dir_move_, dir_move); self->fb.frogwatermove_time = self->fb.frogbot_nextthink + 0.1; if (self->fb.obstruction_normal[0] || self->fb.obstruction_normal[1] || self->fb.obstruction_normal[2]) { SwimAwayFromWall(self, dir_move); } if (BotGoUpForAir(self, dir_move)) { return; } if (BotCanReachMarker(self)) { if (BotSwimDown(self)) { self->fb.swim_arrow = DOWN; } else if (BotSwimUp(self)) { self->fb.swim_arrow = UP; } } else { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 32, true, self); if (g_globalvars.trace_fraction == 1) { self->fb.swim_arrow = UP; } else { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + -32, true, self); if (g_globalvars.trace_fraction == 1) { self->fb.swim_arrow = DOWN; } else { self->fb.swim_arrow = UP; } } } } // client.qc void BotWaterJumpFix(void) { if (self->isBot) { ++self->fb.tread_water_count; if (self->fb.tread_water_count > 60) { self->fb.tread_water_count = 0; self->fb.old_linked_marker = NULL; SetLinkedMarker(self, LocateMarker(self->s.v.origin), "BotWaterJumpFix"); self->fb.path_state = 0; self->fb.linked_marker_time = g_globalvars.time + 5; } } } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_botweap.c000066400000000000000000000507401475442401000176760ustar00rootroot00000000000000/* bot/botweap.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2001 DMSouL Copyright (C) 2003 3d[Power] Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // FIXME: globals, this is just setting void DM6SelectWeaponToOpenDoor(gedict_t *self); // FIXME: This is just stopping quad damage rocket shot, always replacing with shotgun // Can do far better than this static qbool TP_CouldDamageTeammate(gedict_t *self) { if ((int)self->s.v.items & IT_QUAD) { if ((teamplay != 1) && (teamplay != 5)) { gedict_t *search_entity = IdentifyMostVisibleTeammate(self); if (!search_entity->invincible_time) { if (VisibleEntity(search_entity)) { if (self->fb.enemy_visible) { if (VectorDistance(search_entity->s.v.origin, g_edicts[self->s.v.enemy].s.v.origin) < 150) { return (self->s.v.ammo_shells > 0); } } } } } } return false; } static qbool WaterCombat(gedict_t *self) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; if (self->s.v.waterlevel < 2) { return true; } return ((trap_pointcontents(enemy_->s.v.origin[0], enemy_->s.v.origin[1], enemy_->s.v.origin[2]) == CONTENT_WATER) && (enemy_->s.v.origin[2] < self->s.v.origin[2] - 32)); } static qbool RocketSafe(void) { float splash_damage = 80 - (0.25 * self->fb.enemy_dist); if ((teamplay == 1) || (teamplay == 5) || cvar("k_midair") || (splash_damage <= 0)) { return true; } if (self->super_damage_finished > g_globalvars.time) { splash_damage = splash_damage * (deathmatch != 4 ? 4 : 8); if (self->ctf_flag & ITEM_RUNE_MASK) { if (self->ctf_flag & CTF_RUNE_STR) { splash_damage = splash_damage * (cvar("k_ctf_rune_power_str") / 2) + 1; } else if (self->ctf_flag & CTF_RUNE_RES) { splash_damage = splash_damage / (cvar("k_ctf_rune_power_res") / 2) + 1; } } } return (self->fb.total_damage > splash_damage); } qbool CheckNewWeapon(int desired_weapon) { int weapons[] = { IT_AXE, IT_SHOTGUN, IT_SUPER_SHOTGUN, IT_NAILGUN, IT_SUPER_NAILGUN, IT_GRENADE_LAUNCHER, IT_ROCKET_LAUNCHER, IT_LIGHTNING }; if ((self->s.v.weapon != desired_weapon) || !BotUsingCorrectWeapon(self)) { int i = 0; for (i = 0; i < sizeof(weapons) / sizeof(weapons[0]); ++i) { if (weapons[i] == desired_weapon) { self->fb.desired_weapon_impulse = i + 1; return true; } } return false; } return true; } static qbool ShotForLuck(vec3_t object) { trap_makevectors(self->s.v.v_angle); traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2], object[0], object[1], object[2], true, self); return (g_globalvars.trace_fraction == 1); } static void SetFireButtonBasedOnAngles(gedict_t *self, float rel_dist) { float risk_factor = 0.5; float risk = g_random(); float min_angle_error; vec3_t angle_error; int i; risk *= risk; VectorSubtract(self->fb.desired_angle, self->s.v.v_angle, angle_error); for (i = 0; i < 2; ++i) { if (angle_error[i] >= 180) { angle_error[i] -= 360; } else if (angle_error[i] < -180) { angle_error[i] += 360; } angle_error[i] = fabs(angle_error[i]); } min_angle_error = (1 + risk) * risk_factor * (self->fb.skill.accuracy + (1440 / rel_dist)); // Frogbots take into account the distance they've had to snap to look at the player, and won't fire if distance is too high, compared to skill.accuracy self->fb.firing |= (angle_error[0] <= min_angle_error && angle_error[1] <= min_angle_error); } // FIXME: should just be avoiding bore anyway? // FIXME: take strength of player & enemy into account, player might survive quad splashdamage, to enemy weapon static void AvoidQuadBore(gedict_t *self) { qbool has_quad = (int)self->s.v.items & IT_QUAD; qbool has_pent = (int)self->s.v.items & IT_INVULNERABILITY; qbool could_explode = self->fb.desired_weapon_impulse == 7 || self->fb.desired_weapon_impulse == 6; qbool could_hurt_self = could_explode && !has_pent && teamplay != 1 && teamplay != 5; if (cvar("k_midair") || !has_quad || !could_hurt_self) { return; } if ((self->fb.look_object == &g_edicts[self->s.v.enemy]) && (self->fb.enemy_dist <= 250)) { // Enemy is too close for explosion, fire something else instead. int items_ = (int)self->s.v.items; int desired_weapon = IT_AXE; if ((items_ & IT_LIGHTNING) && (self->s.v.ammo_cells)) { desired_weapon = IT_LIGHTNING; } else if ((items_ & IT_SUPER_NAILGUN) && (self->s.v.ammo_nails)) { desired_weapon = IT_SUPER_NAILGUN; } else if ((items_ & IT_NAILGUN) && (self->s.v.ammo_nails)) { desired_weapon = IT_NAILGUN; } else if ((items_ & IT_SUPER_SHOTGUN) && (self->s.v.ammo_shells)) { desired_weapon = IT_SUPER_SHOTGUN; } else if (self->s.v.ammo_shells) { desired_weapon = IT_SHOTGUN; } self->fb.firing |= CheckNewWeapon(desired_weapon); } } // FIXME: This doesn't do what it says, as it has teamplay-value checks static qbool CouldHurtTeammate(gedict_t *me) { float ang, curang; gedict_t *p; if (teamplay == 0 || teamplay == 1 || teamplay == 5) { return false; } for (p = world; (p = find_plr(p));) { if (p != me) { if (SameTeam(me, p)) { if (VisibleEntity(p)) { vec3_t diff; VectorSubtract(p->s.v.origin, me->s.v.origin, diff); curang = vectoyaw(diff); ang = anglemod(me->s.v.angles[1] - curang); // FIXME: fb.skill if (ang < 20 || ang > 340) { return true; } } } } } return false; } // FIXME: Interesting... if a marker is the look object then it wouldn't explode on that? static void SpamRocketShot(gedict_t *self) { qbool has_rl = ((int)self->s.v.items & IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets > 3; qbool safe_to_fire = self->fb.allowedMakeNoise && !CouldHurtTeammate(self); if (self->fb.rocketJumping) { return; } if (!has_rl || !safe_to_fire) { return; } if (self->fb.look_object) { // dist_sfl = threshold distance before attempting shot for luck float dist_sfl = cvar("k_midair") ? 0 : ((int)self->s.v.items & IT_QUAD) ? 300.0f : 250.0f; vec3_t testplace; vec3_t rel_pos; float rel_dist; // rel_dist = distance between player and the item they're about to fire at VectorAdd(self->fb.look_object->s.v.absmin, self->fb.look_object->s.v.view_ofs, testplace); VectorSubtract(testplace, self->s.v.origin, rel_pos); rel_dist = vlen(rel_pos); if (rel_dist > dist_sfl && ShotForLuck(testplace)) { // FIXME: This uses distance to enemy, not to testplace (?) if (RocketSafe()) { // FIXME: Aim lower? This looks like copy & paste from BotsFireLogic() // Why self->origin + rel_pos when rel_pos = testplace - origin, why not just testplace? (or did RocketSafe() just overwrite?) traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 16, self->s.v.origin[0] + rel_pos[0], self->s.v.origin[1] + rel_pos[1], self->s.v.origin[2] + rel_pos[2] - 22, true, self); if (g_globalvars.trace_fraction == 1) { rel_pos[2] -= 38; } self->fb.state |= SHOT_FOR_LUCK; self->fb.desired_weapon_impulse = 7; self->fb.firing = true; } else { self->fb.state &= ~SHOT_FOR_LUCK; } } } } void FindRocketExplosionPoint(vec3_t player_origin, vec3_t player_angles, vec3_t output, float *distance_frac) { vec3_t rocket_origin; vec3_t final_point; VectorCopy(player_origin, rocket_origin); rocket_origin[2] += 16; trap_makevectors(player_angles); VectorMA(rocket_origin, 600, g_globalvars.v_forward, final_point); traceline(PASSVEC3(rocket_origin), PASSVEC3(final_point), false, self); VectorCopy(g_globalvars.trace_endpos, output); *distance_frac = g_globalvars.trace_fraction; } // FIXME: Predicts aim*600, then predicts if the enemy's predicted position will be close to the explosion point... static void RocketLauncherShot(gedict_t *self) { float hit_radius = 160; float risk_strength; gedict_t *test_enemy; float risk_factor = 0.5; float risk = g_random(); risk *= risk; FindRocketExplosionPoint(self->s.v.origin, self->fb.desired_angle, self->fb.rocket_endpos, &risk_strength); for (test_enemy = world; (test_enemy = find_plr(test_enemy));) { float predict_dist = 1000000; vec3_t testplace; // Ignore corpses if (!test_enemy->s.v.takedamage) { continue; } if (test_enemy == &g_edicts[self->s.v.enemy]) { if (self->fb.look_object && (self->fb.look_object->ct == ctPlayer)) { if (self->fb.look_object == &g_edicts[self->s.v.enemy]) { VectorCopy(self->fb.predict_origin, testplace); predict_dist = VectorDistance(testplace, self->fb.rocket_endpos); } } else if (self->fb.look_object && (self->fb.look_object != world)) { if (self->fb.allowedMakeNoise && self->fb.predict_shoot) { VectorAdd(self->fb.look_object->s.v.absmin, self->fb.look_object->s.v.view_ofs, testplace); from_marker = g_edicts[self->s.v.enemy].fb.touch_marker; path_normal = true; ZoneMarker(from_marker, self->fb.look_object, path_normal, g_edicts[self->s.v.enemy].fb.canRocketJump); traveltime = SubZoneArrivalTime(zone_time, middle_marker, self->fb.look_object, g_edicts[self->s.v.enemy].fb.canRocketJump); predict_dist = (traveltime * sv_maxspeed) + VectorDistance(testplace, self->fb.rocket_endpos); } } } else { VectorCopy(test_enemy->s.v.origin, testplace); predict_dist = VectorDistance(testplace, self->fb.rocket_endpos); } if (predict_dist <= (hit_radius / (1 - risk))) { // See if the explosion would hurt that player traceline(PASSVEC3(self->fb.rocket_endpos), PASSVEC3(testplace), true, self); if (g_globalvars.trace_fraction == 1) { // Nothing blocking the explosion... if (!SameTeam(test_enemy, self)) { // Enemy risk_factor /= risk_strength; if (self->fb.look_object == &g_edicts[self->s.v.enemy]) { self->fb.firing = true; } else if (predict_dist <= (80 / (1.2 - risk))) { self->fb.firing = true; } else { SpamRocketShot(self); if ((int)self->s.v.items & IT_GRENADE_LAUNCHER) { if (self->fb.arrow == BACK) { if (self->s.v.enemy && !self->fb.rocketJumping) { if (self->fb.allowedMakeNoise && (self->s.v.ammo_rockets > 3) && !CouldHurtTeammate(self)) { self->fb.desired_weapon_impulse = 6; self->fb.firing = true; } } } } } } else { if (test_enemy != self) { return; } else { risk_factor = risk_factor * risk_strength; } } } } } } // If bot can jump and can attack player from higher position, will jump static void JumpToAttack(vec3_t rel_pos) { if (self->fb.look_object == &g_edicts[self->s.v.enemy]) { if ((self->s.v.waterlevel == 0) && self->fb.allowedMakeNoise && ((int)self->s.v.flags & FL_ONGROUND)) { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 32, self->s.v.origin[0] + rel_pos[0], self->s.v.origin[1] + rel_pos[1], self->s.v.origin[2] + rel_pos[2] + 32, false, self); SetJumpFlag(self, (g_globalvars.trace_fraction == 1), "JumpToAttack"); } } } static qbool PreWarBlockFiring(gedict_t *self) { // Only fire in pre-war if enemy attacked us if (match_in_progress == 0) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; qbool enemy_is_world = self->s.v.enemy && enemy->ct == ctNone; qbool looking_at_enemy = enemy == self->fb.look_object; qbool enemy_attacked = self->s.v.enemy && g_globalvars.time < enemy->attack_finished + 0.5; qbool debugging_door = (self->fb.debug_path && enemy_is_world); // Don't fire at other bots if ((self->s.v.enemy == 0) || enemy->isBot || !self->fb.look_object) { self->fb.firing = false; return true; } // If looking at enemy and they haven't attacked us recently, don't fire // Exception for debug_path, when it can fire at doors (but not players) if (looking_at_enemy && !(enemy_attacked || debugging_door)) { self->fb.firing = false; return true; } } // Countdown, never fire if (match_in_progress == 1) { self->fb.firing = false; return true; } return false; } qbool AttackFinished(gedict_t *self) { if (g_globalvars.time < self->attack_finished) { if ((int)self->s.v.weapon & (IT_LIGHTNING | IT_EITHER_NAILGUN)) { return (g_globalvars.time < self->s.v.nextthink); } return true; } return false; } static qbool KeepFiringAtEnemy(gedict_t *self) { // Keep fire button down if tracking enemy return ((self->fb.look_object == &g_edicts[self->s.v.enemy]) && (g_random() < 0.666667f) && BotUsingCorrectWeapon(self)); } static qbool MidairAimLogic(gedict_t *self, float rel_dist) { // In midair mode, delay firing until the rocket will hit opponent near peak of their jump if (cvar( "k_midair") && self->fb.look_object && (self->fb.look_object->s.v.velocity[2] > JUMPSPEED)) { float time_to_hit = rel_dist / (self->super_damage_finished > g_globalvars.time ? 2000 : 1000); float time_to_stationary = self->fb.look_object->s.v.velocity[2] / 800; if (time_to_stationary - time_to_hit > 0.15f) { self->fb.firing = false; return true; } } return false; } static qbool HurtSelfLogic(gedict_t *self) { // If we want to grab an armour to stop player getting it... if (self->fb.state & HURT_SELF) { if (HasWeapon(self, IT_ROCKET_LAUNCHER) && (self->fb.desired_angle[PITCH] > 75)) { self->fb.desired_weapon_impulse = 7; self->fb.firing = true; self->fb.state &= ~HURT_SELF; } return true; } return false; } void SetFireButton(gedict_t *self, vec3_t rel_pos, float rel_dist) { if (PreWarBlockFiring(self)) { return; } if ((self->fb.enemy_dist > 600) && lgc_enabled()) { self->fb.firing = false; return; } if (self->fb.firing) { if (KeepFiringAtEnemy(self)) { return; } if (!AttackFinished(self)) { return; } self->fb.firing &= self->fb.rocketJumping && self->fb.rocketJumpFrameDelay == 0; } else if (self->fb.next_impulse) { return; } if (FUTURE(min_fire_time)) { self->fb.firing = false; return; } if (MidairAimLogic(self, rel_dist)) { return; } if (SameTeam(self->fb.look_object, self)) { self->fb.firing = false; return; } DM6SelectWeaponToOpenDoor(self); if (HurtSelfLogic(self)) { return; } if (self->s.v.enemy && g_edicts[self->s.v.enemy].fb.touch_marker) { traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 16, self->s.v.origin[0] + rel_pos[0], self->s.v.origin[1] + rel_pos[1], self->s.v.origin[2] + rel_pos[2] + 16, false, self); if (g_globalvars.trace_fraction == 1) { // FIXME: This keeps accuracy too high, stops the first shot from missing? !!!! FIXME FIXME FIXME // i.e. could be using rocket launcher for 'shot-for-luck', or using other weapon to hit world if (!((self->fb.desired_weapon_impulse == 7) || (NUM_FOR_EDICT(self->fb.look_object) == self->s.v.enemy))) { // don't needlessly fire into space return; } } else if (PROG_TO_EDICT(g_globalvars.trace_ent) != self->fb.look_object) { gedict_t *traced = PROG_TO_EDICT(g_globalvars.trace_ent); if (traced->ct == ctPlayer) { if (!SameTeam(traced, self)) { if (!((int)self->s.v.flags & FL_WATERJUMP)) { self->s.v.enemy = NUM_FOR_EDICT(traced); LookEnemy(self, traced); } } return; } else { JumpToAttack(rel_pos); return; } } // At this point, bot is looking at enemy // FIXME: This is broken, we should use other weapon in water and override with discharge if necessary if ((self->fb.desired_weapon_impulse == 8) && (self->s.v.waterlevel > 1)) { return; } { AvoidQuadBore(self); if (self->fb.desired_weapon_impulse == 7) { RocketLauncherShot(self); } else { SetFireButtonBasedOnAngles(self, rel_dist); } } } } // FIXME: should still discharge if < 25 cells and would kill enemy... static qbool BotShouldDischarge(void) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; if (self->s.v.waterlevel != 3) { return false; } if (!((int)self->s.v.items & IT_LIGHTNING)) { return false; } if (self->s.v.ammo_cells < 25) { return false; } if (self->fb.enemy_dist > 600) { return false; } if (self->fb.look_object != enemy) { return false; } if (self->invincible_time > g_globalvars.time) { if (trap_pointcontents(PASSVEC3(enemy->s.v.origin)) == CONTENT_WATER) { return true; } } if (((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) && (self->s.v.ammo_rockets > 25) && (self->s.v.ammo_cells > 25)) { return false; } if (((int)self->s.v.items & IT_NAILGUN_ROCKET) && (self->s.v.ammo_rockets > 25) && (self->s.v.ammo_nails > 25)) { return false; } if ((self->tp.enemy_count - self->tp.teammate_count) >= 2) { return (g_random() < 0.003); } return false; } static int DesiredWeapon(void) { int items_ = self->s.v.items; qbool has_rl = self->s.v.ammo_rockets && (items_ & IT_ROCKET_LAUNCHER); qbool has_lg = self->s.v.ammo_cells && (items_ & IT_LIGHTNING); qbool shaft_available = false; qbool avoid_rockets = false; qbool firing_lg = self->fb.firing && self->s.v.weapon == IT_LIGHTNING && self->s.v.ammo_cells && g_globalvars.time < self->attack_finished; if (TP_CouldDamageTeammate(self)) { return IT_SHOTGUN; } // When to always use RL if ((self->fb.skill.rl_preference >= g_random()) || fb_lg_disabled()) { if (has_rl) { if (RocketSafe()) { return IT_ROCKET_LAUNCHER; } avoid_rockets = true; } } // If firing LG then keep going, else look at LG_pref to switch to it if ((firing_lg || (self->fb.skill.lg_preference >= g_random())) && !fb_lg_disabled()) { if ((self->s.v.waterlevel <= 1) || ((int)self->s.v.items & IT_INVULNERABILITY)) { if (has_lg) { if (self->fb.enemy_dist <= 600) { return IT_LIGHTNING; } shaft_available = true; } } } if (BotShouldDischarge()) { return IT_LIGHTNING; } if (!fb_lg_disabled()) { if ((self->s.v.waterlevel <= 1) || ((int)self->s.v.items & IT_INVULNERABILITY)) { if (items_ & IT_LIGHTNING) { if (self->s.v.ammo_cells) { if (self->fb.enemy_dist <= 600) { if (self->fb.look_object == &g_edicts[self->s.v.enemy]) { vec3_t diff, enemy_angles; VectorSubtract(self->fb.look_object->s.v.origin, self->s.v.origin, diff); vectoangles(diff, enemy_angles); if (enemy_angles[0] < 15) { if (enemy_angles[0] > -15) { return IT_LIGHTNING; } } } else { return IT_LIGHTNING; } shaft_available = true; } } } } } if (!avoid_rockets) { if (items_ & IT_ROCKET_LAUNCHER) { if (self->s.v.ammo_rockets) { if (RocketSafe()) { return IT_ROCKET_LAUNCHER; } if (!((int)self->s.v.items & IT_INVULNERABILITY)) { avoid_rockets = true; } } } } if (self->fb.state & WAIT) { if (items_ & IT_ROCKET_LAUNCHER) { if (self->s.v.ammo_rockets) { if (RocketSafe()) { return IT_ROCKET_LAUNCHER; } } } else if (items_ & IT_LIGHTNING) { if (self->s.v.ammo_cells) { if (shaft_available) { return IT_LIGHTNING; } } } } if (shaft_available) { return IT_LIGHTNING; } if (self->fb.enemy_dist <= 320) { if (!avoid_rockets) { if (items_ & IT_GRENADE_LAUNCHER) { if (self->s.v.ammo_rockets) { if (RocketSafe()) { if (WaterCombat(self)) { return IT_GRENADE_LAUNCHER; } } } } } } if (self->fb.enemy_dist <= 600) { if (items_ & IT_SUPER_NAILGUN) { if (self->s.v.ammo_nails) { return IT_SUPER_NAILGUN; } } if (items_ & IT_SUPER_SHOTGUN) { if (self->s.v.ammo_shells) { return IT_SUPER_SHOTGUN; } } if (items_ & IT_NAILGUN) { if (self->s.v.ammo_nails) { return IT_NAILGUN; } } } if (self->s.v.ammo_shells) { return IT_SHOTGUN; } return IT_AXE; } void SelectWeapon(void) { if (self->fb.path_state & DM6_DOOR) { return; } if (self->fb.state & HURT_SELF) { qbool has_rl = self->s.v.ammo_rockets && ((int)self->s.v.items & IT_ROCKET_LAUNCHER); if (has_rl && (self->s.v.health >= 60) && (self->super_damage_finished <= g_globalvars.time)) { self->fb.desired_weapon_impulse = 7; return; } self->fb.state &= ~HURT_SELF; } CheckNewWeapon(DesiredWeapon()); if (tot_mode_enabled()) { self->fb.desired_weapon_impulse = FrogbotWeapon(); } } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_client.c000066400000000000000000000226751475442401000175210ustar00rootroot00000000000000/* client.qc client functions Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 07/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" #define PERIODIC_MM2_STATUS 4 void PlayerReady(qbool startIdlebot); void BotBlocked(void); int weapon_impulse_codes[] = { 0, IT_AXE, IT_SHOTGUN, IT_SUPER_SHOTGUN, IT_NAILGUN, IT_SUPER_NAILGUN, IT_GRENADE_LAUNCHER, IT_ROCKET_LAUNCHER, IT_LIGHTNING }; void TeamplayReportVisiblePowerups(gedict_t *self) { byte visible[MAX_CLIENTS]; gedict_t *opponent; if (FUTURE(last_mm2_spot_attempt)) return; self->fb.last_mm2_spot_attempt = g_globalvars.time + 0.5 + g_random() * 0.2; // Don't burn CPU with frequent visible_to() calls. visible_to(self, g_edicts + 1, MAX_CLIENTS, visible); for (opponent = g_edicts + 1; opponent <= g_edicts + MAX_CLIENTS; opponent++) { qbool diff_team = opponent->k_teamnum != self->k_teamnum; qbool powerups = (int)opponent->s.v.items & (IT_QUAD | IT_INVULNERABILITY); if (diff_team && powerups && opponent->ct == ctPlayer && visible[opponent - (g_edicts + 1)] && (opponent->fb.last_mm2_spot < g_globalvars.time)) { if (VisibleEntity(opponent)) { TeamplayMessageByName(self, "enemypwr"); opponent->fb.last_mm2_spot = g_globalvars.time + 2; break; } } } } static void ResetEnemy(gedict_t *self) { gedict_t *test_enemy = NULL; // Find all players who consider the current player their enemy, and clear it for (test_enemy = world; (test_enemy = find_plr(test_enemy));) { if (test_enemy->s.v.enemy == NUM_FOR_EDICT(self)) { test_enemy->s.v.enemy = NUM_FOR_EDICT(world); // Clear look object as well if (test_enemy->fb.look_object && (test_enemy->fb.look_object->ct == ctPlayer)) { ClearLookObject(test_enemy); test_enemy->fb.look_object = NULL; } // Clear goal entity (if we were hunting them down) if (test_enemy->s.v.goalentity == NUM_FOR_EDICT(self)) { test_enemy->fb.goal_refresh_time = 0; } } if (test_enemy->fb.prev_look_object == self) { test_enemy->fb.prev_look_object = NULL; } } self->s.v.enemy = NUM_FOR_EDICT(world); } void ResetGoalEntity(gedict_t *self) { if (self->s.v.goalentity) { gedict_t *ent = &g_edicts[self->s.v.goalentity]; ent->fb.teamflag &= ~self->fb.teamflag; self->s.v.goalentity = NUM_FOR_EDICT(world); } } void BotPlayerKilledEvent(gedict_t *targ, gedict_t *attacker, gedict_t *inflictor) { if ((inflictor && inflictor->ct != ctPlayer) && (inflictor->fb.T & UNREACHABLE)) { targ->fb.state |= BACKPACK_IS_UNREACHABLE; } } // Called whenever a player dies void BotPlayerDeathEvent(gedict_t *self) { ResetGoalEntity(self); ResetEnemy(self); if (self->isBot && teamplay) { qbool dropped_weapon = self->s.v.weapon == IT_ROCKET_LAUNCHER || self->s.v.weapon == IT_LIGHTNING; qbool no_teammates = self->tp.teammate_count == 0 || self->tp.enemy_count > self->tp.teammate_count; if (dropped_weapon || no_teammates) { TeamplayMessageByName(self, "lost"); } } self->fb.last_death = g_globalvars.time; self->fb.prev_look_object = NULL; } // Was: PutClientInServer_apply() void BotClientEntersEvent(gedict_t *self, gedict_t *spawn_pos) { self->fb.oldwaterlevel = self->fb.oldwatertype = 0; self->fb.desired_angle[0] = self->s.v.angles[0]; self->fb.desired_angle[1] = self->s.v.angles[1]; self->fb.state = 0; self->fb.min_fire_time = g_globalvars.time + self->fb.skill.awareness_delay; self->fb.min_move_time = g_globalvars.time + self->fb.skill.spawn_move_delay; self->fb.last_rndaim_time = 0; self->fb.wiggle_run_dir = 0; SetMarker(self, spawn_pos); self->fb.arrow = 0; ClearLookObject(self); VectorSet(self->fb.oldvelocity, 0, 0, 0); self->fb.jumping = false; self->fb.firing = false; self->fb.desired_weapon_impulse = 2; self->fb.goal_refresh_time = 0; self->fb.allowedMakeNoise = true; FrogbotSetHealthArmour(self); self->fb.weapon_refresh_time = 0; self->blocked = (func_t) BotBlocked; } qbool BotUsingCorrectWeapon(gedict_t *self) { return ((self->fb.desired_weapon_impulse >= 1) && (self->fb.desired_weapon_impulse <= 8) && (self->s.v.weapon == weapon_impulse_codes[self->fb.desired_weapon_impulse])); } static float goal_client(gedict_t *self, gedict_t *other) { gedict_t *p; int seconds = 0; if (g_globalvars.time < other->invisible_finished) { return 0; // don't chase enemies with eyes } else if (g_globalvars.time < other->invincible_finished) { return 0; // or with pent } if ((p = find(world, FOFCLSN, "timer"))) { seconds = p->cnt2 + (p->cnt - 1) * 60; } if (isDuel() && seconds && timelimit) { // More human logic... if winning, value control, if losing, frag-hunt int frag_difference = self->s.v.frags - other->s.v.frags; if (frag_difference > 10) { // don't chase once comfortably in lead return 0; } else if (frag_difference > 4 && seconds < 60) { // don't chase unless no chance if (!EnemyDefenceless(self)) { return 0; } } else if (frag_difference > 0 && seconds < 20) { // return 0; } } if (self->fb.look_object && (self->s.v.enemy == NUM_FOR_EDICT(self->fb.look_object))) { return (((self->fb.total_damage + 100) * self->fb.firepower - self->fb.virtual_enemy->fb.total_damage * self->fb.virtual_enemy->fb.firepower) * 0.01); } else if (EnemyDefenceless(self)) { return (((self->fb.total_damage + 120) * self->fb.firepower - self->fb.virtual_enemy->fb.total_damage * self->fb.virtual_enemy->fb.firepower) * 0.01); } else { return ((self->fb.total_damage * self->fb.firepower - self->fb.virtual_enemy->fb.total_damage * self->fb.virtual_enemy->fb.firepower) * 0.01); } } static float goal_client6(gedict_t *self, gedict_t *other) { if (!k_matchLess && (match_in_progress != 2)) { return 100; } if ((g_globalvars.time < self->fb.virtual_enemy->invisible_finished) || (g_globalvars.time < self->fb.virtual_enemy->invincible_finished)) { return 0; // or with pent } return (300 - min(self->fb.virtual_enemy->fb.total_damage, 300)); } // client.qc // This is called whenever a client connects (not just bots) // TODO: any preferences stored against the specific bot to be restored here? void BotClientConnectedEvent(gedict_t *self) { self->fb.desire = (deathmatch <= 3 ? goal_client : goal_client6); self->fb.T = UNREACHABLE; self->fb.skill.skill_level = g_globalvars.parm3; self->fb.skill.lookahead_time = 30; self->fb.skill.prediction_error = 0; self->fb.ammo_used = FrogbotWeaponFiredEvent; if (self->isBot) { PlayerReady(true); } // Assign all flags again if (match_in_progress == 2) { BotsAssignTeamFlags(); } } // client.qc void BotOutOfWater(gedict_t *self) { return; // qqshka: meag turned it off for some reason. I commented it out completely so compiler does not emit warnings. #if 0 if (self->s.v.waterlevel == 2) { vec3_t start; vec3_t end; // Tread water self->fb.tread_water_count = self->fb.tread_water_count + 1; if (self->fb.tread_water_count > 75) { self->fb.old_linked_marker = NULL; SetLinkedMarker(self, LocateMarker(self->s.v.origin), "BotOutOfWater"); self->fb.path_state = 0; self->fb.linked_marker_time = g_globalvars.time + 5; } trap_makevectors(self->s.v.v_angle); VectorCopy(self->s.v.origin, start); start[2] += 8; g_globalvars.v_forward[2] = 0; VectorNormalize(g_globalvars.v_forward); VectorScale(g_globalvars.v_forward, 24, g_globalvars.v_forward); VectorAdd(start, g_globalvars.v_forward, end); trap_traceline(PASSVEC3(start), PASSVEC3(end), true, NUM_FOR_EDICT(self)); if (g_globalvars.trace_fraction < 1) { start[2] = self->s.v.origin[2] + self->s.v.maxs[2]; VectorAdd(start, g_globalvars.v_forward, end); VectorScale(g_globalvars.trace_plane_normal, -50, self->s.v.movedir); traceline(start[0], start[1], start[2], end[0], end[1], end[2], true, self); if (g_globalvars.trace_fraction == 1) { vec3_t temp_vector; VectorCopy(self->fb.dir_move_, temp_vector); temp_vector[2] = 225; SetDirectionMove(self, temp_vector, "BotOutOfWater"); SetJumpFlag(self, true, "BotOutOfWater"); } } } #endif } static void BotPeriodicMessages(gedict_t *self) { if (PAST(last_mm2_status)) { qbool has_rl = ((int)self->s.v.items & IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets >= 3; qbool has_lg = ((int)self->s.v.items & IT_LIGHTNING) && self->s.v.ammo_cells >= 6; qbool is_strong = (has_rl || has_lg) && self->fb.total_damage >= 120; if (is_strong && (self->tp.enemy_count == 0)) { TeamplayMessageByName(self, "secure"); } else if (is_strong && (self->tp.enemy_count > self->tp.teammate_count)) { TeamplayMessageByName(self, "help"); } else if (self->tp.enemy_count == 0) { TeamplayMessageByName(self, "status"); } else if (self->fb.look_object && (NUM_FOR_EDICT(self->fb.look_object) == self->s.v.enemy)) { TeamplayMessageByName(self, "point"); } self->fb.last_mm2_status = g_globalvars.time + PERIODIC_MM2_STATUS * (g_random() + 0.5); } // Check for opponents with powerups TeamplayReportVisiblePowerups(self); } // Called for every player, if bots are enabled void BotPreThink(gedict_t *self) { if (self->isBot) { self->fb.firing = self->s.v.button0; self->fb.jumping = self->s.v.button2; if (self->isBot && (match_in_progress == 0) && !self->ready) { PlayerReady(true); } if (teamplay && (match_in_progress == 2)) { BotPeriodicMessages(self); } } self->fb.touch_distance = 1000000; } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_commands.c000066400000000000000000001776011475442401000200440ustar00rootroot00000000000000/* commands.qc Copyright (C) 2000-2003 rxr Copyright (C) 2000-2007 ParboiL */ #ifdef BOT_SUPPORT #include "g_local.h" // Handles all "botcmd x" commands from the user // Cripes. Fix all these declarations void SetAttribs(gedict_t *self, qbool customised); qbool SetAttributesBasedOnSkill(int skill_level); void Bot_Print_Thinking(void); void BotsFireInitialTriggers(gedict_t *client); qbool BotDoorIsClosed(gedict_t *door); qbool POVDMM4DontWalkThroughDoor(gedict_t *entity); gedict_t* BotsFirstBot(void); void RemovePath(gedict_t *marker, int path_number); int AddPath(gedict_t *marker, gedict_t *next_marker); void RemoveMarker(gedict_t *marker); int DecodeMarkerFlagString(const char *string); int DecodeMarkerPathFlagString(const char *string); void BotSetRocketJumpFields(int marker_number, int path_index, float pitch, float yaw, int delay); const char* EncodeMarkerPathFlags(int path_flags); const char* EncodeMarkerFlags(int marker_flags); void DM6Debug(gedict_t *self); float AverageTraceAngle(gedict_t *self, qbool debug, qbool report); char* LocationName(float x, float y, float z); static gedict_t* MarkerIndicator(gedict_t *marker); static qbool customised_skill = false; #define MAX_BOTS 32 #define UNLINKED_MARKER_MODEL "progs/w_g_key.mdl" #define LINKED_MARKER_MODEL "progs/w_s_key.mdl" #define CURRENT_MARKER_MODEL UNLINKED_MARKER_MODEL #define EDITOR_BIDIRECTIONAL_COLOUR EF_BLUE #define EDITOR_UNIDIRECTIONAL_COLOUR EF_RED #define EDITOR_SELECTED_NODE EF_GREEN // If the marker/path flag isn't set here, won't be included in .bot file #define EXTERNAL_MARKER_PATH_FLAGS (WATERJUMP_ | DM6_DOOR | ROCKET_JUMP | JUMP_LEDGE | VERTICAL_PLATFORM) #define EXTERNAL_MARKER_FLAGS (UNREACHABLE | MARKER_IS_DM6_DOOR | MARKER_FIRE_ON_MATCH_START | MARKER_DOOR_TOUCHABLE | MARKER_ESCAPE_ROUTE | MARKER_NOTOUCH) #define MIN_DISTANCE_BETWEEN_MARKERS 30 static qbool marker_time; static float next_marker_time; static qbool hazard_time; static float next_hazard_time; static vec3_t saved_marker_pos = { -999999, -999999, -999999 }; static gedict_t *saved_marker = NULL; static gedict_t *last_touched_marker = NULL; // FIXME: Globals extern gedict_t *markers[]; typedef struct team_s { char name[16]; int humans; int bots; int topColor; int bottomColor; } team_t; static team_t teams[4]; qbool HasSavedMarker(void) { return (saved_marker != NULL); } qbool IsMarkerFrame(void) { return marker_time; } qbool IsHazardFrame(void) { return hazard_time; } typedef struct botcmd_s { int msec; vec3_t angles; int velocity[3]; int buttons; int impulse; } botcmd_t; typedef struct bot_s { int entity; char name[64]; botcmd_t command; } bot_t; bot_t bots[MAX_BOTS] = { { 0 } }; int FrogbotSkillLevel(void) { return (int)cvar(FB_CVAR_SKILL); } int FrogbotHealth(void) { return (int)cvar(FB_CVAR_HEALTH); } int FrogbotWeapon(void) { return (int)cvar(FB_CVAR_WEAPON); } int FrogbotQuadMultiplier(void) { return (int)cvar(FB_CVAR_QUAD_MULTIPLIER); } static team_t* AddTeamToList(int *teamsFound, char *team, int topColor, int bottomColor) { int i; for (i = 0; i < *teamsFound; ++i) { if (streq(team, teams[i].name)) { return &teams[i]; } } if (*teamsFound < sizeof(teams) / sizeof(teams[0])) { i = *teamsFound; strlcpy(teams[i].name, team, sizeof(teams[i].name)); teams[i].topColor = topColor; teams[i].bottomColor = bottomColor; teams[i].humans = teams[i].bots = 0; *teamsFound = *teamsFound + 1; return &teams[i]; } return NULL; } void FrogbotListPaths(void) { int path_count = 0; int path_filter; int arg_number = FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE) ? 2 : 3; char argument[64]; int i, j; if (trap_CmdArgc() <= arg_number) { G_sprint(self, PRINT_HIGH, "Provide path flags: " FROGBOT_PATH_FLAG_OPTIONS "\n"); return; } trap_CmdArgv(arg_number, argument, sizeof(argument)); path_filter = DecodeMarkerPathFlagString(argument); if (!path_filter) { G_sprint(self, PRINT_HIGH, "Path flags invalid, options are %s\n", FROGBOT_PATH_FLAG_OPTIONS); return; } for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; if (!m || (m == world) || (m == dropper)) { continue; } for (j = 0; j < NUMBER_PATHS; ++j) { fb_path_t *p = &m->fb.paths[j]; gedict_t *next = p->next_marker; if (!next || !(p->flags & path_filter)) { continue; } if (path_count == 0) { G_sprint(self, PRINT_HIGH, "Paths found:\n"); } G_sprint(self, PRINT_HIGH, " %3d > %3d \20%s\21 > \20%s\21\n", m->fb.index + 1, next->fb.index + 1, LocationName(PASSVEC3(m->s.v.origin)), LocationName(PASSVEC3(next->s.v.origin))); ++path_count; } } G_sprint(self, PRINT_HIGH, "%3d paths found matching %s\n", path_count, argument); } static void BuildTeamList(void) { int foundTeams = 0; gedict_t *ed; for (ed = world; (ed = find_plr(ed));) { char *t = getteam(ed); int topColor, bottomColor; team_t *team = NULL; if (strnull(t)) { continue; } topColor = atoi(ezinfokey(ed, "topcolor")); bottomColor = atoi(ezinfokey(ed, "bottomcolor")); team = AddTeamToList(&foundTeams, t, topColor, bottomColor); if (team) { if (ed->isBot) { ++team->bots; } else { ++team->humans; } } } // Add defaults AddTeamToList(&foundTeams, "red", 4, 4); AddTeamToList(&foundTeams, "blue", 13, 13); AddTeamToList(&foundTeams, "yellow", 12, 12); AddTeamToList(&foundTeams, "green", 3, 3); } void FrogbotsAddbot(int skill_level, const char *specificteam, qbool error_messages) { int i; skill_level = bound(MIN_FROGBOT_SKILL, skill_level, MAX_FROGBOT_SKILL); for (i = 0; i < sizeof(bots) / sizeof(bots[0]); ++i) { if (bots[i].entity == 0) { int entity = 0; int topColor = 0; int bottomColor = 0; const char *teamName = specificteam; customised_skill = SetAttributesBasedOnSkill(skill_level); if (teamplay && !specificteam[0]) { int team1Count, team2Count; team_t *team; team_t *otherTeam; BuildTeamList(); team1Count = teams[0].humans + teams[0].bots; team2Count = teams[1].humans + teams[1].bots; team = team1Count < team2Count || (team1Count == team2Count && g_random() < 0.5) ? &teams[0] : &teams[1]; otherTeam = team == &teams[0] ? &teams[1] : &teams[0]; if (team->humans && !otherTeam->humans) { strlcpy(bots[i].name, BotNameFriendly(team->bots), sizeof(bots[i].name)); } else if (otherTeam->humans && !team->humans) { strlcpy(bots[i].name, BotNameEnemy(team->bots), sizeof(bots[i].name)); } else { strlcpy(bots[i].name, BotNameGeneric(i), sizeof(bots[i].name)); } topColor = team->topColor; bottomColor = team->bottomColor; teamName = team->name; } else { strlcpy(bots[i].name, BotNameGeneric(i), sizeof(bots[i].name)); topColor = tot_mode_enabled() ? 11 : i_rnd(0, 13); bottomColor = tot_mode_enabled() ? 12 : i_rnd(0, 13); } entity = trap_AddBot(bots[i].name, bottomColor, topColor, "base"); if (entity == 0) { if (error_messages) { G_sprint(self, 2, "Error adding bot\n"); } return; } memset(&bots[i], 0, sizeof(bot_t)); bots[i].entity = entity; memset(&bots[i].command, 0, sizeof(bots[i].command)); g_edicts[entity].fb.last_cmd_sent = g_globalvars.time; g_edicts[entity].fb.skill.skill_level = skill_level; g_edicts[entity].fb.botnumber = i; trap_SetBotUserInfo(entity, "team", teamName, 0); G_bprint(2, "skill &cf00%d&r\n", self->fb.skill.skill_level); SetAttribs(&g_edicts[entity], customised_skill); trap_SetBotUserInfo(entity, "k_nick", bots[i].name, 0); return; } } if (error_messages) { G_sprint(self, 2, "Bot limit reached\n"); } } static void FrogbotsAddbot_f(void) { int skill_level = FrogbotSkillLevel(); char specificteam[10] = { 0 }; if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } if (trap_CmdArgc() >= 3) { char temp[10]; trap_CmdArgv(2, temp, sizeof(temp)); if (isdigit(temp[0])) { skill_level = atoi(temp); } } if (trap_CmdArgc() >= 4) { trap_CmdArgv(3, specificteam, sizeof(specificteam)); } FrogbotsAddbot(skill_level, specificteam, true); } static void FrogbotsRemoveBot(bot_t *lastbot) { gedict_t *e = NULL; e = &g_edicts[lastbot->entity]; G_bprint(PRINT_HIGH, "%s left the game with %.0f frags\n", e->netname, e->s.v.frags); sound(e, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE); trap_RemoveBot(lastbot->entity); memset(lastbot, 0, sizeof(bot_t)); } static void FrogbotsRemovebot_f(void) { int i = 0; bot_t *lastbot = NULL; for (i = 0; i < sizeof(bots) / sizeof(bots[0]); ++i) { if (bots[i].entity) { lastbot = &bots[i]; } } if (lastbot == NULL) { return; } FrogbotsRemoveBot(lastbot); } static void PrintCurrentGoals(void) { int i; gedict_t *touch = self->fb.touch_marker; extern void EvalGoal(gedict_t *self, gedict_t *goal_entity); if (!touch) { return; } self->fb.best_goal_score = 0; self->fb.best_goal = NULL; self->fb.goal_enemy_repel = self->fb.goal_enemy_desire = 0; G_sprint(self, PRINT_HIGH, "Goals from marker #%3d (%s)\n", touch->fb.index + 1, touch->classname); for (i = 0; i < NUMBER_GOALS; ++i) { gedict_t *next = touch->fb.goals[i].next_marker; if ((next == NULL) || (next == world) || (next == dropper)) { continue; } EvalGoal(self, next); G_sprint(self, PRINT_HIGH, " #%2d: %25s = %3.1f\n", i + 1, next->classname, next->fb.saved_goal_desire); } } static void FrogbotsSetSkill(void) { if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } if (trap_CmdArgc() <= 2) { G_sprint(self, 2, "Usage: /botcmd skill \n"); G_sprint(self, 2, " must be in range %d and %d\n", MIN_FROGBOT_SKILL, MAX_FROGBOT_SKILL); G_sprint(self, 2, "bot skill is currently \"%d\"\n", FrogbotSkillLevel()); } else { char argument[32]; int new_skill = 0; int old_skill = FrogbotSkillLevel(); trap_CmdArgv(2, argument, sizeof(argument)); new_skill = bound(MIN_FROGBOT_SKILL, atoi(argument), MAX_FROGBOT_SKILL); if (new_skill != old_skill) { cvar_fset(FB_CVAR_SKILL, new_skill); G_sprint(self, 2, "bot skill changed to \"%d\"\n", new_skill); customised_skill = SetAttributesBasedOnSkill(new_skill); } } } static void FrogbotsDebug(void) { if (trap_CmdArgc() == 2) { Bot_Print_Thinking(); } else { char sub_command[64]; trap_CmdArgv(2, sub_command, sizeof(sub_command)); if (match_in_progress) { return; } if (streq(sub_command, "goals")) { PrintCurrentGoals(); } else if (streq(sub_command, "door")) { if (streq(mapname, "povdmm4")) { if (markers[0]->fb.door_entity && markers[4]->fb.door_entity) { G_sprint(self, 2, "Low-spawn door is %s @ %f %f %f\n", BotDoorIsClosed(markers[0]) ? "closed" : "open", PASSVEC3(markers[0]->s.v.origin)); G_sprint(self, 2, "High-spawn door is %s @ %f %f %f\n", BotDoorIsClosed(markers[4]) ? "closed" : "open", PASSVEC3(markers[4]->s.v.origin)); G_sprint(self, 2, "Low-spawn YA is %s\n", POVDMM4DontWalkThroughDoor(markers[2]) ? "blocked" : "available"); G_sprint(self, 2, "High-spawn YA is %s\n", POVDMM4DontWalkThroughDoor(markers[5]) ? "blocked" : "available"); } } else { G_sprint(self, 2, "Only available on povdmm4.\n"); } } else if (streq(sub_command, "markers")) { int i = 0; for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i]) { G_sprint(self, 2, "%d / %d: %s\n", i, markers[i]->fb.index + 1, markers[i]->classname); } } } else if (streq(sub_command, "entity")) { int ent = 0; trap_CmdArgv(3, sub_command, sizeof(sub_command)); ent = atoi(sub_command); if ((ent > 0) && (ent < MAX_EDICTS)) { G_sprint(self, 2, "%d: %s [%f %f %f]\n", atoi(sub_command), g_edicts[ent].classname ? g_edicts[ent].classname : "?", PASSVEC3(g_edicts[ent].s.v.origin)); } else { G_sprint(self, 2, "%d - out of range\n", atoi(sub_command)); } } else if (streq(sub_command, "marker")) { gedict_t *marker = NULL; int i = 0; if (trap_CmdArgc() == 4) { trap_CmdArgv(3, sub_command, sizeof(sub_command)); marker = markers[(int)bound(0, atoi(sub_command) - 1, NUMBER_MARKERS - 1)]; } else { marker = LocateMarker(self->s.v.origin); } if (marker == NULL) { G_sprint(self, 2, "(marker #%d not present)\n", atoi(sub_command)); } else { G_sprint(self, 2, "Marker %d, %s, position %d %d %d\n", marker->fb.index + 1, marker->classname, PASSINTVEC3(marker->s.v.origin)); G_sprint(self, 2, "> mins [%d %d %d] maxs [%d %d %d]\n", PASSINTVEC3(marker->s.v.mins), PASSINTVEC3(marker->s.v.maxs)); G_sprint(self, 2, "> absmin [%d %d %d] absmax [%d %d %d]\n", PASSINTVEC3(marker->s.v.absmin), PASSINTVEC3(marker->s.v.absmax)); G_sprint(self, 2, "Zone %d, Subzone %d\n", marker->fb.Z_, marker->fb.S_); G_sprint(self, 2, "Paths:\n"); for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = marker->fb.paths[i].next_marker; if (next != NULL) { G_sprint(self, 2, " %d: %d (%s), time %3.1f, rj time %3.1f\n", i + 1, next->fb.index + 1, next->classname, marker->fb.paths[i].time, marker->fb.paths[i].rj_time); } } G_sprint(self, 2, "Zones:\n"); for (i = 0; i < NUMBER_ZONES; ++i) { fb_zone_t *zone = &marker->fb.zones[i]; if (zone->next) { G_sprint(self, 2, " %2d: %d (%s), time %3.1f\n", i + 1, zone->next->fb.index + 1, zone->next->classname, zone->time); } if (zone->next_rj) { G_sprint(self, 2, " RJ%2d: %d (%s), time %3.1f\n", i + 1, zone->next_rj->fb.index + 1, zone->next_rj->classname, zone->rj_time); } } G_sprint(self, 2, "Goals:\n"); for (i = 0; i < NUMBER_GOALS; ++i) { fb_goal_t *goal = &marker->fb.goals[i]; if (goal->next_marker) { G_sprint(self, 2, " %2d: %d (%s), time %3.1f\n", i + 1, goal->next_marker->fb.index + 1, goal->next_marker->classname, goal->time); } if (goal->next_marker_rj) { G_sprint(self, 2, " RJ%2d: %d (%s), time %3.1f\n", i + 1, goal->next_marker_rj->fb.index + 1, goal->next_marker_rj->classname, goal->rj_time); } } } } else if ((streq(sub_command, "path") || streq(sub_command, "path/rj")) && (trap_CmdArgc() == 5)) { int start, end; qbool allow_rj = streq(sub_command, "path/rj"); trap_CmdArgv(3, sub_command, sizeof(sub_command)); start = atoi(sub_command); trap_CmdArgv(4, sub_command, sizeof(sub_command)); end = atoi(sub_command); if ((start > 0) && (start <= NUMBER_MARKERS) && (end > 0) && (end <= NUMBER_MARKERS)) { gedict_t *from = markers[start - 1]; gedict_t *to = markers[end - 1]; if (from && to) { G_sprint(self, 2, "%s \20%s\21 -> %s \20%s\21\n", from->classname, LocationName(PASSVEC3(from->s.v.origin)), to->classname, LocationName(PASSVEC3(to->s.v.origin))); G_sprint(self, 2, "From zone %d, subzone %d to zone %d subzone %d\n", from->fb.Z_, from->fb.S_, to->fb.Z_, to->fb.S_); from_marker = from; ZoneMarker(from_marker, to, path_normal, allow_rj); traveltime = SubZoneArrivalTime(zone_time, middle_marker, to, allow_rj); G_sprint(self, 2, "Travel time %f, zone_time %f\n", traveltime, zone_time); G_sprint(self, 2, "Middle marker %d \20%s\21 (zone %d subzone %d), time %f\n", middle_marker->fb.index + 1, LocationName(PASSVEC3(middle_marker->s.v.origin)), middle_marker->fb.Z_, middle_marker->fb.S_, middle_marker->fb.subzones[to->fb.S_].time); { float best_score = -1000000; gedict_t *linked_marker_ = NULL; int new_path_state = 0; int new_angle_hint = 0; vec3_t player_direction = { 0, 0, 0 }; // Standing still, for sake of argument int new_rj_frame_delay = 0; float new_rj_angles[2] = { 0, 0 }; PathScoringLogic(to->fb.goal_respawn_time, false, 30, true, from->s.v.origin, player_direction, from, to, false, allow_rj, true, NULL, &best_score, &linked_marker_, &new_path_state, &new_angle_hint, &new_rj_frame_delay, new_rj_angles); if (linked_marker_) { G_sprint( self, PRINT_HIGH, "Finished: next marker %d (%s) \20%s\21, best_score %5.2f\n", linked_marker_->fb.index + 1, linked_marker_->classname, LocationName(PASSVEC3(linked_marker_->s.v.origin)), best_score); } else { G_sprint(self, PRINT_HIGH, "Finished: next marker \20UNKNOWN\21\n"); } if (new_path_state & ROCKET_JUMP) { G_sprint(self, PRINT_HIGH, "> RJ Delay: %d frames, [%3.1f %3.1f]\n", new_rj_frame_delay, new_rj_angles[PITCH], new_rj_angles[YAW]); } } } } } else if (streq(sub_command, "random")) { RunRandomTrials(0, 6, 2); } else if (streq(sub_command, "startmap")) { if (!k_practice) { SetPractice(1, NULL); } if (!k_practice) { G_sprint(self, 2, "Map must be in practice mode\n"); return; } BotsFireInitialTriggers(self); } else if (streq(sub_command, "botpath") || streq(sub_command, "botpath/rj")) { gedict_t *first_bot = BotsFirstBot(); gedict_t *marker = NULL; gedict_t *target = NULL; vec3_t teleport_angles = { 0, 0, 0 }; vec3_t teleport_location = { 0, 0, 0 }; qbool allow_rj = streq(sub_command, "botpath/rj"); if (!k_practice) { SetPractice(1, NULL); } if ((first_bot == NULL) || !k_practice) { G_sprint(self, 2, "Map must be in practice mode and have one bot\n"); return; } trap_CmdArgv(3, sub_command, sizeof(sub_command)); marker = markers[(int)bound(0, atoi(sub_command) - 1, NUMBER_MARKERS - 1)]; if ((marker == NULL) || ((marker->fb.index + 1) != atoi(sub_command))) { G_sprint(self, 2, "(marker #%d not present)\n", atoi(sub_command)); return; } trap_CmdArgv(4, sub_command, sizeof(sub_command)); target = markers[(int)bound(0, atoi(sub_command) - 1, NUMBER_MARKERS - 1)]; if ((target == NULL) || ((target->fb.index + 1) != atoi(sub_command))) { G_sprint(self, 2, "(marker #%d not present)\n", atoi(sub_command)); return; } first_bot->fb.fixed_goal = target; first_bot->fb.debug = true; first_bot->fb.debug_path = true; first_bot->fb.debug_path_rj = allow_rj; //cvar_fset (FB_CVAR_DEBUG, 1); VectorClear(first_bot->s.v.velocity); trap_SetBotCMD(NUM_FOR_EDICT(first_bot), g_globalvars.frametime, 0, 0, 0, 0, 0, 0, 0, 0); first_bot->fb.debug_path_start = g_globalvars.time; first_bot->fb.touch_marker_time = first_bot->fb.linked_marker_time = first_bot->fb.goal_refresh_time = 0; first_bot->fb.old_linked_marker = NULL; G_sprint(self, 2, "Marker #%d (%s) set as goalent\n", target->fb.index + 1, target->classname); VectorCopy(marker->s.v.origin, teleport_location); if (!streq(marker->classname, "marker")) { teleport_location[2] += 32; } first_bot->fb.dbg_countdown = 33; teleport_player(first_bot, teleport_location, teleport_angles, TFLAGS_SND_DST | TFLAGS_FOG_DST); } else if (streq(sub_command, "dm6")) { DM6Debug(self); } else if (streq(sub_command, "trace")) { AverageTraceAngle(self, true, true); } else if (streq(sub_command, "info")) { } else if (streq(sub_command, "pathlist")) { FrogbotListPaths(); } } } static void FrogbotGoto(void) { gedict_t *marker = NULL; char buffer[64]; vec3_t teleport_location; vec3_t teleport_angles = { 0, 0, 0 }; if (trap_CmdArgc() != 3) { G_sprint(self, PRINT_HIGH, "Usage: /botcmd goto \n"); return; } trap_CmdArgv(2, buffer, sizeof(buffer)); marker = markers[(int)bound(0, atoi(buffer) - 1, NUMBER_MARKERS - 1)]; if (!marker) { G_sprint(self, PRINT_HIGH, "Marker #%3d not found\n", atoi(buffer)); return; } VectorCopy(marker->s.v.origin, teleport_location); if (!streq(marker->classname, "marker")) { teleport_location[2] += 32; } teleport_player(self, teleport_location, teleport_angles, TFLAGS_SND_DST | TFLAGS_FOG_DST); } static void FrogbotMoveMarker(void) { gedict_t *marker = LocateMarker(self->s.v.origin); gedict_t *indicator; while ((marker != NULL) && !streq(marker->classname, "marker")) { marker = LocateNextMarker(self->s.v.origin, marker); } if (marker == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } setorigin(marker, PASSVEC3(self->s.v.origin)); indicator = MarkerIndicator(marker); if (indicator) { extern void SetMarkerIndicatorPosition(gedict_t *item, gedict_t *indicator); SetMarkerIndicatorPosition(marker, indicator); } } static int FindPathIndex(gedict_t *saved_marker, gedict_t *nearest) { int i = 0; if ((saved_marker == NULL) || (nearest == NULL)) { return -1; } for (i = 0; i < NUMBER_PATHS; ++i) { if (saved_marker->fb.paths[i].next_marker == nearest) { return i; } } return -1; } static void BotFileGenerate(void) { fileHandle_t file; char *entityFile = cvar_string("k_entityfile"); char date[64]; char fileName[256]; int i; if (!QVMstrftime(date, sizeof(date), "%Y%m%d-%H%M%S", 0)) { snprintf(date, sizeof(date), "%d", i_rnd(0, 9999)); } snprintf(fileName, sizeof(fileName), "bots/maps/%s[%s].bot", strnull(entityFile) ? mapname : entityFile, date); file = std_fwopen("%s", fileName); if (file == -1) { G_sprint(self, PRINT_HIGH, "Failed to open botfile. Check bots/maps/ directory is writable\n"); return; } for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i] && streq(markers[i]->classname, "marker")) { std_fprintf(file, "CreateMarker %d %d %d\n", PASSINTVEC3(markers[i]->s.v.origin)); } } for (i = 0; i < NUMBER_MARKERS; ++i) { int p; if (markers[i] == NULL || markers[i] == world) { continue; } if (markers[i]->fb.T & MARKER_DYNAMICALLY_ADDED) { continue; } if (markers[i]->fb.G_) { std_fprintf(file, "SetGoal %d %d\n", markers[i]->fb.index + 1, markers[i]->fb.G_); } if (markers[i]->fb.Z_) { std_fprintf(file, "SetZone %d %d\n", markers[i]->fb.index + 1, markers[i]->fb.Z_); } if (markers[i]->fb.T & EXTERNAL_MARKER_FLAGS) { std_fprintf(file, "SetMarkerFlag %d %s\n", markers[i]->fb.index + 1, EncodeMarkerFlags(markers[i]->fb.T & EXTERNAL_MARKER_FLAGS)); } if (markers[i]->fb.T & MARKER_EXPLICIT_VIEWOFFSET) { std_fprintf(file, "SetMarkerViewOfs %d %d\n", markers[i]->fb.index + 1, (int)markers[i]->s.v.view_ofs[2]); } for (p = 0; p < NUMBER_PATHS; ++p) { if (markers[i]->fb.paths[p].next_marker && !(markers[i]->fb.paths[p].next_marker->fb.T & MARKER_DYNAMICALLY_ADDED)) { std_fprintf(file, "SetMarkerPath %d %d %d\n", markers[i]->fb.index + 1, p, markers[i]->fb.paths[p].next_marker->fb.index + 1); if (markers[i]->fb.paths[p].flags & EXTERNAL_MARKER_PATH_FLAGS) { std_fprintf( file, "SetMarkerPathFlags %d %d %s\n", markers[i]->fb.index + 1, p, EncodeMarkerPathFlags( markers[i]->fb.paths[p].flags & EXTERNAL_MARKER_PATH_FLAGS)); if (markers[i]->fb.paths[p].flags & ROCKET_JUMP) { gedict_t *m = markers[i]; fb_path_t *path = &markers[i]->fb.paths[p]; std_fprintf(file, "SetRocketJumpPathFields %d %d %3.1f %3.1f %d\n", m->fb.index + 1, p, path->rj_pitch, path->rj_yaw, path->rj_delay); } } if (markers[i]->fb.paths[p].angle_hint) { std_fprintf(file, "SetMarkerPathAngleHint %d %d %d\n", markers[i]->fb.index + 1, p, markers[i]->fb.paths[p].angle_hint); } } } } if (MapDeathHeight() > FB_MAPDEATHHEIGHT_DEFAULT) { std_fprintf(file, "SetMapDeathHeight %d\n", MapDeathHeight()); } std_fclose(file); G_sprint(self, PRINT_HIGH, "Created file %s\n", fileName); } static gedict_t* MarkerIndicator(gedict_t *marker) { gedict_t *indicator; if ((marker == NULL) || streq(marker->classname, "marker")) { return marker; } for (indicator = world; (indicator = ez_find(indicator, "marker_indicator"));) { if (indicator->fb.index == marker->fb.index) { return indicator; } } return NULL; } static void SelectMarker(gedict_t *marker) { gedict_t *indicator; int i; indicator = MarkerIndicator(marker); if (indicator) { indicator->s.v.effects = (int)indicator->s.v.effects | EDITOR_SELECTED_NODE; setmodel(indicator, CURRENT_MARKER_MODEL); } for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = marker->fb.paths[i].next_marker; if (next) { int j; int effect = EDITOR_UNIDIRECTIONAL_COLOUR; gedict_t *next_indicator = MarkerIndicator(next); if (next_indicator != NULL) { for (j = 0; j < NUMBER_PATHS; ++j) { if (next->fb.paths[j].next_marker == marker) { effect = EDITOR_BIDIRECTIONAL_COLOUR; } } next_indicator->s.v.effects = ((int)next_indicator->s.v.effects & ~(EDITOR_UNIDIRECTIONAL_COLOUR | EDITOR_BIDIRECTIONAL_COLOUR)) | effect; setmodel(next_indicator, LINKED_MARKER_MODEL); } } } } static void DeselectMarker(gedict_t *marker) { gedict_t *indicator = MarkerIndicator(marker); int i = 0; if (indicator) { indicator->s.v.effects = (int)indicator->s.v.effects & ~EDITOR_SELECTED_NODE; } for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = marker->fb.paths[i].next_marker; if (next) { gedict_t *next_indicator = MarkerIndicator(next); if (next_indicator) { next_indicator->s.v.effects = (int)next_indicator->s.v.effects & ~(EDITOR_UNIDIRECTIONAL_COLOUR | EDITOR_BIDIRECTIONAL_COLOUR); setmodel(next_indicator, UNLINKED_MARKER_MODEL); } } } } void FrogbotEditorMarkerTouched(gedict_t *marker) { if (saved_marker == NULL) { if (last_touched_marker != marker) { if (last_touched_marker) { DeselectMarker(last_touched_marker); } SelectMarker(marker); } } last_touched_marker = marker; } static void FrogbotMapInfo(void) { if (streq(mapname, "aerowalk")) { gedict_t *quad = ez_find(world, "item_artifact_super_damage"); gedict_t *tele_exit = markers[10]; gedict_t *high_landing = markers[70]; if (quad) { gedict_t *indicator = MarkerIndicator(quad); G_sprint(self, PRINT_HIGH, "Found quad damage, marker #%3d, goal %d, zone %d\n", quad->fb.index + 1, quad->fb.G_, quad->fb.Z_); G_sprint(self, PRINT_HIGH, " solid = %d, fl_marker = %s\n", (int)quad->s.v.solid, quad->fb.fl_marker ? "true" : "false"); if (indicator) { G_sprint(self, PRINT_HIGH, "Indicator found @ %d %d %d\n", PASSINTVEC3(indicator->s.v.origin)); } else { G_sprint(self, PRINT_HIGH, "Indicator for quad not found...\n"); } } else { G_sprint(self, PRINT_HIGH, "Quad damage not found\n"); } if (tele_exit && high_landing) { vec3_t high_pos; VectorAdd(high_landing->s.v.absmin, high_landing->s.v.view_ofs, high_pos); G_sprint(self, PRINT_HIGH, "Tele-exit: %3d %3d %3d\n", PASSINTVEC3(tele_exit->s.v.origin)); G_sprint(self, PRINT_HIGH, "High-landing: %3d %3d %3d\n", PASSINTVEC3(high_pos)); VectorSubtract(high_pos, tele_exit->s.v.origin, high_pos); G_sprint(self, PRINT_HIGH, "Difference: %3d %3d %3d\n", PASSINTVEC3(high_pos)); } } else { G_sprint(self, PRINT_HIGH, "No map-specific info available\n"); } } static void FrogbotAddMarker(void) { vec3_t pos, nearest_pos; gedict_t *nearest = LocateMarker(self->s.v.origin); gedict_t *spawn = NULL; if (nearest) { VectorAdd(self->s.v.origin, self->s.v.view_ofs, pos); VectorAdd(nearest->s.v.origin, nearest->s.v.view_ofs, nearest_pos); if (VectorDistance(nearest_pos, pos) < MIN_DISTANCE_BETWEEN_MARKERS) { G_sprint(self, PRINT_HIGH, "Too close to marker #%d [%s]\n", nearest->fb.index + 1, nearest->classname); return; } } spawn = CreateNewMarker(self->s.v.origin); G_sprint(self, PRINT_HIGH, "Created marker #%d\n", spawn->fb.index + 1); } static void FrogbotRemoveMarker(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); if (!nearest) { G_sprint(self, PRINT_HIGH, "No marker found nearby\n"); return; } if (!streq(nearest->classname, "marker")) { G_sprint(self, PRINT_HIGH, "Cannot remove non-manual markers\n"); return; } if (saved_marker == nearest) { DeselectMarker(nearest); saved_marker = NULL; } RemoveMarker(nearest); } static void FrogbotSaveMarker(void) { if (saved_marker == NULL) { gedict_t *nearest = LocateMarker(self->s.v.origin); if (nearest != NULL) { if (last_touched_marker) { DeselectMarker(last_touched_marker); } SelectMarker(saved_marker = nearest); VectorCopy(self->s.v.origin, saved_marker_pos); G_sprint(self, PRINT_HIGH, "Marker #%d [%s] is saved\n", nearest->fb.index + 1, nearest->classname); } } else if (saved_marker && VectorCompare(self->s.v.origin, saved_marker_pos)) { gedict_t *nearest = LocateNextMarker(self->s.v.origin, saved_marker); if (nearest) { DeselectMarker(saved_marker); SelectMarker(saved_marker = nearest); G_sprint(self, PRINT_HIGH, "Marker #%d [%s] is saved\n", nearest->fb.index + 1, nearest->classname); } else { DeselectMarker(saved_marker); saved_marker = NULL; if (last_touched_marker) { SelectMarker(last_touched_marker); } G_sprint(self, PRINT_HIGH, "Cleared saved marker\n"); } } else { DeselectMarker(saved_marker); saved_marker = NULL; if (last_touched_marker) { SelectMarker(last_touched_marker); } G_sprint(self, PRINT_HIGH, "Cleared saved marker\n"); } } static void FrogbotAddPath(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); gedict_t *nearest_indicator; int source_to_target_path = FindPathIndex(saved_marker, nearest); int target_to_source_path = FindPathIndex(nearest, saved_marker); if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "Could not locate marker nearby\n"); return; } if (saved_marker == NULL) { G_sprint(self, PRINT_HIGH, "Save a marker before creating path\n"); return; } if (nearest == saved_marker) { G_sprint(self, PRINT_HIGH, "Cannot link a marker to itself\n"); return; } if (source_to_target_path >= 0 && target_to_source_path >= 0) { RemovePath(saved_marker, source_to_target_path); RemovePath(nearest, target_to_source_path); nearest_indicator = MarkerIndicator(nearest); if (nearest_indicator) { nearest_indicator->s.v.effects = (int)nearest_indicator->s.v.effects & ~(EDITOR_BIDIRECTIONAL_COLOUR | EDITOR_UNIDIRECTIONAL_COLOUR); setmodel(nearest_indicator, UNLINKED_MARKER_MODEL); } G_sprint(self, PRINT_HIGH, "Both paths cleared - no link\n"); return; } if (source_to_target_path >= 0) { if (AddPath(nearest, saved_marker) >= 0) { G_sprint(self, PRINT_HIGH, "Marker %d > %d linked (bi-directional)\n", nearest->fb.index + 1, saved_marker->fb.index + 1); nearest_indicator = MarkerIndicator(nearest); if (nearest_indicator) { nearest_indicator->s.v.effects = ((int)nearest_indicator->s.v.effects & ~EDITOR_UNIDIRECTIONAL_COLOUR) | EDITOR_BIDIRECTIONAL_COLOUR; setmodel(nearest_indicator, LINKED_MARKER_MODEL); } } else { G_sprint(self, PRINT_HIGH, "{&cf00ERROR&cfff}: Unable to link (maximum paths hit?)\n"); } return; } if (AddPath(saved_marker, nearest) >= 0) { G_sprint(self, PRINT_HIGH, "Marker %d > %d linked (uni-directional)\n", saved_marker->fb.index + 1, nearest->fb.index + 1); nearest_indicator = MarkerIndicator(nearest); if (nearest_indicator) { nearest_indicator->s.v.effects = ((int)nearest_indicator->s.v.effects & ~EDITOR_BIDIRECTIONAL_COLOUR) | EDITOR_UNIDIRECTIONAL_COLOUR; setmodel(nearest_indicator, LINKED_MARKER_MODEL); } } else { G_sprint(self, PRINT_HIGH, "{&cf00ERROR&cfff}: Unable to link (maximum paths hit?)\n"); } } static void FrogbotRemovePath(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); gedict_t *nearest_indicator; int source_to_target_path = FindPathIndex(saved_marker, nearest); int target_to_source_path = FindPathIndex(nearest, saved_marker); if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "Could not locate marker nearby\n"); return; } if (saved_marker == NULL) { G_sprint(self, PRINT_HIGH, "Save a marker before creating path\n"); return; } if (source_to_target_path >= 0) { RemovePath(saved_marker, source_to_target_path); } if (target_to_source_path >= 0) { RemovePath(nearest, target_to_source_path); } nearest_indicator = MarkerIndicator(nearest); if (nearest_indicator) { nearest_indicator->s.v.effects = (int)nearest_indicator->s.v.effects & ~(EDITOR_UNIDIRECTIONAL_COLOUR | EDITOR_BIDIRECTIONAL_COLOUR); setmodel(nearest_indicator, UNLINKED_MARKER_MODEL); } } static void FrogbotRemoveAllPaths(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int i; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "Could not locate marker nearby\n"); return; } for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = nearest->fb.paths[i].next_marker; if (next) { gedict_t *indicator = MarkerIndicator(next); if (indicator) { indicator->s.v.effects = (int)indicator->s.v.effects & ~(EDITOR_UNIDIRECTIONAL_COLOUR | EDITOR_BIDIRECTIONAL_COLOUR); setmodel(indicator, UNLINKED_MARKER_MODEL); } } RemovePath(nearest, i); } } static void FrogbotSetZone(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int zone = 0; if (trap_CmdArgc() >= 4) { char param[64]; int marker_number = 0; int i; trap_CmdArgv(2, param, sizeof(param)); marker_number = bound(1, atoi(param), NUMBER_MARKERS); trap_CmdArgv(3, param, sizeof(param)); zone = bound(1, atoi(param), NUMBER_ZONES); for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i] && markers[i]->fb.index == marker_number - 1) { nearest = markers[i]; break; } } if (!nearest) { G_sprint(self, PRINT_HIGH, "No marker #%3d found\n", marker_number); return; } } else { if (!nearest) { G_sprint(self, PRINT_HIGH, "No marker found nearby\n"); return; } zone = nearest->fb.Z_ + 1; if (zone > NUMBER_ZONES) { zone = 1; } if (trap_CmdArgc() == 3) { char param[64]; trap_CmdArgv(2, param, sizeof(param)); if (atoi(param) != 0) { zone = bound(1, atoi(param), NUMBER_ZONES); } } } nearest->fb.Z_ = zone; G_sprint(self, PRINT_HIGH, "Marker #%d now has zone %d\n", nearest->fb.index + 1, nearest->fb.Z_); } static void FrogbotSetMarkerFlag(void) { char param[64]; gedict_t *nearest = LocateMarker(self->s.v.origin); int flags; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (trap_CmdArgc() < 3) { G_sprint(self, PRINT_HIGH, "Provide marker flags: " FROGBOT_MARKER_FLAG_OPTIONS "\n"); return; } trap_CmdArgv(2, param, sizeof(param)); flags = DecodeMarkerFlagString(param); if (flags) { nearest->fb.T |= flags; G_sprint(self, PRINT_HIGH, "Marker flags set, now: %s\n", EncodeMarkerFlags(nearest->fb.T)); } else { G_sprint(self, PRINT_HIGH, "Marker flags invalid, options are %s\n", FROGBOT_MARKER_FLAG_OPTIONS); } } static void FrogbotClearMarkerFlag(void) { char param[64]; gedict_t *nearest = LocateMarker(self->s.v.origin); int flags; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (trap_CmdArgc() < 3) { G_sprint(self, PRINT_HIGH, "Provide marker flags: " FROGBOT_MARKER_FLAG_OPTIONS "\n"); return; } trap_CmdArgv(2, param, sizeof(param)); flags = DecodeMarkerFlagString(param); if (flags) { nearest->fb.T &= ~flags; G_sprint(self, PRINT_HIGH, "Marker flags cleared, now: %s\n", EncodeMarkerFlags(nearest->fb.T)); } else { G_sprint(self, PRINT_HIGH, "Marker flags invalid, options are %s\n", FROGBOT_MARKER_FLAG_OPTIONS); } } static void FrogbotSetAngleHint(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int source_to_target_path = FindPathIndex(saved_marker, nearest); char param[64]; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (source_to_target_path >= 0) { short offset = saved_marker->fb.paths[source_to_target_path].angle_hint; if (trap_CmdArgc() < 3) { G_sprint(self, PRINT_HIGH, "Current angle hint: %d\n", offset); return; } trap_CmdArgv(2, param, sizeof(param)); offset = atoi(param); saved_marker->fb.paths[source_to_target_path].angle_hint = offset; G_sprint(self, PRINT_HIGH, "Angle hint set to %d\n", offset); } else { G_sprint(self, PRINT_HIGH, "No path linked to add angle hint\n"); } } static void FrogbotSetPathFlag(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int source_to_target_path = FindPathIndex(saved_marker, nearest); char param[64]; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (trap_CmdArgc() < 3) { G_sprint(self, PRINT_HIGH, "Provide path flags: " FROGBOT_PATH_FLAG_OPTIONS "\n"); return; } trap_CmdArgv(2, param, sizeof(param)); if (source_to_target_path >= 0) { int flags = DecodeMarkerPathFlagString(param); if (flags) { saved_marker->fb.paths[source_to_target_path].flags |= flags; G_sprint(self, PRINT_HIGH, "Path flags set, now: %s\n", EncodeMarkerPathFlags(saved_marker->fb.paths[source_to_target_path].flags)); } else { G_sprint(self, PRINT_HIGH, "Path flags invalid, options are %s\n", FROGBOT_PATH_FLAG_OPTIONS); } } else { G_sprint(self, PRINT_HIGH, "No path linked to add flag\n"); } } static void FrogbotClearPathFlag(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int source_to_target_path = FindPathIndex(saved_marker, nearest); char param[64]; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (trap_CmdArgc() < 3) { G_sprint(self, PRINT_HIGH, "Provide path flags: " FROGBOT_PATH_FLAG_OPTIONS "\n"); return; } trap_CmdArgv(2, param, sizeof(param)); if (source_to_target_path >= 0) { int flags = DecodeMarkerPathFlagString(param); if (flags) { saved_marker->fb.paths[source_to_target_path].flags &= ~flags; G_sprint(self, PRINT_HIGH, "Path flags cleared, now: %s\n", EncodeMarkerPathFlags(saved_marker->fb.paths[source_to_target_path].flags)); } else { G_sprint(self, PRINT_HIGH, "Path flags invalid, options are %s\n", FROGBOT_PATH_FLAG_OPTIONS); } } else { G_sprint(self, PRINT_HIGH, "No path linked to add flag\n"); } } static void FrogbotSaveBotFile(void) { int i = 0, j = 0; gedict_t *new_markers[NUMBER_MARKERS] = { 0 }; // Renumber all markers for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i]) { markers[i]->fb.index = j; new_markers[j++] = markers[i]; } } memcpy(markers, new_markers, sizeof(new_markers)); BotFileGenerate(); } static void FrogbotShowInfo(void) { char message[1024] = { 0 }; int i = 0; gedict_t *marker = self->fb.touch_marker; const char *marker_flags = 0; if (trap_CmdArgc() >= 3) { char temp[10]; trap_CmdArgv(2, temp, sizeof(temp)); if ((atoi(temp) >= 1) && (atoi(temp) <= NUMBER_MARKERS)) { marker = markers[atoi(temp) - 1]; if (marker == NULL) { G_sprint(self, PRINT_HIGH, "No such marker #%d found\n", atoi(temp)); return; } } } if (marker == NULL) { marker = LocateMarker(self->s.v.origin); } if (marker == NULL) { G_sprint(self, PRINT_HIGH, "Unable to find nearby marker\n"); return; } marker_flags = EncodeMarkerFlags(marker->fb.T); if (g_globalvars.time < self->fb.last_spec_cp) { return; } if (!marker) { return; } strlcpy(message, va("Marker #%3d [%s]\n", marker->fb.index + 1, marker->classname), sizeof(message)); strlcat(message, va("Origin %3d %3d %3d\n", PASSINTVEC3(marker->s.v.origin)), sizeof(message)); strlcat(message, va("Dim [%3d %3d %3d] > [%3d %3d %3d]\n\n", PASSINTVEC3(marker->s.v.absmin), PASSINTVEC3(marker->s.v.absmax)), sizeof(message)); strlcat(message, va("Zone #%2d, Goal #%2d\n", marker->fb.Z_, marker->fb.G_), sizeof(message)); strlcat(message, va("Flags: %s\n", strnull(marker_flags) ? "(none)" : marker_flags), sizeof(message)); strlcat(message, "Paths:\n", sizeof(message)); for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = marker->fb.paths[i].next_marker; if (next) { const char *path_flags = EncodeMarkerPathFlags(marker->fb.paths[i].flags); strlcat(message, va(" %3d: %s [%s] ang %d\n", next->fb.index + 1, next->classname, strnull(path_flags) ? "(none)" : path_flags, marker->fb.paths[i].angle_hint), sizeof(message)); } } G_centerprint(self, "%s", message); self->fb.last_spec_cp = g_globalvars.time + 0.2; } static void FrogbotPathList(void) { char message[1024] = { 0 }; int i = 0; gedict_t *marker = self->fb.touch_marker; if (trap_CmdArgc() >= 3) { char temp[10]; trap_CmdArgv(2, temp, sizeof(temp)); if (atoi(temp) >= 1 && atoi(temp) <= NUMBER_MARKERS) { marker = markers[atoi(temp) - 1]; if (marker == NULL) { G_sprint(self, PRINT_HIGH, "No such marker #%d found\n", atoi(temp)); return; } } } if (marker == NULL) { marker = LocateMarker(self->s.v.origin); } if (marker == NULL) { G_sprint(self, PRINT_HIGH, "Unable to find nearby marker\n"); return; } if (g_globalvars.time < self->fb.last_spec_cp) { return; } if (!marker) { return; } strlcpy(message, "Paths away:\n", sizeof(message)); for (i = 0; i < NUMBER_PATHS; ++i) { gedict_t *next = marker->fb.paths[i].next_marker; if (next) { const char *path_flags = EncodeMarkerPathFlags(marker->fb.paths[i].flags); strlcat(message, va(" %3d: %s [%s] ang %d\n", next->fb.index + 1, next->classname, strnull(path_flags) ? "(none)" : path_flags, marker->fb.paths[i].angle_hint), sizeof(message)); } } strlcat(message, "Path to:\n", sizeof(message)); for (i = 0; i < NUMBER_MARKERS; ++i) { int j; if (!markers[i]) { continue; } for (j = 0; j < NUMBER_PATHS; ++j) { if (markers[i]->fb.paths[j].next_marker == marker) { strlcat(message, va(" %3d: %s\n", markers[i]->fb.index + 1, markers[i]->classname), sizeof(message)); } } } G_sprint(self, PRINT_HIGH, "%s", message); } static void FrogbotsFillServer(void) { int max_clients = cvar("maxclients"); int plr_count = CountPlayers(); int skill_level = FrogbotSkillLevel(); int i; if (trap_CmdArgc() >= 3) { char temp[10]; trap_CmdArgv(2, temp, sizeof(temp)); if (isdigit(temp[0])) { skill_level = atoi(temp); } } for (i = 0; i < min(max_clients - plr_count, 8); ++i) { FrogbotsAddbot(skill_level, "", true); } cvar_fset(FB_CVAR_SKILL, skill_level); } static void FrogbotsRemoveAll(void) { int bot_count = CountBots(); while (bot_count-- > 0) { FrogbotsRemovebot_f(); } } static void FrogbotGoalSummary(void) { int i, j; G_sprint(self, PRINT_HIGH, "Goal summary:\n"); for (i = 1; i <= NUMBER_GOALS; ++i) { qbool first = true; for (j = 0; j < NUMBER_MARKERS; ++j) { if (markers[j] && markers[j]->fb.G_ == i) { if (first) { G_sprint(self, PRINT_HIGH, " Goal #%2d:\n", i); first = false; } G_sprint(self, PRINT_HIGH, " %3d: %s\n", markers[j]->fb.index + 1, markers[j]->classname); } } } } static void FrogbotZoneSummary(void) { int i, j; G_sprint(self, PRINT_HIGH, "Zone summary:\n"); for (i = 0; i <= NUMBER_ZONES; ++i) { qbool first = true; for (j = 0; j < NUMBER_MARKERS; ++j) { if (markers[j] && (markers[j]->fb.Z_ == i)) { if (first) { if (i) { G_sprint(self, PRINT_HIGH, " Zone #%2d:\n", i); } else { G_sprint(self, PRINT_HIGH, " &cf00Zone #%2d&cfff:\n", i); } first = false; } G_sprint(self, PRINT_HIGH, " %3d: %s\n", markers[j]->fb.index + 1, markers[j]->classname); } } } } static void FrogbotGoalInfo(void) { gedict_t *marker = self->fb.touch_marker; int g; if (marker == NULL) { return; } G_sprint(self, PRINT_HIGH, "Goals for marker #%d (%s)\n", marker->fb.index + 1, marker->classname); for (g = 0; g < NUMBER_GOALS; ++g) { gedict_t *next = marker->fb.goals[g].next_marker; if (next && (next != world) && (next != dropper)) { G_sprint(self, PRINT_HIGH, "%2d: time %3.1f: marker %3d: %s\n", g + 1, marker->fb.goals[g].time, next->fb.index + 1, next->classname); } } } // Format: botcmd rjfields static void FrogbotSetRocketJumpFields(void) { gedict_t *nearest = LocateMarker(self->s.v.origin); int source_to_target_path = FindPathIndex(saved_marker, nearest); char param[64]; if (nearest == NULL) { G_sprint(self, PRINT_HIGH, "No marker nearby\n"); return; } if (source_to_target_path < 0) { G_sprint(self, PRINT_HIGH, "No linked path found\n"); return; } if (!(saved_marker->fb.paths[source_to_target_path].flags & ROCKET_JUMP)) { G_sprint(self, PRINT_HIGH, "Path is not flagged as a RJ\n"); return; } if (trap_CmdArgc() == 2) { fb_path_t *path = &saved_marker->fb.paths[source_to_target_path]; G_sprint(self, PRINT_HIGH, "Current fields: pitch %3.1f, yaw %3.1f, delay %d\n", path->rj_pitch, path->rj_yaw, path->rj_delay); return; } if (trap_CmdArgc() < 5) { G_sprint(self, PRINT_HIGH, "Parameters: \n"); return; } trap_CmdArgv(2, param, sizeof(param)); saved_marker->fb.paths[source_to_target_path].rj_pitch = atof(param); trap_CmdArgv(3, param, sizeof(param)); saved_marker->fb.paths[source_to_target_path].rj_yaw = atof(param); trap_CmdArgv(4, param, sizeof(param)); saved_marker->fb.paths[source_to_target_path].rj_delay = atoi(param); G_sprint(self, PRINT_HIGH, "RJ parameters updated\n"); return; } static void FrogbotSetDeathHeight(void) { if (trap_CmdArgc() == 2) { if (MapDeathHeight() <= FB_MAPDEATHHEIGHT_DEFAULT) { G_sprint(self, PRINT_HIGH, "Death height: not set\n"); } else { G_sprint(self, PRINT_HIGH, "Death height: %d\n", MapDeathHeight()); G_sprint(self, PRINT_HIGH, " Specify 'deathheight clear' to clear\n"); } } else { char buffer[64]; trap_CmdArgv(2, buffer, sizeof(buffer)); if (streq(buffer, "clear")) { SetMapDeathHeight(FB_MAPDEATHHEIGHT_DEFAULT); } else if (atoi(buffer)) { SetMapDeathHeight(atoi(buffer)); } } } static void FrogbotSummary(void) { int marker_count = 0; int goal_count[NUMBER_GOALS] = { 0 }; int zone_count[NUMBER_ZONES] = { 0 }; int i, j; G_sprint(self, PRINT_HIGH, "Marker summary:\n"); for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i]) { int path_count = 0; ++marker_count; for (j = 0; j < NUMBER_PATHS; ++j) { if (markers[i]->fb.paths[j].next_marker) { ++path_count; } } if (path_count == 0) { G_sprint(self, PRINT_HIGH, " %3d: %s: no paths%s\n", markers[i]->fb.index + 1, markers[i]->classname, markers[i]->fb.Z_ ? "" : " and no zone"); } else if (!markers[i]->fb.Z_) { G_sprint(self, PRINT_HIGH, " %3d: %s: no zone\n", markers[i]->fb.index + 1, markers[i]->classname); } if (markers[i]->fb.G_) { ++goal_count[markers[i]->fb.G_ - 1]; } if (markers[i]->fb.Z_) { ++zone_count[markers[i]->fb.Z_ - 1]; } } } G_sprint(self, PRINT_HIGH, " %d markers in total\n", marker_count); } static void FrogbotsDisable(void) { if (!match_in_progress) { cvar_fset(FB_CVAR_ENABLED, 0); GotoNextMap(); UserMode(-cvar("_k_last_xonx")); } } static void FrogbotsSetHealth(void) { if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } if (trap_CmdArgc() <= 2) { G_sprint(self, 2, "Usage: /botcmd health \n"); G_sprint(self, 2, " must be in range %d and %d\n", 1, 300); G_sprint(self, 2, "health is currently \"%d\"\n", FrogbotHealth()); } else { char argument[32]; int new_health = 0; int old_health = FrogbotHealth(); trap_CmdArgv(2, argument, sizeof(argument)); new_health = bound(1, atoi(argument), 300); if (new_health != old_health) { cvar_fset(FB_CVAR_HEALTH, new_health); G_sprint(self, 2, "health changed to \"%d\"\n", new_health); } } } static void FrogbotsSetWeapon(void) { if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } if (trap_CmdArgc() <= 2) { G_sprint(self, 2, "Usage: /botcmd weapon \n"); G_sprint(self, 2, " must be in range %d and %d\n", 2, 8); G_sprint(self, 2, "weapon is currently \"%d\"\n", FrogbotWeapon()); } else { char argument[32]; int new_weapon = 0; int old_weapon = FrogbotWeapon(); trap_CmdArgv(2, argument, sizeof(argument)); new_weapon = bound(2, atoi(argument), 8); if (new_weapon != old_weapon) { cvar_fset(FB_CVAR_WEAPON, new_weapon); G_sprint(self, 2, "weapon changed to \"%d\"\n", new_weapon); } } } static void FrogbotsSetBreakOnDeath(void) { if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } cvar_fset(FB_CVAR_BREAK_ON_DEATH, !cvar(FB_CVAR_BREAK_ON_DEATH)); G_sprint(self, 2, "break on death changed to \"%s\"\n", (int)cvar(FB_CVAR_BREAK_ON_DEATH) ? "on" : "off"); } static void FrogbotsToggleQuad(void) { if ((int)self->s.v.items & IT_QUAD) { self->s.v.items = (int)self->s.v.items & ~IT_QUAD; self->super_time = 0; self->super_damage_finished = 0; } else { self->s.v.items = (int)self->s.v.items | IT_QUAD; self->super_time = 1; self->super_damage_finished = g_globalvars.time + 3600 * 20; } } static void FrogbotsSetQuadMultiplier(void) { if (!bots_enabled()) { G_sprint(self, 2, "Bots are disabled by the server.\n"); return; } if (trap_CmdArgc() <= 2) { G_sprint(self, 2, "Usage: /botcmd quadmultiplier \n"); G_sprint(self, 2, " must be in range %d and %d\n", 1, 10); G_sprint(self, 2, "multiplier is currently \"%d\"\n", FrogbotQuadMultiplier()); } else { char argument[32]; int new_multiplier = 0; int old_multiplier = FrogbotQuadMultiplier(); trap_CmdArgv(2, argument, sizeof(argument)); new_multiplier = bound(1, atoi(argument), 10); if (new_multiplier != old_multiplier) { cvar_fset(FB_CVAR_QUAD_MULTIPLIER, new_multiplier); G_sprint(self, 2, "quad multiplier changed to \"%d\"\n", new_multiplier); } } } typedef struct frogbot_cmd_s { char *name; void (*func)(void); char *description; } frogbot_cmd_t; static frogbot_cmd_t std_commands[] = { { "skill", FrogbotsSetSkill, "Set skill level for next bot added" }, { "addbot", FrogbotsAddbot_f, "Adds a bot. Skill & team optional" }, { "fill", FrogbotsFillServer, "Fills the server (max 8 bots at a time)" }, { "removebot", FrogbotsRemovebot_f, "Removes a single bot" }, { "removeall", FrogbotsRemoveAll, "Removes all bots from server" }, { "debug", FrogbotsDebug, "Debugging commands" }, { "disable", FrogbotsDisable, "Disable frogbots" }, { "health", FrogbotsSetHealth, "Set initial health for the bot" }, { "weapon", FrogbotsSetWeapon, "Set which weapon the bot should use" }, { "breakondeath", FrogbotsSetBreakOnDeath, "Automatically break when you die" }, { "togglequad", FrogbotsToggleQuad, "Toggle quad damage" }, { "quadmultiplier", FrogbotsSetQuadMultiplier, "Set quad damage multiplier" }}; static frogbot_cmd_t editor_commands[] = { { "addmarker", FrogbotAddMarker, "Adds a routing marker to the map" }, { "removemarker", FrogbotRemoveMarker, "Removes a routing marker from the map" }, { "savemarker", FrogbotSaveMarker, "Saves current marker" }, { "addpath", FrogbotAddPath, "Adds a path between markers" }, { "removepath", FrogbotRemovePath, "Removes a path between markers" }, { "removeallpaths", FrogbotRemoveAllPaths, "Removes all paths from this marker" }, { "setzone", FrogbotSetZone, "Sets a marker's zone #" }, { "setmarkerflag", FrogbotSetMarkerFlag, "Flags a single marker" }, { "clearmarkerflag", FrogbotClearMarkerFlag, "Clears flag on a path between two markers" }, { "setpathflag", FrogbotSetPathFlag, "Flags a path between two markers" }, { "clearpathflag", FrogbotClearPathFlag, "Clears flag on a path between two markers" }, { "save", FrogbotSaveBotFile, "Saves current routing as a .bot file" }, { "info", FrogbotShowInfo, "Shows information about the current marker" }, { "pathinfo", FrogbotPathList, "Shows information abouts paths to/from current marker" }, { "summary", FrogbotSummary, "Shows summary of current map" }, { "goalsummary", FrogbotGoalSummary, "Show summary of goals" }, { "zonesummary", FrogbotZoneSummary, "Show summary of zones" }, { "mapinfo", FrogbotMapInfo, "Shows information about current map" }, { "goalinfo", FrogbotGoalInfo, "Shows goal information for current marker" }, { "goto", FrogbotGoto, "Teleport to a marker #" }, { "move", FrogbotMoveMarker, "Moves marker to current position" }, { "anglehint", FrogbotSetAngleHint, "Sets angle hint for bot path" }, { "deathheight", FrogbotSetDeathHeight, "Sets the auto-death level for this map" }, { "rjfields", FrogbotSetRocketJumpFields, "Sets rocket jump fields" }, { "pathlist", FrogbotListPaths, "Lists paths with flags set" } }; #define NUM_EDITOR_COMMANDS (sizeof (editor_commands) / sizeof (editor_commands[0])) #define NUM_STANDARD_COMMANDS (sizeof (std_commands) / sizeof (std_commands[0])) static void PrintAvailableCommands(frogbot_cmd_t *commands, int num_commands) { int i; int max_length = 0; char dots[64]; G_sprint(self, PRINT_HIGH, "Available commands:\n"); for (i = 0; i < num_commands; ++i) { max_length = max(max_length, strlen(commands[i].name)); } for (i = 0; i < num_commands; ++i) { make_dots(dots, sizeof(dots), max_length, commands[i].name); G_sprint(self, PRINT_HIGH, " &cff0%s&cfff %s %s\n", commands[i].name, dots, commands[i].description); } } void FrogbotsCommand(void) { frogbot_cmd_t *commands = FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE) ? editor_commands : std_commands; int num_commands = FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE) ? NUM_EDITOR_COMMANDS : NUM_STANDARD_COMMANDS; char command[64]; int i; float admin_rules = cvar(FB_CVAR_ADMIN_ONLY); if ((admin_rules == 2) && !is_real_adm(self)) { G_sprint(self, PRINT_HIGH, "You must be a server admin to use this command\n"); return; } else if (admin_rules && !is_adm(self)) { G_sprint(self, PRINT_HIGH, "You must be an admin to use this command\n"); return; } if (!bots_enabled()) { trap_CmdArgv(1, command, sizeof(command)); if ((trap_CmdArgc() > 1) && streq(command, "enable")) { if (match_in_progress) { G_sprint(self, PRINT_HIGH, "Cannot enable bots while match in progress\n"); return; } if (isRACE()) { G_sprint(self, PRINT_HIGH, "Cannot enable bots while in race mode\n"); return; } if (isCTF()) { G_sprint(self, PRINT_HIGH, "Cannot enable bots while in CTF mode\n"); return; } cvar_fset(FB_CVAR_ENABLED, 1); GotoNextMap(); UserMode(-cvar("_k_last_xonx")); return; } G_sprint(self, PRINT_HIGH, "Bots not enabled: to turn on, %s\n", redtext("/botcmd enable")); return; } if (trap_CmdArgc() <= 1) { PrintAvailableCommands(commands, num_commands); return; } trap_CmdArgv(1, command, sizeof(command)); if (!FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE) && !streq(command, "disable") && !FrogbotsCheckMapSupport()) { G_sprint(self, PRINT_HIGH, "Bots not supported on this map.\n"); return; } for (i = 0; i < num_commands; ++i) { if (streq(commands[i].name, command)) { commands[i].func(); return; } } G_sprint(self, 2, "Command not known.\n"); PrintAvailableCommands(commands, num_commands); } void Bot_Print_Thinking(void) { // Spectator is watching a bot - display bot's thinking qbool isSpectator = self->ct == ctSpec && self->s.v.goalentity; gedict_t *bot = self->isBot ? self : isSpectator ? PROG_TO_EDICT(self->s.v.goalentity) : bots[0].entity ? &g_edicts[bots[0].entity] : self; gedict_t *linked = bot->fb.linked_marker; gedict_t *oldlink = bot->fb.old_linked_marker; char data[1024] = { 0 }; if (g_globalvars.time < self->fb.last_spec_cp) { return; } if (FrogbotOptionEnabled(FB_OPTION_SHOW_ROUTING_LOGIC)) { gedict_t *goal = bot->s.v.goalentity ? &g_edicts[bot->s.v.goalentity] : NULL; strlcat(data, "\n", sizeof(data)); strlcat(data, va(" %s: %s (%d)\n", redtext("Touch"), bot->fb.touch_marker ? bot->fb.touch_marker->classname : "(none)", bot->fb.touch_marker ? bot->fb.touch_marker->fb.index + 1 : -1), sizeof(data)); strlcat(data, va(" %s: %s\n", redtext("Looking"), bot->fb.look_object ? bot->fb.look_object->classname : "(nothing)"), sizeof(data)); strlcat(data, va(" %s: %s (%d)\n", redtext("Linked"), linked ? linked->classname : "?", linked ? linked->fb.index + 1 : -1), sizeof(data)); strlcat(data, va(" %s: %s (%d)\n", redtext("OldLinked"), oldlink ? oldlink->classname : "?", oldlink ? oldlink->fb.index + 1 : -1), sizeof(data)); strlcat(data, va(" %s: %s\n", redtext("GoalEnt"), goal ? va("%s (%d) (%f)", goal->classname, goal->fb.index + 1, goal->fb.saved_goal_desire) : "(none)"), sizeof(data)); if (goal && !streq(goal->classname, "player")) { strlcat(data, va(" %s (touch %d)", goal->netname, goal->fb.touch_marker ? goal->fb.touch_marker->fb.index + 1 : -1), sizeof(data)); } } if (FrogbotOptionEnabled(FB_OPTION_SHOW_DUEL_LOGIC)) { strlcat(data, "\n", sizeof(data)); strlcat(data, va(" %s: armor %d, damage %d\n", redtext("Strength"), (int)bot->fb.total_armor, (int)bot->fb.total_damage), sizeof(data)); strlcat(data, va(" %s: RA %d YA %d GA %d\n", redtext("Desire"), (int)bot->fb.desire_armorInv, (int)bot->fb.desire_armor2, (int)bot->fb.desire_armor1), sizeof(data)); strlcat(data, va(" %s: LG %d RL %d\n", redtext("Desire"), (int)bot->fb.desire_lightning, (int)bot->fb.desire_rocketlauncher), sizeof(data)); if (bot->s.v.enemy) { gedict_t *enemy = &g_edicts[bot->s.v.enemy]; strlcat(data, va("\n%s: %s\n", redtext("Enemy"), enemy->netname), sizeof(data)); strlcat(data, va(" %s: armor %d, damage %d\n", redtext("Strength"), (int)enemy->fb.total_armor, (int)enemy->fb.total_damage), sizeof(data)); strlcat(data, va(" %s: RA %d YA %d GA %d\n", redtext("Desire"), (int)enemy->fb.desire_armorInv, (int)enemy->fb.desire_armor2, (int)bot->fb.desire_armor1), sizeof(data)); strlcat(data, va(" %s: LG %d RL %d\n", redtext("Desire"), (int)enemy->fb.desire_lightning, (int)enemy->fb.desire_rocketlauncher), sizeof(data)); } } if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { strlcat(data, "\n", sizeof(data)); strlcat(data, va(" %s: %4d %4d %4d\n", redtext("Velocity"), PASSINTVEC3(bot->s.v.velocity)), sizeof(data)); strlcat(data, va(" %s: %4d %4d %4d\n", redtext("Obstruction"), PASSSCALEDINTVEC3(bot->fb.obstruction_normal, 320)), sizeof(data)); strlcat(data, va(" %s: %4d %4d %4d\n", redtext("LastDirection"), PASSINTVEC3(bot->fb.last_cmd_direction)), sizeof(data)); } if (FrogbotOptionEnabled(FB_OPTION_SHOW_GOAL_LOGIC)) { int i; gedict_t *touch = bot->fb.touch_marker; if (touch && (touch != world) && (touch != dropper)) { strlcat(data, "\nGoals:\n", sizeof(data)); for (i = 0; i < NUMBER_GOALS; ++i) { gedict_t *goal = touch->fb.goals[i].next_marker; if (goal && goal != world && goal != dropper) { char *name = goal->classname; if (streq(name, "item_artifact_super_damage")) { name = "quad"; } else if (streq(name, "item_health") && ((int)goal->s.v.spawnflags & H_MEGA)) { name = "mega"; } if (!strncmp(name, "weapon_", sizeof("weapon_") - 1)) { name += sizeof("weapon_") - 1; } else if (!strncmp(name, "item_", sizeof("item_") - 1)) { name += sizeof("item_") - 1; } strlcat(data, va("%2d: %s (%3.1f) %d\n", i + 1, name, goal->fb.desire(bot, goal), (int)max(0, goal->fb.goal_respawn_time - g_globalvars.time)), sizeof(data)); } } } else { strlcat(data, "\nGoals: (no touch marker)\n", sizeof(data)); } } if (data[0]) { G_centerprint(self, "%s", data); } self->fb.last_spec_cp = g_globalvars.time + 0.2; } qbool TimeTrigger(float *next_time, float time_increment) { qbool triggered = (g_globalvars.time >= *next_time); if (triggered) { *next_time += time_increment; if (*next_time <= g_globalvars.time) *next_time = g_globalvars.time + time_increment; } return triggered; } static void BotInitialiseServer(void) { dropper = spawn(); setsize(dropper, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); dropper->fb.desire = goal_NULL; dropper->fb.virtual_goal = dropper; dropper->classname = "fb_dropper"; sv_accelerate = cvar("sv_accelerate"); sv_maxspeed = cvar("sv_maxspeed"); sv_maxstrafespeed = sv_maxspeed; sv_maxwaterspeed = sv_maxspeed * 0.7; half_sv_maxspeed = sv_maxspeed * 0.5; inv_sv_maxspeed = 1 / sv_maxspeed; } static float last_auto_client = 0; float last_frame_time = 0; void BotStartFrame(void) { static int bot_framecount = 0; int min_required_clients = cvar(FB_CVAR_AUTOADD_LIMIT); int max_required_clients = cvar(FB_CVAR_AUTOREMOVE_AT); int auto_delay = cvar(FB_CVAR_AUTO_DELAY); last_frame_time = g_globalvars.time; // disable feature if it has been mis-configured if (min_required_clients && max_required_clients && (min_required_clients > max_required_clients)) { min_required_clients = max_required_clients = 0; } ++bot_framecount; if (bot_framecount == 3) { BotInitialiseServer(); } else if (bot_framecount == 20) { LoadMap(); } else if (bot_framecount > 20) { int client_count = 0; int human_count = 0; int max_clients = cvar("maxclients"); gedict_t *lowest_scoring_bot = NULL; marker_time = TimeTrigger(&next_marker_time, 0.03); hazard_time = TimeTrigger(&next_hazard_time, 0.025); FrogbotPrePhysics1(); FrogbotPrePhysics2(); for (self = world; (self = find_plr(self));) { ++client_count; // Logic that gets called every frame for every frogbot if (self->isBot) { BotCanRocketJump(self); SelectWeapon(); BotsFireLogic(); if (FrogbotOptionEnabled(FB_OPTION_SHOW_THINKING)) { Bot_Print_Thinking(); } if (IsHazardFrame()) { gedict_t *p; // Set all players to non-solid so we can avoid hazards for (p = world; (p = find_plr(p));) { p->fb.oldsolid = p->s.v.solid; p->s.v.solid = SOLID_NOT; } AvoidHazards(self); // Re-instate client entity types for (p = world; (p = find_plr(p));) { p->s.v.solid = p->fb.oldsolid; } } BotSetCommand(self); if ((lowest_scoring_bot == NULL) || (self->s.v.frags < lowest_scoring_bot->s.v.frags)) { lowest_scoring_bot = self; } } else { ++human_count; if (FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { if (self->s.v.button2 && (self->fb.last_jump_frame == 0)) { self->fb.last_jump_frame = framecount; } else if (!self->s.v.button2 && ((int)self->s.v.flags & FL_ONGROUND)) { self->fb.last_jump_frame = 0; } if ((self->fb.last_jump_frame > 1) && self->s.v.button0) { float yaw = self->s.v.v_angle[YAW]; float pitch = self->s.v.v_angle[PITCH]; if (yaw < 1) { yaw += 360; } G_sprint(self, PRINT_HIGH, "Jumpflags: %d %d %d\n", (int)pitch, (int)yaw, framecount - self->fb.last_jump_frame); self->fb.last_jump_frame = 1; } } } } if (FrogbotsCheckMapSupport() && human_count && ((g_globalvars.time - last_auto_client) >= max(auto_delay, 1))) { if (min_required_clients && (client_count < min(min_required_clients, max_clients))) { FrogbotsAddbot(FrogbotSkillLevel(), "", false); last_auto_client = g_globalvars.time; } else if (max_required_clients && (client_count > max_required_clients) && lowest_scoring_bot) { FrogbotsRemoveBot(&bots[lowest_scoring_bot->fb.botnumber]); last_auto_client = g_globalvars.time; } } } } // This is stored in statistics files int BotVersionNumber(void) { return 1; } qbool FrogbotOptionEnabled(int option) { return (((int)cvar(FB_CVAR_OPTIONS)) & option); } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_items.c000066400000000000000000000561251475442401000173610ustar00rootroot00000000000000/* items.qc item functions Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2007 ParboiL */ #ifdef BOT_SUPPORT #include "g_local.h" // Goal functions void item_megahealth_rot(void); // If multiple items have the same goal, markers on the map will point to the closest // So (my logic) if you only care about the closest item rather than timing all items, // assign same goal to all objects. Statically assign goals for minor items and leave // other goal numbers free for items to be tracked across the whole map #define FB_FIRST_AUTOGOAL 15 #define FB_GOAL_GA 15 #define FB_GOAL_HEALTH 16 #define FB_GOAL_GL 17 #define FB_GOAL_ROCKETS 18 // These were set in the original FBCA #define FB_GOAL_CELLS 19 #define FB_GOAL_SNG 20 #define FB_GOAL_SSG 21 #define FB_GOAL_NG 22 #define FB_GOAL_SPIKES 23 #define FB_GOAL_SHELLS 24 // This automatically assigns default goal numbers void AssignGoalNumbers(void) { gedict_t *ent; int unassigned_goal = 1; for (ent = world; (ent = nextent(ent));) { switch (ent->tp_flags) { case it_ra: case it_ya: case it_rl: case it_lg: case it_mh: case it_quad: case it_pent: case it_suit: case it_ring: if (unassigned_goal < FB_FIRST_AUTOGOAL) { SetGoalForMarker(unassigned_goal, ent); ++unassigned_goal; } else { G_bprint(PRINT_HIGH, "Unable to assign goal to %s @ [%d %d %d]\n", ent->classname, PASSINTVEC3(ent->s.v.origin)); } break; case it_ga: SetGoalForMarker(FB_GOAL_GA, ent); break; case it_health: SetGoalForMarker(FB_GOAL_HEALTH, ent); break; case it_ng: SetGoalForMarker(FB_GOAL_NG, ent); break; case it_sng: SetGoalForMarker(FB_GOAL_SNG, ent); break; case it_gl: SetGoalForMarker(FB_GOAL_GL, ent); break; case it_shells: SetGoalForMarker(FB_GOAL_SHELLS, ent); break; case it_nails: SetGoalForMarker(FB_GOAL_SPIKES, ent); break; case it_rockets: SetGoalForMarker(FB_GOAL_ROCKETS, ent); break; case it_cells: SetGoalForMarker(FB_GOAL_CELLS, ent); break; } } } static void LocateDynamicItem(gedict_t *item) { vec3_t point; int content = trap_pointcontents(PASSVEC3(item->s.v.origin)); VectorAdd(item->s.v.absmin, item->s.v.view_ofs, point); item->fb.touch_marker = LocateMarker(point); if (item->fb.touch_marker) { if ((item->fb.touch_marker->fb.T & UNREACHABLE) || (content == CONTENT_LAVA)) { item->fb.touch_marker = NULL; } } if (item->fb.touch_marker) { item->fb.Z_ = item->fb.touch_marker->fb.Z_; } } static float goal_health0(gedict_t *self, gedict_t *other) { return self->fb.desire_health0; } static float goal_health2(gedict_t *self, gedict_t *other) { return self->fb.desire_mega_health; } float goal_NULL(gedict_t *self, gedict_t *other) { return 0; } static float goal_armor1(gedict_t *self, gedict_t *other) { return self->fb.desire_armor1; } static float goal_armor2(gedict_t *self, gedict_t *other) { if (self->fb.desire_armor2) { return (self->fb.desire_armor2 + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_armor2 : 0)); } else { qbool low_armor = (qbool)(self->fb.total_armor <= 100 && self->s.v.health >= 50); qbool has_rl = (qbool)(((int)self->s.v.items & IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets); qbool has_quad = (qbool)(self->super_damage_finished <= g_globalvars.time); if (low_armor && has_rl && has_quad) { return (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_armor2 : 0); } return 0; } } static float goal_armorInv(gedict_t *self, gedict_t *other) { if (self->fb.desire_armorInv) { return (self->fb.desire_armorInv + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_armorInv : 0)); } else { qbool has_rl = (qbool)(((int)self->s.v.items & IT_ROCKET_LAUNCHER) && (self->s.v.ammo_rockets)); qbool has_quad = (qbool)(self->super_damage_finished <= g_globalvars.time); qbool ok_health = (qbool)(self->s.v.health >= 50); if (has_rl && has_quad && ok_health) { return (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_armorInv : 0); } return 0; } } static float goal_supershotgun1(gedict_t *self, gedict_t *other) { return (self->fb.desire_supershotgun + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_supershotgun * 0.5 : 0)); } static float goal_supershotgun2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_SUPER_SHOTGUN)) { return 0; } return goal_supershotgun1(self, other); } static float goal_nailgun1(gedict_t *self, gedict_t *other) { return (self->fb.desire_nailgun + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_nailgun * 0.5 : 0)); } static float goal_nailgun2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_NAILGUN)) { return 0; } return goal_nailgun1(self, other); } static float goal_supernailgun1(gedict_t *self, gedict_t *other) { return (self->fb.desire_supernailgun + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_supernailgun * 0.5 : 0)); } static float goal_supernailgun2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_SUPER_NAILGUN)) { return 0; } return goal_supernailgun1(self, other); } static float goal_grenadelauncher1(gedict_t *self, gedict_t *other) { return (self->fb.desire_grenadelauncher + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_grenadelauncher * 0.5 : 0)); } static float goal_grenadelauncher2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_GRENADE_LAUNCHER)) { return 0; } return goal_grenadelauncher1(self, other); } static float goal_rocketlauncher1(gedict_t *self, gedict_t *other) { return (self->fb.desire_rocketlauncher + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_rocketlauncher : 0)); } static float goal_rocketlauncher2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_ROCKET_LAUNCHER)) { return 0; } return goal_rocketlauncher1(self, other); } static float goal_lightning1(gedict_t *self, gedict_t *other) { return (self->fb.desire_lightning + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_lightning * 0.5 : 0)); } static float goal_lightning2(gedict_t *self, gedict_t *other) { if ((deathmatch != 1) && ((int)self->s.v.items & IT_LIGHTNING)) { return 0; } return goal_lightning1(self, other); } static float goal_shells(gedict_t *self, gedict_t *other) { if (self->s.v.ammo_shells < 100) { return self->fb.desire_shells; } return 0; } static float goal_spikes(gedict_t *self, gedict_t *other) { if (self->s.v.ammo_nails < 200) { return self->fb.desire_nails; } return 0; } static float goal_rockets(gedict_t *self, gedict_t *other) { if (self->s.v.ammo_rockets < 100) { return (self->fb.desire_rockets + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_rockets : 0)); } return 0; } static float goal_cells(gedict_t *self, gedict_t *other) { if (self->s.v.ammo_cells < 100) { return (self->fb.desire_cells + (self->fb.virtual_enemy ? self->fb.virtual_enemy->fb.desire_cells * 0.5 : 0)); } return 0; } static float goal_artifact_invulnerability(gedict_t *self, gedict_t *other) { if (Get_Powerups()) { return (200 + self->fb.total_damage); } return 0; } static float goal_artifact_invisibility(gedict_t *self, gedict_t *other) { if (Get_Powerups()) { return (200 + self->fb.total_damage); } return 0; } static float goal_artifact_super_damage(gedict_t *self, gedict_t *other) { if (Get_Powerups()) { return (200 + self->fb.total_damage); } return 0; } // Pickup functions (TODO) qbool pickup_health0(void) { return (qbool)(self->s.v.health < 100); } qbool pickup_health2(void) { return (qbool)(self->s.v.health < 250); } qbool pickup_armor1(void) { return (qbool)(self->fb.total_armor < 30); } qbool pickup_armor2(void) { return (qbool)(self->fb.total_armor < 90); } qbool pickup_armorInv(void) { return (qbool)(self->fb.total_armor < 160); } qbool pickup_supershotgun2(void) { return (qbool) !((int)self->s.v.items & IT_SUPER_SHOTGUN); } qbool pickup_true(void) { return true; } qbool pickup_nailgun2(void) { return ((deathmatch == 1) || (qbool) !((int)self->s.v.items & IT_NAILGUN)); } qbool pickup_supernailgun2(void) { return ((deathmatch == 1) || (qbool) !((int)self->s.v.items & IT_SUPER_NAILGUN)); } qbool pickup_grenadelauncher2(void) { return ((deathmatch == 1) || (qbool) !((int)self->s.v.items & IT_GRENADE_LAUNCHER)); } qbool pickup_rocketlauncher2(void) { return ((deathmatch == 1) || (qbool) !((int)self->s.v.items & IT_ROCKET_LAUNCHER)); } qbool pickup_lightning2(void) { return ((deathmatch == 1) || (qbool) !((int)self->s.v.items & IT_LIGHTNING)); } qbool pickup_shells(void) { return (qbool)(self->s.v.ammo_shells < 100); } qbool pickup_spikes(void) { return (qbool)(self->s.v.ammo_nails < 200); } qbool pickup_rockets(void) { return (qbool)(self->s.v.ammo_rockets < 100); } qbool pickup_cells(void) { return (qbool)(self->s.v.ammo_cells < 100); } void StartItemFB(gedict_t *ent) { AddToQue(ent); VectorSet(ent->s.v.view_ofs, 80, 80, 24); if (!ent->touch) { ent->touch = (func_t) marker_touch; ent->s.v.nextthink = -1; } ent->fb.goal_respawn_time = g_globalvars.time; ent->s.v.solid = SOLID_TRIGGER; } static void BotTookMessage(gedict_t *item, gedict_t *player) { if (player->isBot && teamplay) { TeamplayMessageByName(player, "took"); } } static void BotDroppedMessage(gedict_t *item, gedict_t *player) { } // // Health static void fb_health_taken(gedict_t *item, gedict_t *player) { if ((int)item->s.v.spawnflags & H_MEGA) { BotTookMessage(item, player); item->fb.goal_respawn_time = g_globalvars.time + 5 + max(player->s.v.health - 100, 0); } else { item->fb.goal_respawn_time = item->s.v.nextthink; } AssignVirtualGoal(item); FrogbotSetHealthArmour(player); UpdateGoalEntity(item, player); item->s.v.solid = SOLID_TRIGGER; } static qbool fb_health_touch(gedict_t *item, gedict_t *player) { if (player->ct != ctPlayer) { return true; } if (IsMarkerFrame()) { check_marker(item, player); } if (WaitingToRespawn(item) || (self->think == (func_t)item_megahealth_rot)) { return true; } if (NoItemTouch(item, player)) { return true; } return false; } static void fb_health_rot(gedict_t *item, gedict_t *player) { FrogbotSetHealthArmour(player); if (player->s.v.health <= player->s.v.max_health) { item->fb.goal_respawn_time = item->s.v.nextthink; AssignVirtualGoal(item); } } static void fb_spawn_health(gedict_t *ent) { if ((int)ent->s.v.spawnflags & H_MEGA) { ent->fb.desire = goal_health2; ent->fb.pickup = pickup_health2; ent->fb.item_affect = fb_health_rot; } else { ent->fb.desire = goal_health0; ent->fb.pickup = pickup_health0; } ent->fb.item_taken = fb_health_taken; ent->fb.item_touch = fb_health_touch; ent->fb.item_respawned = AssignVirtualGoal; StartItemFB(ent); } // // Armor static void fb_armor_taken(gedict_t *item, gedict_t *player) { item->fb.goal_respawn_time = item->s.v.nextthink; AssignVirtualGoal(item); FrogbotSetHealthArmour(player); UpdateGoalEntity(item, player); BotTookMessage(item, player); item->s.v.solid = SOLID_TRIGGER; } static qbool fb_armor_touch(gedict_t *item, gedict_t *player) { if (IsMarkerFrame()) { check_marker(item, player); } if (WaitingToRespawn(item)) { return true; } // allow the bot to hurt themselves to pickup armor if (player->isBot && player->s.v.takedamage) { qbool have_more_armor = player->fb.total_armor >= item->fb.total_armor; qbool want_armor = player->s.v.goalentity == NUM_FOR_EDICT(item); qbool has_rl = ((int)player->s.v.items & IT_ROCKET_LAUNCHER) && player->s.v.ammo_rockets > 0; qbool targetting_player = player->fb.look_object && player->fb.look_object->ct == ctPlayer; if (want_armor && have_more_armor && has_rl && IsMarkerFrame() && !targetting_player && !player->fb.firing) { player->fb.state |= HURT_SELF; SetLinkedMarker(player, item, "fb_armor_touch"); player->fb.path_state = 0; player->fb.linked_marker_time = g_globalvars.time + 0.5f; player->fb.goal_refresh_time = g_globalvars.time + 2 + g_random(); //G_bprint (2, "Wait(HURT_SELF): %f vs %f armor\n", player->fb.total_armor, item->fb.total_armor); return true; // wait } } return NoItemTouch(item, player); } static void fb_spawn_armor(gedict_t *ent) { if (streq(ent->classname, "item_armor1")) { ent->fb.desire = goal_armor1; ent->fb.pickup = pickup_armor1; ent->fb.total_armor = (k_yawnmode ? 0.4 : 0.3) * 100.0f; } else if (streq(ent->classname, "item_armor2")) { ent->fb.desire = goal_armor2; ent->fb.pickup = pickup_armor2; ent->fb.total_armor = (k_yawnmode ? 0.6 : 0.6) * 150.0f; } else if (streq(ent->classname, "item_armorInv")) { ent->fb.desire = goal_armorInv; ent->fb.pickup = pickup_armorInv; ent->fb.total_armor = (k_yawnmode ? 0.8 : 0.8) * 200.0f; } ent->fb.item_taken = fb_armor_taken; ent->fb.item_touch = fb_armor_touch; ent->fb.item_respawned = AssignVirtualGoal; StartItemFB(ent); } // // weapons static qbool fb_weapon_touch(gedict_t *item, gedict_t *player) { if (player->ct != ctPlayer) { return true; } if (IsMarkerFrame()) { check_marker(item, player); } if (WaitingToRespawn(item)) { return true; } if (NoItemTouch(item, player)) { return true; } return false; } static void fb_weapon_taken(gedict_t *item, gedict_t *player) { player->fb.weapon_refresh_time = 0; switch ((int)item->tp_flags) { case it_rl: case it_lg: case it_gl: BotTookMessage(item, player); break; } if ((deathmatch == 2) || (deathmatch == 3) || (deathmatch == 5) || coop) { // Weapon left } else { UpdateGoalEntity(item, player); item->fb.goal_respawn_time = item->s.v.nextthink; AssignVirtualGoal(item); item->s.v.solid = SOLID_TRIGGER; } } static void StartWeapon(gedict_t *ent) { ent->fb.item_taken = fb_weapon_taken; ent->fb.item_touch = fb_weapon_touch; ent->fb.item_respawned = AssignVirtualGoal; StartItemFB(ent); } static void fb_spawn_ssg(gedict_t *ent) { SetGoalForMarker(FB_GOAL_SSG, ent); ent->fb.desire = goal_supershotgun2; ent->fb.pickup = pickup_supershotgun2; StartWeapon(ent); } static void fb_spawn_ng(gedict_t *ent) { SetGoalForMarker(FB_GOAL_NG, ent); ent->fb.desire = goal_nailgun2; ent->fb.pickup = pickup_nailgun2; StartWeapon(ent); } static void fb_spawn_sng(gedict_t *ent) { SetGoalForMarker(FB_GOAL_SNG, ent); ent->fb.desire = goal_supernailgun2; ent->fb.pickup = pickup_supernailgun2; StartWeapon(ent); } static void fb_spawn_gl(gedict_t *ent) { // no goal set for GL ent->fb.desire = goal_grenadelauncher2; ent->fb.pickup = pickup_grenadelauncher2; StartWeapon(ent); } static void fb_spawn_rl(gedict_t *ent) { // no goal set for RL ent->fb.desire = goal_rocketlauncher2; ent->fb.pickup = pickup_rocketlauncher2; StartWeapon(ent); } static void fb_spawn_lg(gedict_t *ent) { // no goal set for LG ent->fb.desire = goal_lightning2; ent->fb.pickup = pickup_lightning2; StartWeapon(ent); } static qbool fb_ammo_touch(gedict_t *item, gedict_t *player) { if (player->ct != ctPlayer) { return true; } if (IsMarkerFrame()) { check_marker(item, player); } if (WaitingToRespawn(item)) { return true; } if (NoItemTouch(item, player)) { return true; } return false; } static void fb_ammo_taken(gedict_t *item, gedict_t *player) { item->fb.goal_respawn_time = item->s.v.nextthink; UpdateGoalEntity(item, player); AssignVirtualGoal(item); item->s.v.solid = SOLID_TRIGGER; } static void StartAmmoFB(gedict_t *ent) { ent->fb.item_touch = fb_ammo_touch; ent->fb.item_taken = fb_ammo_taken; ent->fb.item_respawned = AssignVirtualGoal; StartItemFB(ent); } static void fb_spawn_shells(gedict_t *ent) { SetGoalForMarker(FB_GOAL_SHELLS, ent); ent->fb.desire = goal_shells; ent->fb.pickup = pickup_shells; StartAmmoFB(ent); } static void fb_spawn_spikes(gedict_t *ent) { SetGoalForMarker(FB_GOAL_SPIKES, ent); ent->fb.desire = goal_spikes; ent->fb.pickup = pickup_spikes; StartAmmoFB(ent); } static void fb_spawn_rockets(gedict_t *ent) { // no goal for rockets ent->fb.desire = goal_rockets; ent->fb.pickup = pickup_rockets; StartAmmoFB(ent); } static void fb_spawn_cells(gedict_t *ent) { SetGoalForMarker(FB_GOAL_CELLS, ent); ent->fb.desire = goal_cells; ent->fb.pickup = pickup_cells; StartAmmoFB(ent); } // Also defined in items.qc ... support for older maps #define WEAPON_SHOTGUN 1 #define WEAPON_ROCKET 2 #define WEAPON_SPIKES 4 #define WEAPON_BIG 8 static void fb_spawn_weapon(gedict_t *ent) { if ((int)ent->s.v.spawnflags & WEAPON_SHOTGUN) { fb_spawn_shells(ent); } else if ((int)ent->s.v.spawnflags & WEAPON_SPIKES) { fb_spawn_spikes(ent); } else if ((int)ent->s.v.spawnflags & WEAPON_ROCKET) { fb_spawn_rockets(ent); } } static qbool fb_powerup_touch(gedict_t *item, gedict_t *player) { if (player->ct != ctPlayer) { return true; } if (IsMarkerFrame()) { check_marker(item, player); } if (WaitingToRespawn(item)) { return true; } if (NoItemTouch(item, player)) { return true; } return false; } static void fb_powerup_taken(gedict_t *item, gedict_t *player) { UpdateGoalEntity(item, player); item->fb.goal_respawn_time = item->s.v.nextthink + AUTOTRACK_POWERUPS_PREDICT_TIME; AssignVirtualGoal(item); item->s.v.solid = SOLID_TRIGGER; player->fb.last_mm2_spot = 0; BotTookMessage(item, player); } static void fb_spawn_pent(gedict_t *ent) { ent->fb.desire = goal_artifact_invulnerability; ent->fb.pickup = pickup_true; ent->fb.item_taken = fb_powerup_taken; ent->fb.item_respawned = AssignVirtualGoal; if (ent->fb.fl_marker) { ent->fb.item_touch = fb_powerup_touch; StartItemFB(ent); } } static void fb_spawn_biosuit(gedict_t *ent) { ent->fb.desire = goal_NULL; // FIXME ent->fb.pickup = pickup_true; ent->fb.item_taken = fb_powerup_taken; ent->fb.item_respawned = AssignVirtualGoal; if (ent->fb.fl_marker) { ent->fb.item_touch = fb_powerup_touch; StartItemFB(ent); } } static void fb_spawn_ring(gedict_t *ent) { ent->fb.desire = goal_artifact_invisibility; ent->fb.pickup = pickup_true; ent->fb.item_taken = fb_powerup_taken; ent->fb.item_respawned = AssignVirtualGoal; if (ent->fb.fl_marker) { ent->fb.item_touch = fb_powerup_touch; StartItemFB(ent); } } static void fb_spawn_quad(gedict_t *ent) { ent->fb.desire = goal_artifact_super_damage; ent->fb.pickup = pickup_true; ent->fb.item_taken = fb_powerup_taken; ent->fb.item_respawned = AssignVirtualGoal; if (ent->fb.fl_marker) { ent->fb.item_touch = fb_powerup_touch; if (!streq("aerowalk", mapname)) { StartItemFB(ent); } } } static fb_spawn_t itemSpawnFunctions[] = { { "item_armor1", fb_spawn_armor }, { "item_armor2", fb_spawn_armor }, { "item_armorInv", fb_spawn_armor }, { "item_artifact_invulnerability", fb_spawn_pent }, { "item_artifact_envirosuit", fb_spawn_biosuit }, { "item_artifact_invisibility", fb_spawn_ring }, { "item_artifact_super_damage", fb_spawn_quad }, { "item_cells", fb_spawn_cells }, { "item_health", fb_spawn_health }, { "item_rockets", fb_spawn_rockets }, { "item_shells", fb_spawn_shells }, { "item_spikes", fb_spawn_spikes }, { "item_weapon", fb_spawn_weapon }, { "weapon_supershotgun", fb_spawn_ssg }, { "weapon_nailgun", fb_spawn_ng }, { "weapon_supernailgun", fb_spawn_sng }, { "weapon_grenadelauncher", fb_spawn_gl }, { "weapon_rocketlauncher", fb_spawn_rl }, { "weapon_lightning", fb_spawn_lg }, }; fb_spawn_t* ItemSpawnFunction(int i) { return &itemSpawnFunctions[i]; } int ItemSpawnFunctionCount(void) { return (sizeof(itemSpawnFunctions) / sizeof(itemSpawnFunctions[0])); } qbool NoItemTouch(gedict_t *self, gedict_t *other) { //G_bprint (2, "NoItemTouch(%f,%f,%f) = [%f,%f,%f] > [%f,%f,%f]\n", PASSVEC3 (other->s.v.origin), PASSVEC3 (self->fb.virtual_mins), PASSVEC3 (self->fb.virtual_maxs)); if ((other->s.v.origin[0] <= self->fb.virtual_maxs[0]) && (other->s.v.origin[1] <= self->fb.virtual_maxs[1]) && (other->s.v.origin[2] <= self->fb.virtual_maxs[2])) { if ((other->s.v.origin[0] >= self->fb.virtual_mins[0]) && (other->s.v.origin[1] >= self->fb.virtual_mins[1]) && (other->s.v.origin[2] >= self->fb.virtual_mins[2])) { if (other->s.v.goalentity == NUM_FOR_EDICT(self)) { other->fb.goal_refresh_time = 0; } return false; } } return true; } static void BackpackTimedOut(void) { SUB_Remove(); } static float goal_health_backpack(gedict_t *self, gedict_t *pack) { if (self->invincible_time > g_globalvars.time) { return 0; } if (self->super_damage_finished > g_globalvars.time) { return 0; } return 20; } static qbool fb_backpack_touch(gedict_t *item, gedict_t *player) { if (player->s.v.goalentity == NUM_FOR_EDICT(item)) { player->fb.goal_refresh_time = 0; } return false; } static void fb_backpack_taken(gedict_t *item, gedict_t *player) { player->fb.weapon_refresh_time = 0; UpdateGoalEntity(item, player); player->fb.old_linked_marker = NULL; SetLinkedMarker(player, LocateMarker(player->s.v.origin), "bp taken"); player->fb.linked_marker_time = g_globalvars.time + 5; if ((int)item->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) { BotTookMessage(item, player); } } void BotsBackpackTouchedNonPlayer(gedict_t *pack, gedict_t *touch_ent) { LocateDynamicItem(pack); } void BotsBackpackDropped(gedict_t *self, gedict_t *pack) { pack->think = (func_t) BackpackTimedOut; pack->fb.goal_respawn_time = g_globalvars.time; if ((int)pack->s.v.items & IT_SUPER_SHOTGUN) { pack->fb.desire = goal_supershotgun1; } else if ((int)pack->s.v.items & IT_NAILGUN) { pack->fb.desire = goal_nailgun1; } else if ((int)pack->s.v.items & IT_SUPER_NAILGUN) { pack->fb.desire = goal_supernailgun1; } else if ((int)pack->s.v.items & IT_GRENADE_LAUNCHER) { pack->fb.desire = goal_grenadelauncher1; } else if ((int)pack->s.v.items & IT_ROCKET_LAUNCHER) { pack->fb.desire = goal_rocketlauncher1; } else if ((int)pack->s.v.items & IT_LIGHTNING) { pack->fb.desire = goal_lightning1; } else if (pack->s.v.ammo_cells > (pack->s.v.ammo_rockets * 5)) { pack->fb.desire = goal_cells; } else if (pack->s.v.ammo_rockets) { pack->fb.desire = goal_rockets; } else if (pack->s.v.ammo_nails >= 50) { pack->fb.desire = goal_spikes; } else { pack->fb.desire = goal_shells; } if (deathmatch == 4) { pack->fb.desire = goal_health_backpack; } pack->fb.item_touch = fb_backpack_touch; pack->fb.item_taken = fb_backpack_taken; if (!(self->fb.state & BACKPACK_IS_UNREACHABLE)) { LocateDynamicItem(pack); BotDroppedMessage(self, pack); } } void BotsPowerupDropped(gedict_t *player, gedict_t *powerup) { if (powerup->tp_flags & it_quad) { fb_spawn_quad(powerup); } else if (powerup->tp_flags & it_pent) { fb_spawn_pent(powerup); } else if (powerup->tp_flags & it_ring) { fb_spawn_ring(powerup); } else { return; } LocateDynamicItem(powerup); AssignVirtualGoal(powerup); } void BotsPowerupTouchedNonPlayer(gedict_t *powerup, gedict_t *touch_ent) { LocateDynamicItem(powerup); } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_load.c000066400000000000000000000027561475442401000171600ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #include "g_local.h" #if 0 void a_think(void) { } void spawn_load(void) { load_position = dropper; while (load_position) { if (!load_position->s.v.think) { load_position->s.v.nextthink = 0.001; load_position->s.v.think = dropper->s.v.think; load_position->fb.next_load = current_load_position; current_load_position = load_position; } load_position = nextent(load_position); } while (total_entity_count < 400) { load_position = spawn(); load_position->s.v.classname = "load"; load_position->s.v.nextthink = 0.001; load_position->s.v.think = dropper->s.v.think; load_position->fb.next_load = current_load_position; current_load_position = load_position; ++total_entity_count; } } void set_load(void) { load_position = current_load_position; while (load_position) { load_position->s.v.think = dropper->s.v.think; load_position = load_position->fb.next_load; } } void remove_load(void) { gedict_t *marker_; time_start = g_globalvars.time; framecount_start = framecount; markers_loaded = true; /* while (current_load_position) { if (current_load_position->s.v.classname == "load") { trap_remove(NUM_FOR_EDICT(current_load_position)); } else { current_load_position->s.v.nextthink = 0; } current_load_position = current_load_position->fb.next_load; }*/ StartItems(); for (marker_ = first_item; marker_ && marker_ != world; marker_ = marker_->fb.next) { AssignVirtualGoal_apply(marker_); } } #endif QW-Group-ktx-d05d6ca/src/bot_loadmap.c000066400000000000000000000265201475442401000176510ustar00rootroot00000000000000/* loadmap.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" static qbool map_supported = false; void check_marker(gedict_t *self, gedict_t *other); qbool LoadBotRoutingFromFile(void); qbool pickup_true(void); int AddPath(gedict_t *marker, gedict_t *next_marker); void AssignGoalNumbers(void); // fixme: also in doors.c #define SECRET_OPEN_ONCE 1 // stays open typedef struct fb_mapping_s { char *name; fb_void_funcref_t func; } fb_mapping_t; fb_spawn_t* ItemSpawnFunction(int i); void InvalidMap(void) { G_sprint(self, 2, "This map does not have bot-support.\n"); } static void fb_spawn_button(gedict_t *ent) { AddToQue(ent); if (ent->s.v.health) { //Add_takedamage(ent); } else { BecomeMarker(ent); adjust_view_ofs_z(ent); } } static void fb_spawn_spawnpoint(gedict_t *ent) { AddToQue(ent); ent->s.v.solid = SOLID_TRIGGER; ent->touch = (func_t) marker_touch; ent->s.v.flags = FL_ITEM; BecomeMarker(ent); setsize(ent, -65, -65, -24, 65, 65, 32); SetVector(ent->s.v.view_ofs, 80, 80, 24); ent->fb.pickup = pickup_true; adjust_view_ofs_z(ent); } static void fb_spawn_door(gedict_t *ent) { gedict_t *original = ent; vec3_t position; VectorScale(original->s.v.mins, 0.5, position); VectorMA(position, 0.5, original->s.v.maxs, position); position[2] = min(original->s.v.mins[2], original->s.v.maxs[2]) + 24; ent = CreateMarker(PASSVEC3(position)); ent->classname = "door_marker"; ent->fb.door_entity = original; ent->s.v.solid = SOLID_NOT; // this will be set to SOLID_TRIGGER if MARKER_DOOR_TOUCHABLE flag set if (ent->fb.wait < 0) { // TODO: ? return; } else if ((int)ent->s.v.spawnflags & SECRET_OPEN_ONCE) { // TODO: ? return; } else { if (ent->s.v.health) { //Add_takedamage(ent); } adjust_view_ofs_z(ent); //BecomeMarker(ent); } } static void fb_spawn_plat(gedict_t *ent) { AddToQue(ent); VectorSubtract(ent->s.v.absmax, ent->s.v.absmin, ent->s.v.view_ofs); VectorScale(ent->s.v.view_ofs, 0.5f, ent->s.v.view_ofs); ent->s.v.view_ofs[2] = ent->s.v.absmax[2] - ent->s.v.absmin[2] + 23; adjust_view_ofs_z(ent); BecomeMarker(ent); } static void fb_spawn_simple(gedict_t *ent) { AddToQue(ent); if (ent->fb.wait < 0) { // Remove... so ignore? return; } else { if (ent->s.v.health) { //Add_takedamage(ent); } } } static void fb_spawn_trigger_teleport(gedict_t *ent) { AddToQue(ent); //G_Printf ("fb_trigger_tele([%f %f %f] > [%f %f %f])\n", PASSVEC3 (ent->s.v.mins), PASSVEC3 (ent->s.v.maxs)); VectorSet(ent->fb.virtual_mins, ent->s.v.absmin[0] - 18, ent->s.v.absmin[1] - 18, ent->s.v.absmin[2] - 34); VectorSet(ent->fb.virtual_maxs, ent->s.v.absmax[0] + 18, ent->s.v.absmax[1] + 18, ent->s.v.absmax[2] + 26); //G_Printf("> virtual [%f %f %f] [%f %f %f]\n", PASSVEC3(ent->fb.virtual_mins), PASSVEC3(ent->fb.virtual_maxs)); setsize(ent, ent->s.v.mins[0] - 32, ent->s.v.mins[1] - 32, ent->s.v.mins[2], ent->s.v.maxs[0] + 32, ent->s.v.maxs[1] + 32, ent->s.v.maxs[2]); VectorSet(ent->s.v.view_ofs, 0.5 * (ent->s.v.absmax[0] - ent->s.v.absmin[0]), 0.5 * (ent->s.v.absmax[1] - ent->s.v.absmin[1]), 0.5 * (ent->s.v.absmax[2] - ent->s.v.absmin[2])); adjust_view_ofs_z(ent); BecomeMarker(ent); } static void fb_spawn_teleport_destination_touch(void) { if (IsMarkerFrame() && (other->ct == ctPlayer)) { check_marker(self, other); } } static void fb_spawn_teleport_destination(gedict_t *ent) { AddToQue(ent); ent->s.v.solid = SOLID_TRIGGER; ent->touch = (func_t) fb_spawn_teleport_destination_touch; ent->s.v.flags = FL_ITEM; BecomeMarker(ent); setsize(ent, -65, -65, -24 - 27, 65, 65, 32); // -27 extra to get back to floor VectorSet(ent->s.v.view_ofs, 80, 80, 24); ent->fb.pickup = pickup_true; adjust_view_ofs_z(ent); } static fb_spawn_t stdSpawnFunctions[] = { { "door", fb_spawn_door }, // covers func_door and func_door_secret { "func_button", fb_spawn_button }, { "info_player_deathmatch", fb_spawn_spawnpoint }, { "info_teleport_destination", fb_spawn_teleport_destination }, { "plat", fb_spawn_plat }, { "train", fb_spawn_simple }, { "trigger_changelevel", fb_spawn_simple }, { "trigger_counter", fb_spawn_simple }, { "trigger_hurt", fb_spawn_simple }, { "trigger_multiple", fb_spawn_simple }, { "trigger_once", fb_spawn_simple }, { "trigger_onlyregistered", fb_spawn_simple }, { "trigger_push", fb_spawn_simple }, { "trigger_secret", fb_spawn_simple }, { "trigger_setskill", fb_spawn_simple }, { "trigger_teleport", fb_spawn_trigger_teleport } }; void SetMarkerIndicatorPosition(gedict_t *item, gedict_t *indicator) { vec3_t pos; VectorAdd(item->s.v.absmin, item->s.v.absmax, pos); VectorScale(pos, 0.5f, pos); if (streq(item->classname, "plat")) { VectorAdd(item->s.v.mins, item->s.v.maxs, pos); VectorScale(pos, 0.5f, pos); } setorigin(indicator, PASSVEC3(pos)); } static void SpawnMarkerIndicator(gedict_t *item) { gedict_t *p; if (FrogbotShowMarkerIndicators()) { p = spawn(); p->s.v.flags = FL_ITEM; p->s.v.solid = SOLID_NOT; p->s.v.movetype = MOVETYPE_NONE; setmodel(p, "progs/w_g_key.mdl"); p->netname = "Marker"; p->classname = "marker_indicator"; p->fb.index = item->fb.index; SetMarkerIndicatorPosition(item, p); } } static qbool ProcessedItem(gedict_t *item) { return (item->fb.fl_marker || item->fb.index); } static void CreateItemMarkers(void) { // Old frogbot method was to call during item spawns, we just // catch up afterwards once we know the map is valid gedict_t *item; for (item = world; (item = nextent(item));) { int i = 0; qbool found = false; // Don't bother with search if it's already processed if (ProcessedItem(item)) { continue; } // check for item spawn for (i = 0; i < ItemSpawnFunctionCount(); ++i) { fb_spawn_t *spawn = ItemSpawnFunction(i); if (streq(spawn->name, item->classname)) { BecomeMarker(item); spawn->func(item); found = true; break; } } // check for std spawn (world items like buttons etc) if (!found) { for (i = 0; i < sizeof(stdSpawnFunctions) / sizeof(stdSpawnFunctions[0]); ++i) { if (streq(stdSpawnFunctions[i].name, item->classname)) { stdSpawnFunctions[i].func(item); found = true; break; } } } if (found && ProcessedItem(item)) { SpawnMarkerIndicator(item); } } } // After all markers have been created, re-process items static void AssignVirtualGoals(void) { gedict_t *item; for (item = world; (item = nextent(item));) { int i = 0; for (i = 0; i < ItemSpawnFunctionCount(); ++i) { fb_spawn_t *spawn = ItemSpawnFunction(i); if (streq(spawn->name, item->classname)) { AssignVirtualGoal_apply(item); break; } } } } // Item creation functions static void PlaceItemFB(gedict_t *ent) { vec3_t new_size = { 49, 49, 0 }; if (ent->fb.fixed_size[0]) { new_size[0] = ent->fb.fixed_size[0] / 2 - 15; } if (ent->fb.fixed_size[1]) { new_size[1] = ent->fb.fixed_size[1] / 2 - 15; } if (ent->fb.fixed_size[2]) { new_size[2] = ent->fb.fixed_size[2] / 2 - 0; } ent->s.v.movetype = MOVETYPE_NONE; setsize(ent, ent->s.v.mins[0] - new_size[0], ent->s.v.mins[1] - new_size[1], ent->s.v.mins[2], ent->s.v.maxs[0] + new_size[0], ent->s.v.maxs[1] + new_size[1], ent->s.v.maxs[2]); adjust_view_ofs_z(ent); VectorSet(ent->fb.virtual_mins, ent->s.v.absmin[0] + (new_size[0] - 49 + 32), ent->s.v.absmin[1] + (new_size[1] - 49 + 32), ent->s.v.absmin[2] - (new_size[2] - 0 + 33)); VectorSet(ent->fb.virtual_maxs, ent->fb.virtual_mins[0] + 96, ent->fb.virtual_mins[1] + 96, ent->fb.virtual_mins[2] + 114); } // KTX has in-built modifications to several maps - frogbot routing relies on entity order so we have // to customise again here. Called after all markers created, but before traveltime calculations static void CustomiseFrogbotMap(void) { gedict_t *ent = NULL; // KTX may have added a quad, so to keep routes compatible with PR1-version, we add it as a marker after others if (streq(mapname, "aerowalk") && !FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { gedict_t *quad = ez_find(world, "item_artifact_super_damage"); if (quad) { gedict_t *nearest_marker; quad->fb.fl_marker = false; nearest_marker = LocateMarker(quad->s.v.origin); quad->fb.fl_marker = true; StartItemFB(quad); quad->fb.T |= MARKER_DYNAMICALLY_ADDED; // Quad is in same zone as nearest marker, and linked by the first path that's valid SetZone(nearest_marker->fb.Z_, quad->fb.index + 1); SetGoalForMarker(18, quad); AddPath(nearest_marker, quad); AddPath(quad, nearest_marker); SpawnMarkerIndicator(quad); } } // We stopped it from removing the telespawn earlier on... if (!cvar("k_end_tele_spawn") && streq("end", mapname)) { vec3_t TS_ORIGIN = { -392, 608, 40 }; // tele spawn gedict_t *p = NULL; gedict_t *m = NULL; for (p = world; (p = find(p, FOFCLSN, "info_player_deathmatch"));) { if (VectorCompare(p->s.v.origin, TS_ORIGIN)) { p->classname = "info_player_deathmatch_removed"; // Remove any spawn marker for (m = world; (m = find(m, FOFCLSN, "spawnpoint"));) { if (m->k_lastspawn == p) { ent_remove(m); break; } } break; } } } // Expand bounding box of all items if (!isRACE()) { for (ent = world; (ent = nextent(ent));) { if (streq(ent->classname, "info_teleport_destination") || streq(ent->classname, "info_player_deathmatch")) { continue; } if (streq(ent->classname, "marker")) { vec3_t mins = { -65, -65, -24 }; vec3_t maxs = { 65, 65, 32 }; vec3_t viewoffset = { 80, 80, 24 }; int i; for (i = 0; i < 3; ++i) { if (ent->fb.fixed_size[i]) { mins[i] = -ent->fb.fixed_size[i] / 2 - (i < 2 ? 15 : 0); maxs[i] = ent->fb.fixed_size[i] / 2 - (i < 2 ? 15 : 0); viewoffset[i] = (maxs[i] - mins[i]) / 2; } } VectorCopy(viewoffset, ent->s.v.view_ofs); setsize(ent, PASSVEC3(mins), PASSVEC3(maxs)); } else if ((int)ent->s.v.flags & FL_ITEM) { PlaceItemFB(ent); } } } // Link all teleporters if (FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { for (ent = world; (ent = ez_find(ent, "trigger_teleport"));) { // If this teleport takes us to the marker close to the grenade, set arrow_time if (!strnull(ent->target)) { gedict_t *target = find(world, FOFS(targetname), ent->target); AddPath(ent, target); } } } } void LoadMap(void) { // Need to do this anyway, otherwise teleporters will be broken CreateItemMarkers(); if (!(isRACE() || isCTF()) && deathmatch) { // If we have a .bot file, use that if (LoadBotRoutingFromFile()) { map_supported = true; CustomiseFrogbotMap(); AssignVirtualGoals(); AllMarkersLoaded(); return; } } // At this point it's an unsupported map CustomiseFrogbotMap(); if (FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { gedict_t *e; // We don't want spawnpoint markers or powerups to mess with colours for (e = world; (e = nextent(e));) { e->s.v.effects = (int)e->s.v.effects & ~(EF_BLUE | EF_GREEN | EF_RED); } AssignGoalNumbers(); } } qbool FrogbotsCheckMapSupport(void) { if (!map_supported && self) { G_sprint(self, 2, "Map %s not supported for bots\n", mapname); } return map_supported; } void BecomeMarker(gedict_t *marker) { marker->fb.fl_marker = true; } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_match.c000066400000000000000000000047471475442401000173370ustar00rootroot00000000000000/* match.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 2000-2007 ParboiL */ // bot_match.c #ifdef BOT_SUPPORT #include "g_local.h" void button_use(void); void fd_secret_use(gedict_t *attacked, float take); void door_use(void); void door_killed(void); void multi_use(void); // Can also be called via "botcmd debug startmap" void BotsFireInitialTriggers(gedict_t *player) { gedict_t *old_self = self; extern gedict_t *markers[]; int i; other = activator = player; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *ent = markers[i]; if (!ent) { break; } if (!(ent->fb.T & MARKER_FIRE_ON_MATCH_START)) { continue; } if (ent && ent->fb.door_entity) { ent = ent->fb.door_entity; } if (streq(ent->classname, "func_button")) { self = ent; button_use(); } else if (streq(ent->classname, "trigger_once")) { self = ent; multi_use(); } else if (streq(ent->classname, "door")) { self = ent; if (ent->s.v.takedamage) { ((void (*)(void))(ent->th_pain))(); } else if (ent->use) { ((void (*)(void))(ent->use))(); } } } self = old_self; } // Assign bitmask to each player to indicate what team they are in // Called at match start and also when a client connects void BotsAssignTeamFlags(void) { gedict_t *p, *p2; int teamflag = 1; char *s = ""; if (!teamplay) { return; } // Clear teamflag from all items for (p = world; (p = nextent(p));) { p->fb.teamflag = 0; } for (p = world; (p = find_plr(p));) { p->k_flag = 0; } for (p = world; (p = find_plr(p));) { if (p->k_flag || strnull(s = getteam(p))) { continue; } p->k_flag = 1; p->fb.teamflag = teamflag; for (p2 = p; (p2 = find_plr(p2));) { if (streq(s, getteam(p2))) { p2->k_flag = 1; p2->fb.teamflag = teamflag; } } teamflag <<= 1; } } gedict_t* BotsFirstBot(void) { gedict_t *first_bot = NULL; gedict_t *ent; for (ent = world; (ent = find_plr(ent));) { if (ent->isBot) { first_bot = ent; break; } } return first_bot; } // Called by KTX as match begins void BotsMatchStart(void) { gedict_t *first_bot = BotsFirstBot(); gedict_t *ent; for (ent = world; (ent = find(ent, FOFCLSN, "marker_indicator"));) { ent_remove(ent); } for (ent = world; (ent = find(ent, FOFCLSN, "marker"));) { setmodel(ent, ""); } // No bots => perform no action, standard human match if (first_bot == NULL) { return; } BotsAssignTeamFlags(); BotsFireInitialTriggers(first_bot); } #endif QW-Group-ktx-d05d6ca/src/bot_movement.c000066400000000000000000000360461475442401000200720ustar00rootroot00000000000000#ifdef BOT_SUPPORT #include "g_local.h" #define ARROW_TIME_INCREASE 0.15 // Seconds to advance after NewVelocityForArrow #define MIN_DEAD_TIME 0.2f #define MAX_DEAD_TIME 1.0f //#define DEBUG_MOVEMENT void SetLinkedMarker(gedict_t *player, gedict_t *marker, char *explanation) { gedict_t *touch = player->fb.touch_marker; if ((marker != player->fb.linked_marker) && FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(player, 2, "linked to %3d/%s, touching %3d/%s g %s (%s)\n", marker ? marker->fb.index + 1 : -1, marker ? marker->classname : "(null)", touch ? touch->fb.index + 1 : -1, touch ? touch->classname : "(null)", g_edicts[player->s.v.goalentity].classname, explanation ? explanation : ""); } if (player->fb.debug_path) { G_bprint(2, "%3.2f: linked to %3d/%s, touching %3d/%s g %s (%s)\n", g_globalvars.time, marker ? marker->fb.index + 1 : -1, marker ? marker->classname : "(null)", touch ? touch->fb.index + 1 : -1, touch ? touch->classname : "(null)", g_edicts[player->s.v.goalentity].classname, explanation ? explanation : ""); } player->fb.linked_marker = marker; } void SetJumpFlag(gedict_t *player, qbool jumping, const char *explanation) { if (jumping != player->fb.jumping) { if (self->fb.debug_path) { G_bprint(PRINT_HIGH, "%3.2f: jumping (%s)\n", g_globalvars.time, explanation); } if (FrogbotOptionEnabled(FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint(player, PRINT_HIGH, "%3.2f: jumping (%s)\n", g_globalvars.time, explanation); } } player->fb.jumping = jumping; } void SetDirectionMove(gedict_t *self, vec3_t dir_move, const char *explanation) { VectorCopy(dir_move, self->fb.dir_move_); self->fb.dir_speed = VectorNormalize(self->fb.dir_move_); /* if (self->fb.debug_path) { G_bprint (PRINT_HIGH, "%3.2f: SetDirection(%4d %4d %4d): %s\n", g_globalvars.time, PASSSCALEDINTVEC3 (self->fb.dir_move_, 320), explanation); } if (FrogbotOptionEnabled (FB_OPTION_SHOW_MOVEMENT_LOGIC)) { G_sprint (self, PRINT_HIGH, "%3.2f: SetDirection(%4d %4d %4d): %s\n", g_globalvars.time, PASSSCALEDINTVEC3 (self->fb.dir_move_, 320), explanation); }*/ } void NewVelocityForArrow(gedict_t *self, vec3_t dir_move, const char *explanation) { SetDirectionMove(self, dir_move, explanation); self->fb.arrow_time = g_globalvars.time + ARROW_TIME_INCREASE; } static qbool BotRequestRespawn(gedict_t *self) { float time_dead = min(g_globalvars.time - self->fb.last_death, MAX_DEAD_TIME); return ((self->s.v.deadflag == DEAD_RESPAWNABLE) && (time_dead > MIN_DEAD_TIME) && (g_random() < (time_dead / MAX_DEAD_TIME))); } static void PM_Accelerate(vec3_t vel_after_friction, qbool onGround, vec3_t orig_wishdir, vec3_t vel_result, qbool trace) { float addspeed, accelspeed, currentspeed; float wishspeed = 320; // FIXME: assuming attemping sv_maxspeed float accel = 10; // FIXME: assumption vec3_t velocity; vec3_t wishdir; VectorCopy(vel_after_friction, velocity); if (onGround) { velocity[2] = 0; } wishdir[0] = orig_wishdir[0]; wishdir[1] = orig_wishdir[1]; wishdir[2] = 0; wishspeed = VectorNormalize(wishdir); wishspeed = sv_maxspeed; // fixme: we scale back up to maximum just as passing command currentspeed = DotProduct(velocity, wishdir); addspeed = wishspeed - currentspeed; if (addspeed <= 0) { VectorCopy(vel_after_friction, vel_result); #ifdef DEBUG_MOVEMENT if (trace) { G_bprint (PRINT_HIGH, "%3.2f,KTX,%4.1f,%4.1f,%4.1f,%4.1f,%4.1f,%4.1f,%3.2f,%3.2f,%3.2f,0,%4.1f,%4.1f,%4.1f\n", g_globalvars.time, PASSVEC3 (vel_after_friction), PASSVEC3 (wishdir), wishspeed, currentspeed, addspeed, PASSVEC3 (vel_result) ); } #endif return; } accelspeed = accel * g_globalvars.frametime * wishspeed; VectorMA(vel_after_friction, min(accelspeed, addspeed), wishdir, vel_result); #ifdef DEBUG_MOVEMENT if (trace) { G_bprint (PRINT_HIGH, "%3.2f,KTX,%4.1f,%4.1f,%4.1f,%4.1f,%4.1f,%4.1f,%3.2f,%3.2f,%3.2f,%3.2f,%4.1f,%4.1f,%4.1f\n", g_globalvars.time, PASSVEC3 (vel_after_friction), PASSVEC3 (wishdir), wishspeed, currentspeed, addspeed, accelspeed, PASSVEC3 (vel_result) ); } #endif } static void ApplyPhysics(gedict_t *self) { float drop = 0; vec3_t expected_velocity; float vel_length = 0; float hor_speed_squared; float movement_skill = bound(0, self->fb.skill.movement, 1.0); qbool onGround = (int)self->s.v.flags & FL_ONGROUND; // Just perform the move if we're backing away if (FUTURE(arrow_time2)) { return; } if ((deathmatch >= 4) && isDuel() && !self->fb.skill.wiggle_run_dmm4) { return; } // Step 1: Apply friction VectorCopy(self->s.v.velocity, expected_velocity); vel_length = VectorLength(expected_velocity); if (vel_length < 1) { return; } if (self->s.v.waterlevel >= 2) { // Swimming... float waterfriction = cvar("sv_waterfriction"); drop = vel_length * waterfriction * self->s.v.waterlevel * g_globalvars.frametime; } else if (onGround) { // FIXME: friction is doubled if player is about to drop off a ledge float stopspeed = cvar("sv_stopspeed"); float friction = cvar("sv_friction"); float control = vel_length < stopspeed ? stopspeed : vel_length; drop = control * friction * g_globalvars.frametime; } if (drop) { float new_vel = max(vel_length - drop, 0); VectorScale(expected_velocity, new_vel / vel_length, expected_velocity); vel_length = new_vel; } else { vel_length = VectorLength(expected_velocity); } // Step 2: change direction to maximise acceleration in desired direction if (self->s.v.waterlevel >= 2) { // Water movement } else { float min_numerator = onGround ? 319 : 29; float max_numerator = onGround ? 281.6 : -8.4; float used_numerator; float max_incr; vec3_t current_direction; vec3_t original_direction; // Gravity kicks in /* if (!onGround) expected_velocity[2] -= self->gravity * cvar ("sv_gravity") * g_globalvars.frametime; else expected_velocity[2] = 0; */ // Ground & air acceleration is the same hor_speed_squared = (expected_velocity[0] * expected_velocity[0] + expected_velocity[1] * expected_velocity[1]); if (onGround && hor_speed_squared < sv_maxspeed * sv_maxspeed * 0.8 * 0.8) { return; } self->fb.dir_move_[2] = 0; normalize(self->fb.dir_move_, original_direction); normalize(expected_velocity, current_direction); used_numerator = min_numerator + movement_skill * (max_numerator - min_numerator); max_incr = used_numerator * used_numerator; if (hor_speed_squared >= max_incr) { vec3_t perpendicular; vec3_t up_vector = { 0, 0, 1 }; float rotation = acos(max_incr / hor_speed_squared) * 180 / M_PI; // Find out if rotation should be positive or negative CrossProduct(current_direction, original_direction, perpendicular); if ((self->fb.path_state & BOTPATH_CURLJUMP_HINT) && !onGround) { // Once in the air, we rotate in opposite direction // FIXME: THIS IS UGLY HACK if (framecount % 3) { rotation = 0; } else if (self->fb.angle_hint > 0) { rotation = -rotation; } } else if (deathmatch == 4) { if (self->fb.wiggle_run_dir == 0) { self->fb.wiggle_increasing = perpendicular[2] > 0; self->fb.wiggle_run_dir = self->fb.wiggle_increasing ? 1 : -1; } else if ((self->fb.wiggle_run_dir > self->fb.skill.wiggle_run_limit) && (perpendicular[2] < 0)) { self->fb.wiggle_increasing = false; } else if ((self->fb.wiggle_run_dir < -self->fb.skill.wiggle_run_limit) && (perpendicular[2] > 0)) { self->fb.wiggle_increasing = 1; } else if (self->fb.wiggle_increasing) { ++self->fb.wiggle_run_dir; } else { --self->fb.wiggle_run_dir; } if (self->fb.wiggle_increasing) { rotation = -rotation; } } else if (perpendicular[2] < 0) { rotation = -rotation; } if (rotation) { vec3_t proposed_dir; vec3_t vel_after_rot; vec3_t vel_std; float dp_std, dp_rot; RotatePointAroundVector(proposed_dir, up_vector, current_direction, rotation); // Calculate what mvdsv will do (roughly) PM_Accelerate(expected_velocity, (int)self->s.v.flags & FL_ONGROUND, proposed_dir, vel_after_rot, false); PM_Accelerate(expected_velocity, (int)self->s.v.flags & FL_ONGROUND, current_direction, vel_std, false); // Only rotate if 'better' than moving normally dp_rot = DotProduct(vel_after_rot, original_direction); dp_std = DotProduct(vel_std, original_direction); if ((dp_rot > dp_std) || (dp_rot >= 0.9)) { VectorCopy(proposed_dir, self->fb.dir_move_); if (self->fb.debug_path) { PM_Accelerate(expected_velocity, (int)self->s.v.flags & FL_ONGROUND, proposed_dir, vel_after_rot, true); } } else if (self->fb.debug_path) { PM_Accelerate(expected_velocity, (int)self->s.v.flags & FL_ONGROUND, current_direction, vel_std, true); } } else { #ifdef DEBUG_MOVEMENT if (self->fb.debug_path && ! onGround) { G_bprint (PRINT_HIGH, "> AirControl rotation: \n"); } #endif } } } } float AverageTraceAngle(gedict_t *self, qbool debug, qbool report) { vec3_t back_left, projection, incr; int angles[] = { 45, 30, 15, 0, -15, -30, -45 }; int i; float best_angle = 0; float best_angle_frac = 0; float total_angle = 0; float avg_angle; float distance = 320; if (self->fb.path_state & JUMP_LEDGE) { return 0; } if (debug) { trap_makevectors(self->s.v.angles); } else { trap_makevectors(self->fb.dir_move_); } VectorMA(self->s.v.origin, -VEC_HULL_MIN[0], g_globalvars.v_forward, back_left); VectorMA(back_left, VEC_HULL_MIN[1], g_globalvars.v_right, back_left); VectorScale(g_globalvars.v_right, (VEC_HULL_MAX[0] - VEC_HULL_MIN[0]) / (sizeof(angles) / sizeof(angles[0]) - 1), incr); if (debug) { G_bprint(2, "Current origin: %d %d %d\n", PASSINTVEC3(self->s.v.origin)); G_bprint(2, "Current angles: %d %d\n", PASSINTVEC2(self->s.v.angles)); } for (i = 0; i < sizeof(angles) / sizeof(angles[0]); ++i) { int angle = angles[i]; RotatePointAroundVector(projection, g_globalvars.v_up, g_globalvars.v_forward, angle); VectorMA(back_left, distance, projection, projection); traceline(PASSVEC3(back_left), PASSVEC3(projection), false, self); if (g_globalvars.trace_fraction == 1) { total_angle += angle * 1.5; // bonus for success } else if (g_globalvars.trace_fraction > 0.4) { total_angle += angle * g_globalvars.trace_fraction; } if (debug) { G_bprint(2, "Angle: %d => [%d %d %d] [%d %d %d] = %f\n", angle, PASSINTVEC3(back_left), PASSINTVEC3(projection), g_globalvars.trace_fraction); } if ((i == 0) || g_globalvars.trace_fraction > best_angle_frac) { best_angle = angle; best_angle_frac = g_globalvars.trace_fraction; } VectorAdd(back_left, incr, back_left); } avg_angle = total_angle / (sizeof(angles) / sizeof(angles[0])); if (debug) { G_bprint(2, "Best angle: %f\n", best_angle); G_bprint(2, "Total angle: %f\n", avg_angle); } return avg_angle; } static void BestJumpingDirection(gedict_t *self) { float raw_avg_angle = AverageTraceAngle(self, false, self->fb.debug_path); float avg_angle; if (raw_avg_angle < 0) { avg_angle = min(raw_avg_angle, -15); } else { avg_angle = max(raw_avg_angle, 15); } RotatePointAroundVector(self->fb.dir_move_, g_globalvars.v_up, g_globalvars.v_forward, avg_angle); } void BotSetCommand(gedict_t *self) { extern float last_frame_time; float msec_since_last = (last_frame_time - self->fb.last_cmd_sent) * 1000; int cmd_msec = (int)msec_since_last; int weapon_script_impulse = 0; int impulse = 0, buttons = 0; qbool jumping; qbool firing; vec3_t direction; BotPerformRocketJump(self); if (cmd_msec) { self->fb.cmd_msec_lost += (msec_since_last - cmd_msec); if (self->fb.cmd_msec_lost >= 1) { self->fb.cmd_msec_lost -= 1; cmd_msec += 1; } } else if (self->fb.cmd_msec_last) { // Probably re-sending after blocked(), re-use old number cmd_msec = self->fb.cmd_msec_last; } else { cmd_msec = 12; } //G_sprint(self, PRINT_HIGH, "Movement length @ %f: %d\n", last_frame_time, cmd_msec); // dir_move_ is the direction we want to move in, but need to take inertia into effect // ... as rough guide (and save doubling physics calculations), scale command > VectorNormalize(self->fb.dir_move_); VectorScale(self->fb.dir_move_, sv_maxspeed, self->fb.last_cmd_direction); trap_makevectors(self->fb.desired_angle); // During intermission, always do nothing and leave humans to change level if (intermission_running) { self->fb.firing = self->fb.jumping = false; } else if (teamplay && (deathmatch == 1) && !self->fb.firing) { // Weaponscripts if ((self->s.v.weapon != IT_SHOTGUN) && (self->s.v.weapon != IT_AXE)) { weapon_script_impulse = (self->s.v.ammo_shells ? 2 : 1); } } impulse = self->fb.botchose ? self->fb.next_impulse : self->fb.firing ? self->fb.desired_weapon_impulse : weapon_script_impulse; if (self->fb.firing && BotUsingCorrectWeapon(self)) { impulse = 0; // we already have the requested weapon } jumping = self->fb.jumping || self->fb.waterjumping; firing = self->fb.firing; self->fb.waterjumping = false; if (self->fb.dbg_countdown > 0) { jumping = firing = false; VectorClear(direction); --self->fb.dbg_countdown; } else { if (jumping && ((int)self->s.v.flags & FL_ONGROUND)) { BestJumpingDirection(self); } else { ApplyPhysics(self); } if (self->s.v.waterlevel <= 1) { vec3_t hor; VectorCopy(self->fb.dir_move_, hor); hor[2] = 0; VectorNormalize(hor); VectorScale(hor, 800, hor); direction[0] = DotProduct(g_globalvars.v_forward, hor); direction[1] = DotProduct(g_globalvars.v_right, hor); direction[2] = 0; } else { direction[0] = DotProduct (g_globalvars.v_forward, self->fb.dir_move_) * 800; direction[1] = DotProduct (g_globalvars.v_right, self->fb.dir_move_) * 800; direction[2] = DotProduct (g_globalvars.v_up, self->fb.dir_move_) * 800; } #ifdef DEBUG_MOVEMENT if (self->fb.debug_path) { G_bprint (PRINT_HIGH, " : final direction sent [%4.1f %4.1f %4.1f]\n", PASSVEC3 (self->fb.dir_move_)); } #endif } self->fb.desired_angle[2] = 0; if (ISDEAD(self)) { firing = false; jumping = BotRequestRespawn(self); VectorClear(direction); impulse = 0; } else if (self->fb.min_move_time > g_globalvars.time) { VectorClear(direction); } // Keep bots on spawns before match start if (match_in_progress != 2 && cvar(FB_CVAR_FREEZE_PREWAR)) { jumping = firing = false; VectorClear(direction); impulse = 0; } buttons |= (firing ? 1 : 0); buttons |= (jumping ? 2 : 0); trap_SetBotCMD(NUM_FOR_EDICT(self), cmd_msec, PASSVEC3(self->fb.desired_angle), PASSVEC3(direction), buttons, impulse); self->fb.next_impulse = 0; self->fb.botchose = false; self->fb.last_cmd_sent = last_frame_time; self->fb.cmd_msec_last = cmd_msec; VectorClear(self->fb.obstruction_normal); if (self->s.v.button0 && !firing) { // Stopped firing, randomise next time self->fb.last_rndaim_time = 0; } self->fb.prev_look_object = self->fb.look_object; VectorCopy(self->s.v.velocity, self->fb.prev_velocity); } #endif QW-Group-ktx-d05d6ca/src/bot_routing.c000066400000000000000000000200721475442401000177170ustar00rootroot00000000000000#ifdef BOT_SUPPORT #include "g_local.h" qbool DM6DoorClosed(fb_path_eval_t *eval); qbool BotDoorIsClosed(gedict_t *door); #define PATH_NOISE_PENALTY 2.5 #define PATH_AVOID_PENALTY 2.5 static qbool DetectIncomingRocket(gedict_t *self, qbool rocket_alert, vec3_t marker_pos) { // if the path location is too close to an incoming rocket, if (rocket_alert && (VectorDistance(marker_pos, self->fb.rocket_endpos) < 200)) { traceline(PASSVEC3(self->fb.rocket_endpos), PASSVEC3(marker_pos), true, self); return (g_globalvars.trace_fraction == 1); } return false; } static qbool AvoidTeleport(fb_path_eval_t *eval) { if (g_globalvars.time >= eval->test_marker->fb.arrow_time) { return false; } if (!eval->test_marker->fb.arrow_time_setby || !eval->player) { return true; // old behaviour } if ((eval->test_marker->fb.arrow_time_setby == eval->player) || (eval->test_marker->fb.arrow_time_setby->ct != ctPlayer)) { return false; // we can't telefrag ourselves } // don't telefrag our own teammates return SameTeam(eval->test_marker->fb.arrow_time_setby, eval->player); } static float EvalPath(fb_path_eval_t *eval, qbool allowRocketJumps, qbool trace_bprint, float current_goal_time, float current_goal_time_125) { float path_score; float same_dir; vec3_t marker_position; // don't try and pass through closed doors if (BotDoorIsClosed(eval->test_marker)) { return PATH_SCORE_NULL; } // Determine position VectorAdd(eval->test_marker->s.v.absmin, eval->test_marker->s.v.view_ofs, marker_position); // if it's a rocket jump, calculate path time (TODO: fix this for horizontal rocket jumps, also precalculate) // FIXME: /sv_maxspeed is wrong, should be based on velocity of flight if ((eval->description & ROCKET_JUMP) && allowRocketJumps) { vec3_t m_pos; VectorAdd(eval->touch_marker->s.v.absmin, eval->touch_marker->s.v.view_ofs, m_pos); eval->path_time = (VectorDistance(marker_position, m_pos) / (sv_maxspeed * 1.5)); } // if (!eval->path_normal && !(eval->description & REVERSIBLE)) { return PATH_SCORE_NULL; } // FIXME: Map specific logic if (DM6DoorClosed(eval)) { return PATH_SCORE_NULL; } if ((eval->description & ROCKET_JUMP) && !allowRocketJumps) { return PATH_SCORE_NULL; } // FIXME: This code gives a bonus to routes carrying the player in the same direction { vec3_t direction_to_marker; VectorSubtract(marker_position, eval->player_origin, direction_to_marker); VectorNormalize(direction_to_marker); same_dir = DotProduct(eval->player_direction, direction_to_marker); } path_score = same_dir + g_random(); self->fb.avoiding = AvoidTeleport(eval) || DetectIncomingRocket(self, eval->rocket_alert, marker_position); // If we'd pickup an item as we travel, negatively impact score if (eval->be_quiet && eval->test_marker->fb.pickup && !WaitingToRespawn(eval->test_marker)) { if (eval->test_marker != eval->goalentity_marker) { if (eval->test_marker->fb.pickup()) { path_score -= PATH_NOISE_PENALTY; } } } if (self->fb.avoiding) { path_score -= PATH_AVOID_PENALTY; } else if (eval->goalentity_marker) { float total_goal_time; // Calculate time from marker > goal entity from_marker = eval->test_marker; path_normal = eval->path_normal; ZoneMarker(from_marker, eval->goalentity_marker, path_normal, allowRocketJumps); traveltime = SubZoneArrivalTime(zone_time, middle_marker, eval->goalentity_marker, allowRocketJumps); total_goal_time = eval->path_time + traveltime; if (total_goal_time > eval->goal_late_time) { if (traveltime < current_goal_time) { path_score += eval->lookahead_time_ - total_goal_time; } else if (total_goal_time > current_goal_time_125) { path_score -= total_goal_time; } } } return path_score; } // FIXME: Breaking it up like this was useful for initial testing static void BotRouteEvaluation(qbool be_quiet, float lookahead_time, gedict_t *from_marker, gedict_t *to_marker, qbool rocket_alert, qbool rocket_jump_routes_allowed, vec3_t player_origin, vec3_t player_direction, qbool path_normal, qbool trace_bprint, float current_goal_time, float current_goal_time_125, float goal_late_time, gedict_t *player, float *best_score, gedict_t **next_marker, int *next_description, int *new_angle_hint, int *new_rj_frame_delay, float new_rj_angles[2]) { fb_path_eval_t eval = { 0 }; int i = 0; eval.goalentity_marker = to_marker; VectorCopy(player_origin, eval.player_origin); VectorCopy(player_direction, eval.player_direction); eval.rocket_alert = rocket_alert; eval.path_normal = path_normal; eval.touch_marker = from_marker; eval.goal_late_time = goal_late_time; eval.lookahead_time_ = lookahead_time; eval.be_quiet = be_quiet; eval.player = player; for (i = 0; i < NUMBER_PATHS; ++i) { eval.description = from_marker->fb.paths[i].flags; eval.path_time = from_marker->fb.paths[i].time; eval.test_marker = from_marker->fb.paths[i].next_marker; if (eval.test_marker) { float path_score = 0; path_score = EvalPath(&eval, rocket_jump_routes_allowed, trace_bprint, current_goal_time, current_goal_time_125); if (path_score > *best_score) { *best_score = path_score; *next_marker = eval.test_marker; *next_description = eval.description; *new_angle_hint = from_marker->fb.paths[i].angle_hint; new_rj_angles[PITCH] = from_marker->fb.paths[i].rj_pitch; new_rj_angles[YAW] = from_marker->fb.paths[i].rj_yaw; *new_rj_frame_delay = from_marker->fb.paths[i].rj_delay; } } } } void PathScoringLogic(float goal_respawn_time, qbool be_quiet, float lookahead_time, qbool path_normal, vec3_t player_origin, vec3_t player_direction, gedict_t *touch_marker_, gedict_t *goalentity_marker, qbool rocket_alert, qbool rocket_jump_routes_allowed, qbool trace_bprint, gedict_t *player, float *best_score, gedict_t **linked_marker_, int *new_path_state, int *new_angle_hint, int *new_rj_frame_delay, float new_rj_angles[2]) { float current_goal_time = 0; float current_goal_time_125 = 0; float goal_late_time = 0; *new_rj_frame_delay = 0; new_rj_angles[PITCH] = 78.25; new_rj_angles[YAW] = 0; if (goalentity_marker) { from_marker = touch_marker_; ZoneMarker(from_marker, goalentity_marker, path_normal, rocket_jump_routes_allowed); traveltime = SubZoneArrivalTime(zone_time, middle_marker, goalentity_marker, rocket_jump_routes_allowed); current_goal_time = traveltime; current_goal_time_125 = traveltime + 1.25; // FIXME: Estimating respawn times should be skill-based if (current_goal_time < 2.5) { goal_late_time = (goal_respawn_time - (g_random() * 5)) - g_globalvars.time; } else { goal_late_time = (goal_respawn_time - (g_random() * 10)) - g_globalvars.time; } } // Direct from touch marker to goal entity if (goalentity_marker && touch_marker_) { float path_score = 0; fb_path_eval_t eval = { 0 }; eval.path_normal = path_normal; eval.rocket_alert = rocket_alert; eval.touch_marker = touch_marker_; eval.goalentity_marker = goalentity_marker; eval.goal_late_time = goal_late_time; eval.lookahead_time_ = lookahead_time; eval.be_quiet = be_quiet; VectorCopy(player_origin, eval.player_origin); VectorCopy(player_direction, eval.player_direction); eval.player = player; eval.test_marker = touch_marker_; path_score = EvalPath(&eval, rocket_jump_routes_allowed, trace_bprint, current_goal_time, current_goal_time_125); if (path_score > *best_score) { *best_score = path_score; *linked_marker_ = eval.test_marker; *new_path_state = eval.description; *new_angle_hint = 0; *new_rj_frame_delay = 0; } } // Evaluate all paths from touched marker to the goal entity BotRouteEvaluation(be_quiet, lookahead_time, touch_marker_, goalentity_marker, rocket_alert, rocket_jump_routes_allowed, player_origin, player_direction, path_normal, trace_bprint, current_goal_time, current_goal_time_125, goal_late_time, player, best_score, linked_marker_, new_path_state, new_angle_hint, new_rj_frame_delay, new_rj_angles); } #endif // BOT_SUPPORT QW-Group-ktx-d05d6ca/src/bot_world.c000066400000000000000000000064601475442401000173640ustar00rootroot00000000000000#ifdef BOT_SUPPORT #include "g_local.h" void BotEventPlatformHitTop(gedict_t *self) { int i = 0; for (i = 0; i < sizeof(self->fb.paths) / sizeof(self->fb.paths[0]); ++i) { gedict_t *next = self->fb.paths[i].next_marker; if (next) { int j = 0; for (j = 0; j < sizeof(self->fb.paths) / sizeof(self->fb.paths[0]); ++j) { if ((next->fb.paths[j].next_marker == self) && (next->fb.paths[j].flags & VERTICAL_PLATFORM)) { next->fb.paths[j].flags |= ROCKET_JUMP; } } } } } void BotEventPlatformHitBottom(gedict_t *self) { int i = 0; for (i = 0; i < sizeof(self->fb.paths) / sizeof(self->fb.paths[0]); ++i) { gedict_t *next = self->fb.paths[i].next_marker; if (next) { int j = 0; for (j = 0; j < sizeof(self->fb.paths) / sizeof(self->fb.paths[0]); ++j) { if ((next->fb.paths[j].next_marker == self) && (next->fb.paths[j].flags & VERTICAL_PLATFORM)) { next->fb.paths[j].flags &= ~ROCKET_JUMP; } } } } } void BotEventDoorHitTop(gedict_t *self) { //G_bprint (2, "DoorHitTop... %s\n", (self->state & STATE_BOTTOM ? "bottom" : "non-bottom")); } void BotEventDoorHitBottom(gedict_t *self) { //G_bprint (2, "DoorHitBottom... %s\n", (self->state & STATE_BOTTOM ? "bottom" : "non-bottom")); } void BotPlatformTouched(gedict_t *platform, gedict_t *player) { if (IsMarkerFrame() && platform->fb.fl_marker) { check_marker(platform, player); } } // TODO: the height offset is fixed here, leading to the bot not targetting the player when they are behind barrier on povdmm4 // improve with VISIBILITY_LOW | NORMAL | HIGH? // Test if one player is visible to another. takes into account other entities & ring static qbool VisibilityTest(gedict_t *self, gedict_t *visible_object, float min_dot_product) { vec3_t temp; if (visible_object->s.v.takedamage) { // Can only see invisible objects when they're attacking if ((g_globalvars.time < visible_object->invisible_finished) && (g_globalvars.time >= visible_object->attack_finished)) { return false; } // If we can draw straight line between the two... traceline(self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 32, visible_object->s.v.origin[0], visible_object->s.v.origin[1], visible_object->s.v.origin[2] + 32, true, self); if (g_globalvars.trace_fraction == 1) { if (min_dot_product == 0) { return true; } // Check it's sufficiently in front of the player trap_makevectors(self->s.v.v_angle); VectorSubtract(visible_object->s.v.origin, self->s.v.origin, temp); VectorNormalize(temp); return DotProduct (g_globalvars.v_forward, temp) >= min_dot_product; } } return false; } qbool Visible_360(gedict_t *self, gedict_t *visible_object) { return (self->fb.enemy_visible = VisibilityTest(self, visible_object, 0.0f)); } qbool Visible_infront(gedict_t *self, gedict_t *visible_object) { return (self->fb.enemy_visible = VisibilityTest(self, visible_object, self->fb.skill.visibility)); } qbool BotDoorIsClosed(gedict_t *door) { // Not a door if (!door->fb.door_entity) { return false; } door = door->fb.door_entity; if (streq(door->classname, "door")) { if (door->fb.T & MARKER_BLOCKED_ON_STATE_TOP) { return (door->state == STATE_TOP); } else { return (door->state == STATE_BOTTOM); } } return false; } #endif QW-Group-ktx-d05d6ca/src/buttons.c000066400000000000000000000113661475442401000170700ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void button_wait(void); void button_return(void); void button_wait(void) { self->state = STATE_TOP; self->s.v.nextthink = self->s.v.ltime + self->wait; self->think = (func_t) button_return; activator = PROG_TO_EDICT(self->s.v.enemy); SUB_UseTargets(); self->s.v.frame = 1; // use alternate textures } void button_done(void) { self->state = STATE_BOTTOM; } void button_return(void) { self->state = STATE_DOWN; SUB_CalcMove(self->pos1, self->speed, button_done); self->s.v.frame = 0; // use normal textures if (ISLIVE(self)) { self->s.v.takedamage = DAMAGE_YES; // can be shot again } } void button_blocked(void) { // do nothing, just don't ome all the way back out } void button_fire(void) { if (!k_practice) // #practice mode# { if (match_in_progress != 2) { return; } } if ((self->state == STATE_UP) || (self->state == STATE_TOP)) { return; } sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); self->state = STATE_UP; SUB_CalcMove(self->pos2, self->speed, button_wait); } void button_use(void) { // #practice mode# if (!k_practice && (match_in_progress != 2)) { return; } self->s.v.enemy = EDICT_TO_PROG(activator); button_fire(); } void button_touch(void) { // #practice mode# if (!k_practice && (match_in_progress != 2)) { return; } if (other->ct != ctPlayer) { return; } self->s.v.enemy = EDICT_TO_PROG(other); button_fire(); } void button_killed(void) { if (!k_practice && (match_in_progress != 2)) { return; } if (lgc_enabled()) { return; } self->s.v.enemy = EDICT_TO_PROG(damage_attacker); self->s.v.health = self->s.v.max_health; self->s.v.takedamage = DAMAGE_NO; // wil be reset upon return button_fire(); } /*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" 0) steam metal 1) wooden clunk 2) metallic click 3) in-out */ void SP_func_button(void) { float ftemp; if (self->s.v.sounds == 0) { trap_precache_sound("buttons/airbut1.wav"); self->noise = "buttons/airbut1.wav"; } if (self->s.v.sounds == 1) { trap_precache_sound("buttons/switch21.wav"); self->noise = "buttons/switch21.wav"; } if (self->s.v.sounds == 2) { trap_precache_sound("buttons/switch02.wav"); self->noise = "buttons/switch02.wav"; } if (self->s.v.sounds == 3) { trap_precache_sound("buttons/switch04.wav"); self->noise = "buttons/switch04.wav"; } SetMovedir(); self->s.v.movetype = MOVETYPE_PUSH; // if button does't have model ( mapper fault? ), // we must set it to something safe, because with SOLID_BSP and null model server crashed self->s.v.solid = (strnull(self->model) ? SOLID_NOT : SOLID_BSP); setmodel(self, self->model); self->blocked = (func_t) button_blocked; self->use = (func_t) button_use; if (ISLIVE(self)) { self->s.v.max_health = self->s.v.health; self->th_die = button_killed; self->s.v.takedamage = DAMAGE_YES; } else { self->touch = (func_t) button_touch; } if (!self->speed) { self->speed = 40; } if (!self->wait) { self->wait = 1; } if (!self->lip) { self->lip = 4; } self->state = STATE_BOTTOM; // self->pos1 = self->s.v.origin; VectorCopy(self->s.v.origin, self->pos1); ftemp = (fabs(DotProduct(self->s.v.movedir, self->s.v.size)) - self->lip); self->pos2[0] = self->pos1[0] + self->s.v.movedir[0] * ftemp; self->pos2[1] = self->pos1[1] + self->s.v.movedir[1] * ftemp; self->pos2[2] = self->pos1[2] + self->s.v.movedir[2] * ftemp; } QW-Group-ktx-d05d6ca/src/captain.c000066400000000000000000000201571475442401000170070ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // captain.c #include "g_local.h" // Captain functions introduced by rc\sturm // here we use k_captains for storing the number of captains. // one elected captain is worth 1, player being elected is worth 0.5 :) // Check if picking should be finished // pick the player static int turn_number; void CancelCaptains(void); int capt_num(gedict_t *p) { if ((p->k_captain == 1) || (p->k_captain == 2)) { return p->k_captain; } return 0; } void SetPlayerParams(gedict_t *p, gedict_t *cap) { char *infoteam, *infocolor; infoteam = cvar_string(va("_k_captteam%d", (int)k_captainturn)); infocolor = cvar_string(va("_k_captcolor%d", (int)k_captainturn)); if (turn_number != 1) // captains turn rules: c1 c2 c2 c1 c2 c1 c2 etc... i.e. second captain pick twice at beginning { k_captainturn = (k_captainturn == 1 ? 2 : 1); } turn_number++; G_bprint(2, "%s set to team \x90%s\x91\n", p->netname, infoteam); G_sprint(p, 2, "You were picked by %s\n" "Time to go ready\n", cap->netname); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "break\n" "team \"%s\"\n" "color \"%s\"\n", infoteam, infocolor); p->s.v.frags = 0; p->k_picked = capt_num(cap); } void PrintCaptainInTurn(void) { gedict_t *p; for (p = world; (p = find_plr(p)) && capt_num(p) != k_captainturn;) { ; // empty } if (p) { G_bprint(2, "%s is picking\n", p->netname); } else { G_bprint(2, "PrintCaptainInTurn: captain not found\n"); CancelCaptains(); } } void CancelCaptains(void) { gedict_t *p; k_captains = 0; for (p = world; (p = find_plr(p));) { if (capt_num(p)) { G_sprint(p, 2, "You are no longer a %s\n", redtext("captain")); } p->k_captain = p->k_picked = 0; if (is_elected(p, etCaptain)) // just for sanity { AbortElect(); } } } void CheckFinishCaptain(void) { int pl_free = 0; gedict_t *p, *lastone = NULL; // s: calculate how many players are free for (p = world; (p = find_plr(p));) { if (p->s.v.frags) { lastone = p; pl_free++; } } if (pl_free == 1) // one free player left { for (p = world; (p = find_plr(p)) && capt_num(p) != k_captainturn;) { ; // empty } if (p) { SetPlayerParams(lastone, p); } else { G_bprint(2, "CheckFinishCaptain: captain not found\n"); } pl_free = 0; } if (!pl_free) { G_bprint(2, "All players chosen. Captain modes exited\n"); CancelCaptains(); } } void CaptainPickPlayer(void) { gedict_t *p; if (capt_num(self) != k_captainturn) { G_sprint(self, 2, "It's %s your turn\n", redtext("not")); return; } for (p = world; (p = find_plr(p)) && p->s.v.frags != self->s.v.impulse;) { ; // empty } if (!p) { G_sprint(self, 2, "No such player. Pick another one\n"); return; } SetPlayerParams(p, self); CheckFinishCaptain(); if (k_captains) { PrintCaptainInTurn(); } } void ExitCaptain(void) { gedict_t *p; if (!capt_num(self)) { return; } self->k_captain = 0; if (k_captains == 2) { G_bprint(2, "Player picking aborted\n"); for (p = world; (p = find_plr(p));) { if (p->s.v.frags) { p->s.v.frags = 0; } } } k_captains--; G_bprint(2, "%s captain present\n", (floor(k_captains) ? "\x90\x31\x91" : redtext("No"))); } void VoteCaptain(void) { int till; gedict_t *p, *electguard; // s: check if we are being elected or we are a captain already if (is_elected(self, etCaptain)) { G_bprint(2, "%s %s!\n", self->netname, redtext("aborts election")); AbortElect(); return; } if (capt_num(self)) { G_bprint(2, "%s is no longer a %s\n", self->netname, redtext("captain")); ExitCaptain(); return; } if (match_in_progress || intermission_running) { return; } if (!isTeam() && !isCTF()) { G_sprint(self, 2, "No team picking in non team mode\n"); return; } if (CountPlayers() < 3) { G_sprint(self, 2, "Not enough players present\n"); return; } if (k_captains == 2) { G_sprint(self, 2, "Only 2 captains are allowed\n"); return; } // s: no captain election if any election in progress if (get_votes( OV_ELECT)) { G_sprint(self, 2, "An election is already in progress\n"); return; } if ((till = Q_rint(self->v.elect_block_till - g_globalvars.time)) > 0) { G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } // s: no captains with team "" if (strnull(getteam(self))) { G_sprint(self, 2, "Set your team name first\n"); return; } // must be red or blue in ctf if (isCTF()) { if (!streq(getteam(self), "blue") && !streq(getteam(self), "red")) { G_sprint(self, 2, "Must be team red or blue for ctf\n"); return; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %d\n", (int)(streq(getteam(self), "blue") ? 13 : 4)); } // search if a captain already has the same team for (p = world; (p = find_plr(p)) && !capt_num(p);) { ; // empty } if (p) { if (streq(getteam(self), getteam(p))) { G_sprint(self, 2, "A %s with team \x90%s\x91 already exists\n" "Choose a new team name\n", redtext("captain"), getteam(p)); return; } // check if a captain already has the same colors if (streq(ezinfokey(self, "topcolor"), ezinfokey(p, "topcolor")) && streq(ezinfokey(self, "bottomcolor"), ezinfokey(p, "bottomcolor"))) { G_sprint(self, 2, "A %s with your color already exists\n" "Change to new color\n", redtext("captain")); return; } } // announce the election self->v.elect = 1; self->v.elect_type = etCaptain; k_captains += 0.5; G_bprint(2, "%s has %s status!\n", self->netname, redtext("requested captain")); for (p = world; (p = find_client(p));) { if ((p != self) && (p->ct == ctPlayer)) { G_sprint(p, 2, "Type %s in console to approve\n", redtext("yes")); } } G_sprint(self, 2, "Type %s to abort election\n", redtext("captain")); // s: spawn the cool dude electguard = spawn(); // Check the 1 minute timeout for election electguard->s.v.owner = EDICT_TO_PROG(world); electguard->classname = "electguard"; electguard->think = (func_t) ElectThink; electguard->s.v.nextthink = g_globalvars.time + 60; } void BeginPicking(void) { gedict_t *p; int num; if (CountPlayers() < 3) { G_bprint(2, "Not enough players present\n" "Captain modes exited\n"); CancelCaptains(); return; } G_bprint(2, "Both %s elected\n" "Team picking begins\n", redtext("captains")); num = 1; for (p = world; (p = find_plr(p));) { p->k_picked = 0; if (capt_num(p)) { G_sprint(p, 2, "\nUse %s or %s to choose\n", redtext("numbers"), redtext("impulses")); cvar_set(va("_k_captteam%d", capt_num(p)), getteam(p)); cvar_set(va("_k_captcolor%d", capt_num(p)), va("%s %s", ezinfokey(p, "topcolor"), ezinfokey(p, "bottomcolor"))); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "break\n" "color 0\n" "skin \"\"\n" "team \"\"\n"); p->s.v.frags = num; num++; } } turn_number = 0; k_captainturn = (g_random() < 0.5 ? 1 : 2); PrintCaptainInTurn(); } void BecomeCaptain(gedict_t *p) { gedict_t *cap = p; // warning, below 'p' is overwriten for (p = world; (p = find_plr(p)) && !capt_num(p);) { ; // empty } cap->k_captain = (p && capt_num(p) == 1) ? 2 : 1; k_captains = floor(k_captains) + 1; G_bprint(2, "%s becomes a %s\n", cap->netname, redtext("captain")); // s: if both captains are already elected, start choosing players if (k_captains == 2) { BeginPicking(); } else { G_bprint(2, "One more %s should be elected\n", redtext("captain")); } } QW-Group-ktx-d05d6ca/src/clan_arena.c000066400000000000000000001101511475442401000174450ustar00rootroot00000000000000// // Clan Arena related // #include "g_local.h" static int round_num; static int team1_score; static int team2_score; static int pause_count; static int pause_time; static int round_time; static int loser_team; static qbool do_endround_stuff = false; static qbool print_stats = false; static float loser_respawn_time = 999; // number of seconds before a teammate would've respawned void track_player(gedict_t *observer); void enable_player_tracking(gedict_t *e, int follow); void r_changetrackingstatus(float t); void CA_PrintScores(void); void CA_TeamsStats(void); void CA_SendTeamInfo(gedict_t *t); void print_player_stats(qbool series_over); void CA_OnePlayerStats(gedict_t *p, qbool series_over); void EndRound(int alive_team); void show_tracking_info(gedict_t *p); gedict_t* ca_find_player(gedict_t *p, gedict_t *observer) { char *team = getteam(observer); // if the observer is just spectating, or if the round is over // then any player can be watched. // otherwise, you can only spec teammates if (!observer->ca_ready || ca_round_pause) { p = find_plr(p); while (p && !p->in_play) { p = find_plr(p); } } else { p = find_plr_same_team(p, team); while (p && !p->in_play) { p = find_plr_same_team(p, team); } } return p; } gedict_t* ca_get_player(gedict_t *observer) { return ca_find_player(world, observer); } qbool is_rules_change_allowed(void); int CA_count_ready_players(void) { int cnt; gedict_t *p; for (cnt = 0, p = world; (p = find_plr(p));) { if (p->ca_ready) { cnt++; } } return cnt; } int CA_get_score_1(void) { return team1_score; } int CA_get_score_2(void) { return team2_score; } int calc_respawn_time(gedict_t *p, int offset) { qbool isWipeout = (cvar("k_clan_arena") == 2); int max_deaths = cvar("k_clan_arena_max_respawns"); int time = 999; int teamsize = 0; int multiple; gedict_t *p2; // count players on team for (p2 = world; (p2 = find_plr_same_team(p2, getteam(p)));) { teamsize++; } multiple = bound(3, teamsize+1, 6); // first respawn won't take more than 6 seconds regardless of team size if (isWipeout && (p->round_deaths+offset <= max_deaths)) { // if 4 players on team, the spawn times are 5, 10, 20, 30 // if 3 players on team, the spawn times are 4, 8, 16, 24 // if 2 players on team, the spawn times are 3, 6, 12, 18 time = p->round_deaths+offset == 1 ? multiple : (p->round_deaths-1+offset) * (multiple*2); } return time; } // returns 0 if player has at least one alive teammate // otherwise returns number of seconds until next teammate respawns float last_alive_time(gedict_t *player) { gedict_t *p; float time = 0; for (p = world; (p = find_plr_same_team(p, getteam(player)));) { if (p->ca_ready) { if (p->in_play && p != player) { time = 0; break; } else if (!p->in_play) { if (!time || p->seconds_to_respawn < time) { time = p->seconds_to_respawn; } } } } // this checks to see if there's already a last_alive_countdown in progress // because we only want to play the audio once at the begining of the countdown // Only play the audio if the player is alive if (!player->last_alive_active && (time > 0) && player->in_play) { player->last_alive_active = true; stuffcmd(player, "play misc/medkey.wav\n"); } else if (time == 0) { if (player->last_alive_active && player->in_play) { player->escape_time = g_globalvars.time; // start timer for escape time } player->last_alive_active = false; } return time; } float enemy_last_alive_time(gedict_t *player) { gedict_t *p; float time = 0; int alive_enemies = 0; for (p = world; (p = find_plr(p));) { if (p->ca_ready && strneq(getteam(p), getteam(player))) { if (p->in_play) { alive_enemies++; } else if (!p->in_play) { if (!time || p->seconds_to_respawn < time) { time = p->seconds_to_respawn; } } } } return alive_enemies > 1 ? 0 : time; } float team_last_alive_time(int team) { gedict_t *p; float time = 999; char* team_name = team ? (team == 1 ? cvar_string("_k_team1") : cvar_string("_k_team2")) : ""; for (p = world; (p = find_plr_same_team(p, team_name));) { if (p->ca_ready && !p->in_play) { if (p->seconds_to_respawn < time) { time = p->seconds_to_respawn; } } } return time; } void SM_PrepareCA(void) { gedict_t *p; if (!isCA()) { return; } team1_score = team2_score = 0; round_num = 1; for (p = world; (p = find_plr(p));) { if (p->ct == ctPlayer && p->ready) { p->ca_ready = p->ready; p->seconds_to_respawn = 0; p->teamcolor = NULL; } } } int CA_wins_required(void) { int k_clan_arena_rounds = bound(3, cvar("k_clan_arena_rounds"), 101); k_clan_arena_rounds += (k_clan_arena_rounds % 2) ? 0 : 1; return ((k_clan_arena_rounds + 1) / 2); } qbool isCA(void) { return (isTeam() && cvar("k_clan_arena")); } qbool CA_CheckAlive(gedict_t *p) { if (p) { if (!match_in_progress) { return true; } else if (!p->ca_ready && !match_over) { return false; } else if (ra_match_fight != 2 || p->in_limbo) { return true; } else { return false; } } else { return false; } } void CA_MatchBreak(void) { gedict_t *p; // reset these so a new game can be started right away ca_round_pause = 0; ra_match_fight = 0; print_stats = false; do_endround_stuff = false; // stop recording demo localcmd("sv_demostop\n"); // respawn all players for (p = world; (p = find_plr(p));) { if (p->ct == ctPlayer) { k_respawn(p, false); } p->ca_ready = 0; // this needs to be reset } } void track_player(gedict_t *observer) { gedict_t *player = ca_get_player(observer); vec3_t delta; float vlen; int follow_distance; int upward_distance; if (player && !observer->in_play && observer->tracking_enabled) { if (observer->track_target && observer->track_target->in_play) { // is the observer not playing or is the round over? if (!observer->ca_ready || ca_round_pause) { player = observer->track_target; } // otherwise is the target on the observer's team? else if (streq(getteam(observer), getteam(observer->track_target))) { player = observer->track_target; } // if not, find a different player to watch else { observer->track_target = player; } } else { observer->track_target = player; } // { spectate in 1st person follow_distance = -10; upward_distance = 0; observer->hideentity = EDICT_TO_PROG(player); // in this mode we want to hide player model for watcher's view VectorCopy(player->s.v.v_angle, observer->s.v.angles); // } observer->s.v.fixangle = true; // force client v_angle (disable in 3rd person view) trap_makevectors(player->s.v.angles); VectorMA(player->s.v.origin, follow_distance, g_globalvars.v_forward, observer->s.v.origin); VectorMA(observer->s.v.origin, upward_distance, g_globalvars.v_up, observer->s.v.origin); // avoid positionning in walls traceline(PASSVEC3(player->s.v.origin), PASSVEC3(observer->s.v.origin), false, player); VectorCopy(g_globalvars.trace_endpos, observer->s.v.origin); if (g_globalvars.trace_fraction == 1) { VectorCopy(g_globalvars.trace_endpos, observer->s.v.origin); VectorMA(observer->s.v.origin, 10, g_globalvars.v_forward, observer->s.v.origin); } else { VectorSubtract(g_globalvars.trace_endpos, player->s.v.origin, delta); vlen = VectorLength(delta); vlen = vlen - 40; VectorNormalize(delta); VectorScale(delta, vlen, delta); VectorAdd(player->s.v.origin, delta, observer->s.v.origin); } // set observer's health/armor/ammo/weapon to match the player's observer->s.v.ammo_nails = player->s.v.ammo_nails; observer->s.v.ammo_shells = player->s.v.ammo_shells; observer->s.v.ammo_rockets = player->s.v.ammo_rockets; observer->s.v.ammo_cells = player->s.v.ammo_cells; observer->s.v.currentammo = player->s.v.currentammo; observer->s.v.armorvalue = player->s.v.armorvalue; observer->s.v.armortype = player->s.v.armortype; observer->s.v.health = player->s.v.health; observer->s.v.items = player->s.v.items; observer->s.v.weapon = player->s.v.weapon; observer->weaponmodel = player->weaponmodel; observer->s.v.weaponframe = player->s.v.weaponframe; // smooth playing for ezq / zq observer->s.v.movetype = MOVETYPE_LOCK; show_tracking_info(observer); } if (!player || !observer->tracking_enabled) { // restore movement and show racer entity observer->s.v.movetype = MOVETYPE_NOCLIP; observer->hideentity = 0; // set health/item values back to nothing observer->s.v.ammo_nails = 0; observer->s.v.ammo_shells = 0; observer->s.v.ammo_rockets = 0; observer->s.v.ammo_cells = 0; observer->s.v.currentammo = 0; observer->s.v.armorvalue = 0; observer->s.v.armortype = 0; observer->s.v.health = 100; observer->s.v.items = 0; } } void enable_player_tracking(gedict_t *e, int follow) { if (follow) { if (e->tracking_enabled) { return; } G_sprint(e, 2, "tracking %s\n", redtext("enabled")); e->tracking_enabled = 1; } else { if (!e->tracking_enabled) { return; } G_sprint(e, 2, "tracking %s\n", redtext("disabled")); snprintf(e->cptext, sizeof(e->cptext), "%s", ""); G_centerprint(e, "%s", e->cptext); e->tracking_enabled = 0; SetVector(e->s.v.velocity, 0, 0, 0); } } void r_changetrackingstatus(float t) { switch ((int)t) { case 1: // rfollow enable_player_tracking(self, 1); return; case 2: // rnofollow enable_player_tracking(self, 0); return; case 3: // rftoggle enable_player_tracking(self, !self->tracking_enabled); return; default: return; } } void ClanArenaTrackingToggleButton(void) { if ((self->ct == ctPlayer) && ISDEAD(self) && !self->ca_ready) { if (self->s.v.button0) { if (!(((int)(self->s.v.flags)) & FL_ATTACKRELEASED)) { return; } self->s.v.flags = (int)self->s.v.flags & ~FL_ATTACKRELEASED; r_changetrackingstatus((float) 3); } else { self->s.v.flags = ((int)(self->s.v.flags)) | FL_ATTACKRELEASED; } return; } } void CA_PutClientInServer(void) { if (!isCA()) { return; } // set CA self params if (match_in_progress == 2) { int items; self->s.v.ammo_nails = 200; self->s.v.ammo_shells = 100; self->s.v.ammo_rockets = 50; self->s.v.ammo_cells = 150; self->s.v.armorvalue = 200; self->s.v.armortype = 0.8; self->s.v.health = 100; self->ca_ammo_grenades = 6; items = 0; items |= IT_AXE; items |= IT_SHOTGUN; items |= IT_NAILGUN; items |= IT_SUPER_NAILGUN; items |= IT_SUPER_SHOTGUN; items |= IT_ROCKET_LAUNCHER; items |= IT_GRENADE_LAUNCHER; items |= IT_LIGHTNING; items |= IT_ARMOR3; // add red armor self->s.v.items = items; // { remove invincibility/quad if any self->invincible_time = 0; self->invincible_finished = 0; self->super_time = 0; self->super_damage_finished = 0; // } // must reset this to 0 or spectated player from // previous round will be invisible self->hideentity = 0; // reset escape time and last_alive every spawn self->escape_time = 0; self->last_alive_active = false; // default to spawning with rl self->s.v.weapon = IT_ROCKET_LAUNCHER; self->in_play = true; self->in_limbo = false; if (!self->teamcolor && self->ca_ready) { // if your team is "red" or "blue", set color to match if (streq(getteam(self), "red") || streq(getteam(self), "blue")) { self->teamcolor = streq(getteam(self), "red") ? "4" : "13"; } // if a "red" team exists, you aren't on it, so set color to blue else if (streq(cvar_string("_k_team1"), "red") || streq(cvar_string("_k_team2"), "red")) { self->teamcolor = "13"; } // if a "blue" team exists, you aren't on it, so set color to red else if (streq(cvar_string("_k_team1"), "blue") || streq(cvar_string("_k_team2"), "blue")) { self->teamcolor = "4"; } // neither "red" nor "blue" teams exist, so default to team1 being red and team2 blue else { self->teamcolor = streq(cvar_string("_k_team1"), getteam(self)) ? "4" : "13"; } } SetUserInfo(self, "topcolor", self->teamcolor ? self->teamcolor : "0", 0); SetUserInfo(self, "bottomcolor", self->teamcolor ? self->teamcolor : "0", 0); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %s\n", self->teamcolor ? self->teamcolor : "0"); } // set to ghost if dead if (ISDEAD(self)) { int max_deaths = cvar("k_clan_arena_max_respawns"); self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_NOCLIP; self->vw_index = 0; self->s.v.armorvalue = 0; self->s.v.health = 100; // tracking enabled by default self->tracking_enabled = 1; self->in_play = false; self->round_deaths++; //increment death count for wipeout self->in_limbo = (self->ca_ready) && (self->round_deaths <= max_deaths) && self->can_respawn; self->spawn_delay = 0; setmodel(self, ""); setorigin(self, PASSVEC3(self->s.v.origin)); if (!self->in_limbo || ca_round_pause) { // Change color to white if dead or not playing SetUserInfo(self, "topcolor", "0", 0); SetUserInfo(self, "bottomcolor", "0", 0); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %s\n", "0"); } } } qbool CA_can_fire(gedict_t *p) { if (!p) { return false; } if (!isCA()) { return true; } if (!ra_match_fight && p->ready) { return true; // allow fire during prewar if /ready } return (ISLIVE(p) && (ra_match_fight == 2) && time_to_start && (g_globalvars.time >= time_to_start)); } void CA_show_greeting(gedict_t *self) { char* mode = cvar("k_clan_arena") == 2 ? "Wipeout!" : "Clan Arena!"; if (self->ct == ctPlayer && !match_in_progress) { if (!self->ready) { G_centerprint(self, "Welcome to %s\n\n\n%s %s", mode, "set your team and type", redtext("/ready")); } else{ G_centerprint(self, "%s\n\n\n%s", "You are ready!", "waiting for other players"); } } } void CA_UpdateClients(void) { gedict_t *p; static double lastupdate = 0; if (g_globalvars.time - lastupdate < 0.5) { return; } lastupdate = g_globalvars.time; for (p = world; (p = find_client(p));) { CA_SendTeamInfo(p); } } // sends player state information to client for use in teaminfo or other hud elements void CA_SendTeamInfo(gedict_t *t) { int cl; int cnt; int origin0; int origin1; int origin2; int h; int a; int items; int shells; int nails; int rockets; int cells; int camode; int deadtype; int timetospawn; int kills; int deaths; int max_deaths; int track_target; gedict_t *p, *s; char *tm, *nick; s = ((t->ct == ctSpec) ? PROG_TO_EDICT(t->s.v.goalentity) : t); if (s->ct != ctPlayer) { return; } tm = getteam(s); camode = 1; // 1 is the only mode right now deadtype = 0; timetospawn = 0; max_deaths = cvar("k_clan_arena_max_respawns"); for (cnt = 0, p = world; (p = find_plr(p));) { if (cnt >= 10) { break; } if (t->trackent && (t->trackent == NUM_FOR_EDICT(p))) { continue; // we pseudo speccing such player, no point to send info about him } if (p->ca_ready || match_in_progress != 2) // be sure to send info if in prewar { if (match_in_progress == 2) { if (ISLIVE(p)) { deadtype = 0; // player is alive/active in round } else { deadtype = 1; // player is dead but will respawn if ((p->round_deaths > max_deaths) || (p->seconds_to_respawn == 999)) { deadtype = 2; // player is dead and won't respawn } } timetospawn = (int)ceil(p->seconds_to_respawn); } } else { continue; // don't send if player isn't ready/playing } if (strnull(nick = ezinfokey(p, "k_nick"))) // get nick, if any, do not send name, client can guess it too { nick = ezinfokey(p, "k"); } if (nick[0] && nick[1] && nick[2] && nick[3]) { nick[4] = 0; // truncate nick to 4 symbols } cnt++; cl = NUM_FOR_EDICT(p) - 1; if (streq(tm, getteam(p))) { // only teammates should get health/armor/loc/items information origin0 = (int)p->s.v.origin[0]; origin1 = (int)p->s.v.origin[1]; origin2 = (int)p->s.v.origin[2]; h = bound(0, (int)p->s.v.health, 999); a = bound(0, (int)p->s.v.armorvalue, 999); items = (int)p->s.v.items; shells = bound(0, (int)p->s.v.ammo_shells, 999); nails = bound(0, (int)p->s.v.ammo_nails, 999); rockets = bound(0, (int)p->s.v.ammo_rockets, 999); cells = bound(0, (int)p->s.v.ammo_cells, 999); } else { origin0 = origin1 = origin2 = h = a = items = shells = nails = rockets = cells = 0; } kills = bound(0, (int)p->round_kills, 999); deaths = bound(0, (int)p->round_deaths, 999); track_target = p->track_target ? NUM_FOR_EDICT(p->track_target) : -1; stuffcmd(t, "//cainfo %d %d %d %d %d %d %d \"%s\" %d %d %d %d %d %d %d %d %d %d\n", cl, origin0, origin1, origin2, h, a, items, nick, shells, nails, rockets, cells, camode, deadtype, timetospawn, kills, deaths, track_target); } } // wipeout: check if dying player survived just long enough for teammate to spawn void CA_check_escape(gedict_t *targ, gedict_t *attacker) { float escape_time = g_globalvars.time - targ->escape_time; gedict_t *p; if (escape_time > 0 && escape_time < 0.3) { for (p = world; (p = find_plr_same_team(p, getteam(targ)));) { stuffcmd(p, "play ca/hero.wav\n"); } for (p = world; (p = find_plr_same_team(p, getteam(attacker)));) { stuffcmd(p, "play boss2/idle.wav\n"); } // Player is rewarded with an extra life. // Escaping a wipe on the first life results in instant respawn. // That's cool, but could be written cleaner in calc_respawn_time(). targ->round_deaths--; G_bprint(2, "%s survives by &cff0%.3f&r seconds!\n", targ->netname, escape_time); } } void CA_ClientObituary(gedict_t *targ, gedict_t *attacker) { attacker->round_kills++; if (cvar("k_clan_arena") == 2) // Wipeout only { // check if targ was a lone survivor waiting for teammate to spawn CA_check_escape(targ, attacker); } // int ah, aa; // if (!isCA()) // { // return; // } // if (targ->ct != ctPlayer) // { // return; // so below targ is player // } // if (attacker->ct != ctPlayer) // { // attacker = targ; // seems killed self // } // ah = attacker->s.v.health; // aa = attacker->s.v.armorvalue; // if (attacker->ct == ctPlayer) // { // if (attacker != targ) // { // // This is classic CA behavior, but maybe we // // don't want players to know their killer's // // stats before the round is over. Commenting this // // out for now. // // G_sprint(targ, PRINT_HIGH, "%s %s %d %s %d %s\n", // // attacker->netname, redtext("had"), aa, // // redtext("armor and"), ah, redtext("health")); // } // } } // return 0 if there no alive teams // return 1 if there one alive team and alive_team point to 1 or 2 wich refering to _k_team1 or _k_team2 cvars // return 2 if there at least two alive teams static int CA_check_alive_teams(int *alive_team) { gedict_t *p; qbool few_alive_teams = false; char *first_team = NULL; if (alive_team) { *alive_team = 0; } for (p = world; (p = find_plr(p));) { if (!first_team) { if (ISLIVE(p)) { first_team = getteam(p); // ok, we found first team with alive players } continue; } if (strneq(first_team, getteam(p))) { if (ISLIVE(p)) { few_alive_teams = true; // we found at least two teams with alive players break; } } } if (few_alive_teams) { return 2; } if (first_team) { if (alive_team) { *alive_team = streq(first_team, cvar_string("_k_team1")) ? 1 : 2; } return 1; } return 0; } void CA_PrintScores(void) { int s1 = team1_score; int s2 = team2_score; char *t1 = cvar_string("_k_team1"); char *t2 = cvar_string("_k_team2"); G_sprint(self, 2, "%s \x90%s\x91 = %s\n", redtext("Team"), (s1 > s2 ? t1 : t2), dig3(s1 > s2 ? s1 : s2)); G_sprint(self, 2, "%s \x90%s\x91 = %s\n", redtext("Team"), (s1 > s2 ? t2 : t1), dig3(s1 > s2 ? s2 : s1)); } void CA_TeamsStats(void) { if (team1_score != team2_score) { G_bprint(2, "%s \x90%s\x91 wins %d to %d\n", redtext("Team"), cvar_string(va("_k_team%d", team1_score > team2_score ? 1 : 2)), team1_score > team2_score ? team1_score : team2_score, team1_score > team2_score ? team2_score : team1_score); } else { G_bprint(2, "%s have equal scores %d\n", redtext("Teams"), team1_score); } } void team_round_summary(int alive_team) { int t1_score = alive_team == 1 ? team1_score + 1 : team1_score; int t2_score = alive_team == 2 ? team2_score + 1 : team2_score; char *team1 = cvar_string(va("_k_team1")); char *team2 = cvar_string(va("_k_team2")); int winreq = CA_wins_required(); int t1_need = winreq - t1_score; int t2_need = winreq - t2_score; G_bprint(2, "team wins need status\n" "%s\n" "%-6s %4d %4d %s\n" "%-6s %4d %4d %s\n" "\n", redtext("------ ---- ---- ------------"), team1, t1_score, t1_need, !alive_team ? "tied round" : (alive_team == 1 ? "round winner" : ""), team2, t2_score, t2_need, !alive_team ? "tied round" : (alive_team == 2 ? "round winner" : "")); } void print_player_stats(qbool series_over) { gedict_t *p; G_bprint(2, "\nsco damg took k d gl rh rd lg%% player\n%s\n", redtext("--- ----- ---- -- -- --- --- --- ---- --------")); for (p = world; (p = find_plr(p));) { if (p->ready && (streq(getteam(p), cvar_string(va("_k_team1"))) || streq(getteam(p), cvar_string(va("_k_team2"))) )) { CA_OnePlayerStats(p, series_over); } } G_bprint(2, "\n"); } void CA_OnePlayerStats(gedict_t *p, qbool series_over) { qbool use_totals = (round_num == 1 || series_over); float frags; float rkills; float dmg_g; float dmg_t; float vh_rl; float h_rl; float vh_gl; float h_lg; float a_lg; float e_lg; float round_elg; char score[10]; char damage[10]; char dmg_took[10]; char kills[10]; char deaths[10]; char gl_hits[10]; char rl_hits[10]; char rl_directs[10]; char lg_eff[10]; frags = p->s.v.frags; dmg_g = p->ps.dmg_g; dmg_t = p->ps.dmg_t; rkills = frags - ((int)(dmg_g/100.0)); h_rl = p->ps.wpn[wpRL].hits; vh_rl = p->ps.wpn[wpRL].vhits; vh_gl = p->ps.wpn[wpGL].vhits; h_lg = p->ps.wpn[wpLG].hits; a_lg = p->ps.wpn[wpLG].attacks; e_lg = 100.0 * h_lg / max(1, a_lg); if (!use_totals) { round_elg = 100 * (h_lg - p->ca_round_lghit) / max(1, a_lg - p->ca_round_lgfired); } snprintf(score, sizeof(score), "%.0f", use_totals ? p->s.v.frags : p->s.v.frags - p->ca_round_frags); snprintf(damage, sizeof(damage), "%.0f", use_totals ? dmg_g : dmg_g - p->ca_round_dmg); snprintf(dmg_took, sizeof(dmg_took), "%.0f", use_totals ? dmg_t : dmg_t - p->ca_round_dmgt); snprintf(kills, sizeof(kills), "%.0f", use_totals ? rkills : rkills - p->ca_round_kills); snprintf(deaths, sizeof(deaths), "%.0f", use_totals ? p->deaths : p->deaths - p->ca_round_deaths); snprintf(gl_hits, sizeof(gl_hits), "%.0f", use_totals ? vh_gl : vh_gl - p->ca_round_glhit); snprintf(rl_hits, sizeof(rl_hits), "%.0f", use_totals ? vh_rl : vh_rl - p->ca_round_rlhit); snprintf(rl_directs, sizeof(rl_directs), "%.0f", use_totals ? h_rl : h_rl - p->ca_round_rldirect); snprintf(lg_eff, sizeof(lg_eff), "%.0f", use_totals ? e_lg : round_elg); G_bprint(2, "%3s %5s %4s %2s %2s %3s %3s %3s %3s%s %s\n", strneq(score, "0") ? score : "-", strneq(damage, "0") ? damage : "-", strneq(dmg_took, "0") ? dmg_took : "-", strneq(kills, "0") ? kills : "-", strneq(deaths, "0") ? deaths : "-", strneq(gl_hits, "0") ? gl_hits : "-", strneq(rl_hits, "0") ? rl_hits : "-", strneq(rl_directs, "0") ? rl_directs : "-", strneq(lg_eff, "0") ? lg_eff : "-", strneq(lg_eff, "0") ? redtext("%") : " ", getname(p)); p->ca_round_frags = p->s.v.frags; p->ca_round_kills = rkills; p->ca_round_dmg = dmg_g; p->ca_round_dmgt = dmg_t; p->ca_round_deaths = p->deaths; p->ca_round_glhit = vh_gl; p->ca_round_rlhit = vh_rl; p->ca_round_rldirect = h_rl; p->ca_round_lghit = h_lg; p->ca_round_lgfired = a_lg; } void EndRound(int alive_team) { gedict_t *p; static int last_count; char round_or_series[10] = ""; if(!ca_round_pause) { ca_round_pause = 1; last_count = 999999999; pause_time = g_globalvars.time + 8; loser_team = alive_team ? (alive_team == 1 ? 2 : 1) : 0; loser_respawn_time = loser_team ? team_last_alive_time(loser_team) : 999; } pause_count = Q_rint(pause_time - g_globalvars.time); if (pause_count <= 0) { ca_round_pause = 0; round_num++; ra_match_fight = 0; do_endround_stuff = false; print_stats = false; if (!alive_team) { round_num--; // the round repeats in the case of a draw } else if (alive_team == 1) { team1_score++; } else { team2_score++; } } else if (pause_count != last_count) { last_count = pause_count; if (pause_count <= 7) { if (!alive_team) { G_cp2all("Round draw!"); } else { snprintf(round_or_series, sizeof(round_or_series), "%s", ((alive_team == 1 && team1_score == (CA_wins_required()-1)) || (alive_team == 2 && team2_score == (CA_wins_required()-1))) ? "series" : "round"); if ((loser_respawn_time < 2) && (loser_respawn_time > 0)) { G_cp2all("Team \x90%s\x91 wins the %s!\n\n\nTeam %s needed %.3f more seconds", cvar_string(va("_k_team%d", alive_team)), round_or_series, cvar_string(va("_k_team%d", loser_team)), loser_respawn_time); } else { G_cp2all("Team \x90%s\x91 wins the %s!", cvar_string(va("_k_team%d", alive_team)), round_or_series); } } if (!do_endround_stuff) { do_endround_stuff = true; G_cp2all(" "); // clear any centerprint from during the round for (p = world; (p = find_plr(p));) { if (cvar("k_clan_arena") == 2) { if (alive_team && streq(getteam(p), cvar_string(va("_k_team%d", alive_team)))) { stuffcmd(p, "play misc/flagcap.wav\n"); } if (alive_team && streq(getteam(p), cvar_string(va("_k_team%d", alive_team))) && p->in_play) { if (streq(ezinfokey(p, "topcolor"), "13") && streq(ezinfokey(p, "bottomcolor"), "13")) { p->super_time = 8; p->super_damage_finished = 8; } else { p->s.v.items += IT_INVULNERABILITY; } } } } } } if (pause_count < 5 && !print_stats) { print_stats = true; if (alive_team) { // print health of last standing players for (p = world; (p = find_plr(p));) { if (p->in_play && streq(getteam(p), cvar_string(va("_k_team%d", alive_team)))) { G_bprint(2, "%s %s %.0f%s%.0f\n", p->netname, redtext("had"), p->s.v.armorvalue, redtext("/"), p->s.v.health); } } G_bprint(2, "\n%s %s %s", redtext("Team"), cvar_string(va("_k_team%d", alive_team)), redtext("has won the round\n")); } else { G_bprint(2, "\n%s", redtext("The round is a draw!\n")); for (p = world; (p = find_plr(p));) { stuffcmd(p, "play ca/sfdraw.wav\n"); } } print_player_stats(false); team_round_summary(alive_team); } if (pause_count < 4) { ra_match_fight = 1; // disable firing } } } void show_tracking_info(gedict_t *p) { if (!ca_round_pause) { if (p->in_limbo) { snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n%s\n\n\n%d\n\n\n seconds to respawn\n", redtext(p->track_target->netname), (int)ceil(p->seconds_to_respawn)); G_centerprint(p, "%s", p->cptext); } else { snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n%s\n\n\n\n\n\n\n", redtext(p->track_target->netname)); G_centerprint(p, "%s", p->cptext); } } } static void track_player_next(gedict_t *observer) { gedict_t *first_player = ca_get_player(observer); gedict_t *player = first_player; if (!first_player) { return; } if (observer->track_target && ((observer->track_target)->ct != ctPlayer)) { observer->track_target = player; } if (!observer->track_target) { observer->track_target = player; } else { player = ca_find_player(observer->track_target, observer); if (!player) { player = first_player; } observer->track_target = player; } } void CA_player_pre_think(void) { if (isCA()) { CA_show_greeting(self); // Set this player to solid so we trigger checkpoints & teleports during move self->s.v.solid = (ISDEAD(self) ? SOLID_NOT : SOLID_SLIDEBOX); if ((self->s.v.mins[0] == 0) || (self->s.v.mins[1] == 0)) { // This can happen if the world 'squashes' a SOLID_NOT entity, mvdsv will turn into corpse setsize(self, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); } setorigin(self, PASSVEC3(self->s.v.origin)); if ((self->ct == ctPlayer) && (ISDEAD(self) || !self->in_play)) { if (self->tracking_enabled) { if (self->s.v.button2) { if (((int)(self->s.v.flags)) & FL_JUMPRELEASED) { self->s.v.flags = (int)self->s.v.flags & ~FL_JUMPRELEASED; track_player_next(self); } } else { self->s.v.flags = ((int)(self->s.v.flags)) | FL_JUMPRELEASED; } } } if (self->ct == ctPlayer && ra_match_fight && !self->in_play) { track_player(self); // enable tracking by default while dead } if (self->in_play) { self->alive_time = g_globalvars.time - self->time_of_respawn; } // take no damage to health/armor within 1 second of respawn or during endround if (self->in_play && ((self->alive_time >= 1) || !self->round_deaths) && !ca_round_pause) { self->no_pain = false; } else { self->no_pain = true; } // players can't change their color if (self->teamcolor && (self->in_play || (!ca_round_pause && self->in_limbo)) && (strneq(ezinfokey(self, "topcolor"), self->teamcolor) || strneq(ezinfokey(self, "bottomcolor"), self->teamcolor))) { SetUserInfo(self, "topcolor", self->teamcolor, 0); SetUserInfo(self, "bottomcolor", self->teamcolor, 0); } // perma-dead players can't change their color else if (self->teamcolor && !self->in_play && (!self->in_limbo || !self->can_respawn || ca_round_pause) && (strneq(ezinfokey(self, "topcolor"), "0") || strneq(ezinfokey(self, "bottomcolor"), "0"))) { SetUserInfo(self, "topcolor", "0", 0); SetUserInfo(self, "bottomcolor", "0", 0); } // players who aren't in the game must be white and have no team else if (!self->teamcolor && !self->ca_ready && (match_in_progress == 2) && (strneq(ezinfokey(self, "topcolor"), "0") || strneq(ezinfokey(self, "bottomcolor"), "0") || strneq(ezinfokey(self, "team"), ""))) { SetUserInfo(self, "topcolor", "0", 0); SetUserInfo(self, "bottomcolor", "0", 0); SetUserInfo(self, "team", "", 0); } } } void CA_spectator_think(void) { gedict_t *p; p = PROG_TO_EDICT(self->s.v.goalentity); // who we are spectating if (p->ct == ctPlayer && !p->in_play && p->tracking_enabled) { // if the player you're observing is following someone else, hide the player model self->hideentity = EDICT_TO_PROG(p->track_target); } else { self->hideentity = 0; } if (p->ct == ctPlayer) { if (match_in_progress == 2 && ra_match_fight == 2 && round_time > 2 && !ca_round_pause) { // any centerprint the player sees is sent to the spec G_centerprint(self, "%s\n", p->cptext); } } } void CA_Frame(void) { static int last_r; int r; gedict_t *p; if (!isCA() || match_over) { return; } CA_UpdateClients(); if (match_in_progress != 2) { return; } round_time = Q_rint(g_globalvars.time - time_to_start); // if k_clan_arena is 2, we're playing wipeout if (ra_match_fight == 2 && !ca_round_pause && cvar("k_clan_arena") == 2) { int last_alive; int e_last_alive; char str_last_alive[25]; char str_e_last_alive[25]; for (p = world; (p = find_plr(p));) { last_alive = (int)ceil(last_alive_time(p)); e_last_alive = (int)ceil(enemy_last_alive_time(p)); if (p->in_limbo) { if (!p->spawn_delay) { int delay = calc_respawn_time(p, 0); p->spawn_delay = g_globalvars.time + delay; } p->seconds_to_respawn = p->spawn_delay - g_globalvars.time; if (p->seconds_to_respawn <= 0) { p->spawn_delay = 0; snprintf(p->cptext, sizeof(p->cptext), "%s\n", "FIGHT!"); G_centerprint(p, "%s", p->cptext); k_respawn(p, true); p->seconds_to_respawn = calc_respawn_time(p, 1); p->time_of_respawn = g_globalvars.time; // resets alive_time to 0 } else { if (!p->tracking_enabled) { snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n\n\n\n%d\n\n\n seconds to respawn\n", (int)ceil(p->seconds_to_respawn)); G_centerprint(p, "%s", p->cptext); } } } // both you and the enemy are the last alive on your team else if (p->in_play && p->alive_time > 2 && last_alive && e_last_alive) { snprintf(str_last_alive, sizeof(str_last_alive), "%d", last_alive); snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n%s\n\n\n%s\n\n\n\n", redtext("1 on 1"), last_alive == 999 ? " " : redtext(str_last_alive)); G_centerprint(p, "%s", p->cptext); } // you're the last alive on your team versus two or more enemies... hide! else if (p->in_play && p->alive_time > 2 && last_alive) { snprintf(str_last_alive, sizeof(str_last_alive), "%d", last_alive); snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n%s\n\n\n%s\n\n\n\n", redtext("stay alive!"), last_alive == 999 ? " " : redtext(str_last_alive)); G_centerprint(p, "%s", p->cptext); } // only one enemy remains... find him! else if (p->in_play && p->alive_time > 2 && e_last_alive) { snprintf(str_e_last_alive, sizeof(str_e_last_alive), "%d", e_last_alive); snprintf(p->cptext, sizeof(p->cptext), "\n\n\n\n\n\n%s\n\n\n%s\n\n\n\n", "one enemy left", e_last_alive == 999 ? " " : str_e_last_alive); G_centerprint(p, "%s", p->cptext); } else if (p->in_play && p->alive_time > 2) { snprintf(p->cptext, sizeof(p->cptext), " "); G_centerprint(p, "%s", p->cptext); } } } // check if there exist only one team with alive players and others are eluminated, if so then its time to start ca countdown if (ra_match_fight == 2 || (ra_match_fight == 1 && ca_round_pause == 1)) { int alive_team = 0; switch (CA_check_alive_teams(&alive_team)) { case 0: // DRAW, both teams are dead EndRound(0); break; case 1: // Only one team alive EndRound(alive_team); break; default: break; // both teams alive } if (ra_match_fight == 2) { return; } } if ((team1_score >= CA_wins_required()) || (team2_score >= CA_wins_required())) { int winning_team; winning_team = team1_score >= CA_wins_required() ? 1 : 2; G_bprint(2, "%s", redtext("series statistics:\n")); print_player_stats(true); G_bprint(2, "%s %s %s", redtext("Team"), cvar_string(va("_k_team%d", winning_team)), redtext("has won the series!\n\n")); EndMatch(0); return; } if (!ca_round_pause) { if (!ra_match_fight) { // ok start ra timer ra_match_fight = 1; // ra countdown last_r = 999999999; time_to_start = g_globalvars.time + 9; G_cp2all(" "); for (p = world; (p = find_plr(p));) { if (p->ca_ready) { p->can_respawn = true; p->round_deaths = 0; p->round_kills = 0; p->seconds_to_respawn = calc_respawn_time(p, 1); k_respawn(p, false); } G_sprint(p, 2, "round \x90%d\x91 starts in 5 seconds.\n", round_num); snprintf(p->cptext, sizeof(p->cptext), " "); // reset any server print from last round } } r = Q_rint(time_to_start - g_globalvars.time); if (r <= 0) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play ca/sffight.wav\n"); if (p->ca_ready) { p->time_of_respawn = g_globalvars.time; // resets alive_time to 0 } } G_cp2all("%s", "FIGHT!"); ra_match_fight = 2; // rounding suck, so this force readytostart() return true right after FIGHT! is printed time_to_start = g_globalvars.time; } else if (r != last_r) { last_r = r; if (r < 6) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play ca/sf%d.wav\n", r); } G_cp2all("%d\n\n\n \x90%s\x91:%s \x90%s\x91:%s\n", r, cvar_string("_k_team1"), dig3(team1_score), cvar_string("_k_team2"), dig3(team2_score)); // CA_wins_required } if (r == 6) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play ca/sf%d.wav\n", round_num); } } if (r == 7) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play ca/sfround.wav\n"); } G_cp2all("round %d", round_num); } } } } QW-Group-ktx-d05d6ca/src/client.c000066400000000000000000003553321475442401000166540ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ //=========================================================================== // Client // //=========================================================================== #include "g_local.h" vec3_t VEC_ORIGIN = { 0, 0, 0 }; vec3_t VEC_HULL_MIN = { -16, -16, -24 }; vec3_t VEC_HULL_MAX = { 16, 16, 32 }; vec3_t VEC_HULL2_MIN = { -32, -32, -24 }; vec3_t VEC_HULL2_MAX = { 32, 32, 64 }; int modelindex_eyes, modelindex_player, vwep_index; qbool can_prewar(qbool fire); void IdlebotCheck(void); void CheckAll(void); void PlayerStats(void); void ExitCaptain(void); void CheckFinishCaptain(void); void MakeMOTD(void); void ImpulseCommands(void); void StartDie(void); void ZeroFpsStats(void); void item_megahealth_rot(void); void SendSpecInfo(gedict_t *spec, gedict_t *target_client); void del_from_specs_favourites(gedict_t *rm); void item_megahealth_rot(void); extern int g_matchstarttime; void CheckAll(void) { static float next_check = -1; gedict_t *p; if (next_check > g_globalvars.time) { return; } next_check = g_globalvars.time + 20; for (p = world; (p = find_client(p));) { CheckRate(p, ""); } } qbool CheckRate(gedict_t *p, char *newrate) { qbool ret = false; float player_rate, maxrate = 0, minrate = 0; // This is used to check a players rate. If above allowed setting then it kicks em off. player_rate = atof(strnull(newrate) ? (newrate = ezinfokey(p, "rate")) : newrate); if (strnull(newrate)) { return false; // empty rate is special, with new mvdsv mean maximum allowed, so allow it } maxrate = cvar("sv_maxrate"); minrate = cvar("k_minrate"); if (maxrate || minrate) { if (player_rate > maxrate) { G_sprint(p, 2, "\nYour %s setting is too high for this server.\n" "Rate set to %d\n", redtext("rate"), (int)maxrate); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "rate %d\n", (int)maxrate); ret = true; } if (player_rate < minrate) { G_sprint(p, 2, "\nYour %s setting is too low for this server.\n" "Rate set to %d\n", redtext("rate"), (int)minrate); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "rate %d\n", (int)minrate); ret = true; } } return ret; } // timing action #define TA_INFO (1<<0) #define TA_GLOW (1<<1) #define TA_INVINCIBLE (1<<2) #define TA_ALL ( TA_INFO | TA_GLOW | TA_INVINCIBLE ) // check if client lagged or returned from lag void CheckTiming(void) { float timing_players_time = bound(0, cvar("timing_players_time"), 30); int timing_players_action = TA_ALL & (int)cvar("timing_players_action"); gedict_t *p; if (!cvar("allow_timing")) { return; } timing_players_time = timing_players_time ? timing_players_time : 6; // 6 is default for (p = world; (p = find_plr(p));) { if ((p->k_lastPostThink + timing_players_time) < g_globalvars.time) { int firstTime; // guess is we are already know player is lagged firstTime = !p->k_timingWarnTime; // warn and repeat warn after some time if (firstTime || ((p->k_timingWarnTime + 20) < g_globalvars.time)) { if (timing_players_action & TA_INFO) { G_bprint(2, "\x87%s %s is timing out!\n", redtext("WARNING:"), p->netname); } p->k_timingWarnTime = g_globalvars.time; } // ok we are detect - player lagged, so do something, effects is exception if (firstTime) { if (timing_players_action & TA_INVINCIBLE) { p->k_timingTakedmg = p->s.v.takedamage; p->k_timingSolid = p->s.v.solid; p->k_timingMovetype = p->s.v.movetype; p->s.v.takedamage = 0; p->s.v.solid = 0; p->s.v.movetype = 0; SetVector(p->s.v.velocity, 0, 0, 0); // speed is zeroed and not restored } } } else { p->k_timingWarnTime = 0; } // effects stuff if (p->k_timingWarnTime) { if (timing_players_action & TA_GLOW) { // we can't set this in CheckLightEffects() because CheckLightEffects() will not called if client lagged p->s.v.effects = (int)p->s.v.effects | EF_DIMLIGHT; } } else { // moved to CheckLightEffects(), I means CheckLightEffects() will turn EF_DIMLIGHT off } } } /* ============================================================================= LEVEL CHANGING / INTERMISSION ============================================================================= */ float intermission_running = 0; float intermission_exittime = 0; gedict_t *intermission_spot = NULL; char nextmap[64] = ""; void set_nextmap(char *map) { strlcpy(nextmap, strnull(map) ? mapname : map, sizeof(nextmap)); } /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16) This is the camera point for the intermission. Use mangle instead of angle, so you can set pitch or roll as well as yaw. 'pitch roll yaw' */ void SP_info_intermission(void) { // so C can get at it VectorCopy(self->mangle, self->s.v.angles); //self.angles = self.mangle; } typedef struct playerparams_s { float parm1; float parm2; float parm3; float parm4; float parm5; float parm6; float parm7; float parm8; float parm9; float parm10; float parm11; float parm12; float parm13; float parm14; float parm15; float parm16; } playerparams_t; static playerparams_t player_params[MAX_CLIENTS]; static void LoadLevelStartParams(gedict_t *e) { int cl = NUM_FOR_EDICT(e) - 1; if ((cl < 0) || (cl >= MAX_CLIENTS)) { G_Error("LoadLevelStartParams: wrong client"); } g_globalvars.parm1 = player_params[cl].parm1; g_globalvars.parm2 = player_params[cl].parm2; g_globalvars.parm3 = player_params[cl].parm3; g_globalvars.parm4 = player_params[cl].parm4; g_globalvars.parm5 = player_params[cl].parm5; g_globalvars.parm6 = player_params[cl].parm6; g_globalvars.parm7 = player_params[cl].parm7; g_globalvars.parm8 = player_params[cl].parm8; g_globalvars.parm9 = player_params[cl].parm9; g_globalvars.parm10 = player_params[cl].parm10; g_globalvars.parm11 = player_params[cl].parm11; g_globalvars.parm12 = player_params[cl].parm12; g_globalvars.parm13 = player_params[cl].parm13; g_globalvars.parm14 = player_params[cl].parm14; g_globalvars.parm15 = player_params[cl].parm15; g_globalvars.parm16 = player_params[cl].parm16; } void SaveLevelStartParams(gedict_t *e) { int cl = NUM_FOR_EDICT(e) - 1; if ((cl < 0) || (cl >= MAX_CLIENTS)) { G_Error("SaveLevelStartParams: wrong client"); } player_params[cl].parm1 = g_globalvars.parm1; player_params[cl].parm2 = g_globalvars.parm2; player_params[cl].parm3 = g_globalvars.parm3; player_params[cl].parm4 = g_globalvars.parm4; player_params[cl].parm5 = g_globalvars.parm5; player_params[cl].parm6 = g_globalvars.parm6; player_params[cl].parm7 = g_globalvars.parm7; player_params[cl].parm8 = g_globalvars.parm8; player_params[cl].parm9 = g_globalvars.parm9; player_params[cl].parm10 = g_globalvars.parm10; player_params[cl].parm11 = g_globalvars.parm11; player_params[cl].parm12 = g_globalvars.parm12; player_params[cl].parm13 = g_globalvars.parm13; player_params[cl].parm14 = g_globalvars.parm14; player_params[cl].parm15 = g_globalvars.parm15; player_params[cl].parm16 = g_globalvars.parm16; } void InGameParams(void) { // NOTE: DO NOT USE self THERE g_globalvars.parm1 = IT_AXE | IT_SHOTGUN; g_globalvars.parm2 = 100; g_globalvars.parm3 = 0; g_globalvars.parm4 = 25; g_globalvars.parm5 = 0; g_globalvars.parm6 = 0; g_globalvars.parm7 = 0; g_globalvars.parm8 = 1; g_globalvars.parm9 = 0; } void PrewarParams(void) { // NOTE: DO NOT USE self THERE g_globalvars.parm1 = IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING; g_globalvars.parm2 = 1000; g_globalvars.parm3 = 1000; g_globalvars.parm4 = 100; g_globalvars.parm5 = 200; g_globalvars.parm6 = 100; g_globalvars.parm7 = 100; g_globalvars.parm8 = 32; g_globalvars.parm9 = 0; } // used before changing map in non deathmatch mode void NonDMParams(void) { if (ISDEAD(self)) { // NOTE: player will have "empty" backpack if map changin and he/she was dead... // Is it feature or bug? InGameParams(); } else { // remove items self->s.v.items = (int)self->s.v.items & ~( IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD | IT_SUPERHEALTH); // remove super health self->s.v.health = bound(50, self->s.v.health, 100); // give some shells self->s.v.ammo_shells = max(25, self->s.v.ammo_shells); if (!((int)self->s.v.items & ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3))) { self->s.v.armorvalue = 0; } g_globalvars.parm1 = self->s.v.items; g_globalvars.parm2 = self->s.v.health; g_globalvars.parm3 = self->s.v.armorvalue; g_globalvars.parm4 = self->s.v.ammo_shells; g_globalvars.parm5 = self->s.v.ammo_nails; g_globalvars.parm6 = self->s.v.ammo_rockets; g_globalvars.parm7 = self->s.v.ammo_cells; g_globalvars.parm8 = self->s.v.weapon; g_globalvars.parm9 = self->s.v.armortype * 100; } } // // called ONLY on map reload, self is valid there // void SetChangeParms(void) { // ok, server want to change map // check, if matchless mode is active, set ingame params, // we must use k_matchless cvar here because it can be changed during game somehow (via direct server conlose etc) // If matchless mode is not active, set just ordinary prewar stats if (!deathmatch) { NonDMParams(); } else if ( /* match_in_progress == 2 ||*/cvar("k_matchless")) { InGameParams(); } else { PrewarParams(); } g_globalvars.parm11 = self->k_admin; g_globalvars.parm12 = self->k_coach; g_globalvars.parm13 = self->k_stuff; g_globalvars.parm14 = self->ps.handicap; g_globalvars.parm15 = self->ready; } // // called ONLY before player connected, self is _NOT_ valid there // void SetNewParms(void) { if ((match_in_progress == 2) || k_matchLess) { InGameParams(); } else { PrewarParams(); } g_globalvars.parm11 = 0; g_globalvars.parm12 = 0; g_globalvars.parm13 = 0; g_globalvars.parm14 = 0; g_globalvars.parm15 = 0; } // // used in k_respawn() // void SetRespawnParms(void) { if (!deathmatch) { if (streq(mapname, "start")) { InGameParams(); // take away all stuff on starting new episode } else { LoadLevelStartParams(self); } } else if ((match_in_progress == 2) || k_matchLess) { InGameParams(); } else { PrewarParams(); } if (self->connect_time == g_globalvars.time) { // g_globalvars.parm11 contain self->k_admin // g_globalvars.parm13 contain self->k_stuff // g_globalvars.parm14 contain self->ps.handicap } else { g_globalvars.parm11 = 0; g_globalvars.parm12 = 0; g_globalvars.parm13 = 0; g_globalvars.parm14 = 0; g_globalvars.parm15 = 0; } } // called from PutClientInServer void DecodeLevelParms(void) { self->s.v.items = g_globalvars.parm1; self->s.v.health = g_globalvars.parm2; self->s.v.armorvalue = g_globalvars.parm3; self->s.v.ammo_shells = g_globalvars.parm4; self->s.v.ammo_nails = g_globalvars.parm5; self->s.v.ammo_rockets = g_globalvars.parm6; self->s.v.ammo_cells = g_globalvars.parm7; self->s.v.weapon = g_globalvars.parm8; self->s.v.armortype = g_globalvars.parm9 * 0.01; if (g_globalvars.parm11) { self->k_admin = g_globalvars.parm11; } if (g_globalvars.parm12) { self->k_coach = g_globalvars.parm12; } if (g_globalvars.parm13) { self->k_stuff = g_globalvars.parm13; } if (g_globalvars.parm14) { self->ps.handicap = g_globalvars.parm14; } if (g_globalvars.parm15) { self->ready = g_globalvars.parm15; } } gedict_t* Do_FindIntermission(char *info_name) { gedict_t *spot; int i; i = find_cnt( FOFCLSN, info_name); i = (i ? g_random() * i : -1); // pick a random one return (spot = find_idx(i, FOFCLSN, info_name)); } /* ============ FindIntermission Returns the entity to view from ============ */ gedict_t* FindIntermission(void) { gedict_t *spot; if ((spot = Do_FindIntermission("info_intermission"))) { return spot; } if ((spot = Do_FindIntermission("info_player_start"))) { return spot; } if ((spot = Do_FindIntermission("info_player_deathmatch"))) { return spot; } if ((spot = Do_FindIntermission("info_player_coop"))) { return spot; } if ((spot = Do_FindIntermission("info_player_start2"))) { return spot; } // G_Error( "FindIntermission: no spot" ); // return NULL; return world; } void GotoNextMap(void) { char newmap[64] = { 0 }; if (trap_cvar("samelevel")) { // if samelevel is set, stay on same level char *entityfile = cvar_string("k_entityfile"); if (!strnull(entityfile)) { strlcpy(newmap, entityfile, sizeof(newmap)); } else { strlcpy(newmap, mapname, sizeof(newmap)); } } else { extern char* SelectMapInCycle(char *buf, int buf_size); if (deathmatch || cvar("k_force_mapcycle")) { SelectMapInCycle(newmap, sizeof(newmap)); } } if (!strnull(newmap)) { changelevel(newmap); } else if (!strnull(nextmap)) { changelevel(nextmap); } else if (!strnull(mapname)) { changelevel(mapname); } else { changelevel("start"); } } /* ============ IntermissionThink When the player presses attack or jump, change to the next level ============ */ void IntermissionThink(void) { if (g_globalvars.time < intermission_exittime) { return; } if (!self->s.v.button0 && !self->s.v.button1 && !self->s.v.button2) { return; } if (deathmatch) { GotoNextMap(); } else { ExitIntermission(); } } /* ============ SendIntermissionToClient If a client connects during intermission, send svc_intermission to him personally ============ */ void SendIntermissionToClient(void) { if (!intermission_spot) { G_Error("SendIntermissionToClient: !intermission_spot"); } g_globalvars.msg_entity = EDICT_TO_PROG(self); // play intermission music WriteByte(MSG_ONE, SVC_CDTRACK); WriteByte(MSG_ONE, 3); WriteByte(MSG_ONE, SVC_INTERMISSION); WriteCoord(MSG_ONE, intermission_spot->s.v.origin[0]); WriteCoord(MSG_ONE, intermission_spot->s.v.origin[1]); WriteCoord(MSG_ONE, intermission_spot->s.v.origin[2]); WriteAngle(MSG_ONE, intermission_spot->mangle[0]); WriteAngle(MSG_ONE, intermission_spot->mangle[1]); WriteAngle(MSG_ONE, intermission_spot->mangle[2]); setorigin(self, PASSVEC3(intermission_spot->s.v.origin)); } /* ============ execute_changelevel The global "nextmap" has been set previously. Take the players to the intermission spot ============ */ static void intermission_set_player_flags(gedict_t *player) { player->s.v.takedamage = DAMAGE_NO; player->s.v.solid = SOLID_NOT; player->s.v.movetype = MOVETYPE_NONE; player->s.v.modelindex = 0; // KTEAMS: make players invisible player->model = ""; } void execute_changelevel(void) { intermission_running = 1; // enforce a wait time before allowing changelevel intermission_exittime = g_globalvars.time + 1 + max(1, cvar("demo_scoreslength")); intermission_spot = FindIntermission(); // play intermission music WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 3); WriteByte( MSG_ALL, SVC_INTERMISSION); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[0]); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[1]); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[2]); WriteAngle( MSG_ALL, intermission_spot->mangle[0]); WriteAngle( MSG_ALL, intermission_spot->mangle[1]); WriteAngle( MSG_ALL, intermission_spot->mangle[2]); for (other = world; (other = find_plr(other));) { intermission_set_player_flags(other); // take screenshot if requested if (iKey(other, "kf") & KF_SCREEN) { stuffcmd_flags(other, STUFFCMD_IGNOREINDEMO, "wait; wait; wait; wait; wait; wait; screenshot\n"); } } } void changelevel_touch(void) { if (other->ct != ctPlayer) { return; } if (match_in_progress != 2) { return; } if (deathmatch) { if (isCTF()) { // ctf has always allowed players to hide in exits, etc } else { // TODO: qqshka: I have an idea to teleport players to info_player_deathmatch instead... other->deathtype = dtCHANGELEVEL; T_Damage(other, self, self, 50000); } return; } G_bprint( PRINT_HIGH, "%s exited the level\n", other->netname); set_nextmap(self->map); activator = other; SUB_UseTargets(); self->touch = (func_t) SUB_Null; // we can't move people right now, because touch functions are called // in the middle of C movement code, so set a think time to do it self->think = (func_t) execute_changelevel; self->s.v.nextthink = g_globalvars.time + 0.1; } /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION When the player touches this, he gets sent to the map listed in the "map" variable. Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats. */ void SP_trigger_changelevel(void) { if (!self->map) { G_Error("chagnelevel trigger doesn't have map"); } // qqshka: yeah, treat k_remove_end_hurt as hint to remove some shit from this level, // not only hurt trigger if (streq("end", mapname) && cvar("k_remove_end_hurt") && (cvar("k_remove_end_hurt") != 2)) { soft_ent_remove(self); } else { InitTrigger(); self->touch = (func_t) changelevel_touch; } } /* go to the next level for deathmatch */ void NextLevel(void) { gedict_t *o; char *entityfile; if (k_bloodfest || cvar("k_clan_arena")) { return; } if (nextmap[0]) { return; // already done } entityfile = cvar_string("k_entityfile"); if (!strnull(entityfile)) { set_nextmap(entityfile); } else { set_nextmap(mapname); } o = spawn(); o->map = mapname; o->classname = "trigger_changelevel"; o->think = (func_t) execute_changelevel; o->s.v.nextthink = g_globalvars.time + 0.1; /* if ( streq( mapname, "start" ) ) { if ( !trap_cvar( "registered" ) ) { strlcpy( mapname, "e1m1", sizeof(mapname) ); } else if ( !( ( int ) ( g_globalvars.serverflags ) & 1 ) ) { strlcpy( mapname, "e1m1", sizeof(mapname) ); g_globalvars.serverflags = ( int ) ( g_globalvars.serverflags ) | 1; } else if ( !( ( int ) ( g_globalvars.serverflags ) & 2 ) ) { strlcpy( mapname, "e2m1", sizeof(mapname) ); g_globalvars.serverflags = ( int ) ( g_globalvars.serverflags ) | 2; } else if ( !( ( int ) ( g_globalvars.serverflags ) & 4 ) ) { strlcpy( mapname, "e3m1", sizeof(mapname) ); g_globalvars.serverflags = ( int ) ( g_globalvars.serverflags ) | 4; } else if ( !( ( int ) ( g_globalvars.serverflags ) & 8 ) ) { strlcpy( mapname, "e4m1", sizeof(mapname) ); g_globalvars.serverflags = ( int ) ( g_globalvars.serverflags ) - 7; } o = spawn(); o->map = mapname; } else { // find a trigger changelevel o = find( world, FOFS( s.v.classname ), "trigger_changelevel" ); if ( !o ) { // go back to same map if no trigger_changelevel o = spawn(); o->map = mapname; } } set_nextmap( o->map ); if ( o->s.v.nextthink < g_globalvars.time ) { o->think = ( func_t ) execute_changelevel; o->s.v.nextthink = g_globalvars.time + 0.1; } */ } /* ============================================================================= PLAYER GAME EDGE FUNCTIONS ============================================================================= */ void SP_info_player_deathmatch(void) { gedict_t *spot; vec3_t saved_org; int i = 0; for (spot = world; (spot = find(spot, FOFCLSN, self->classname)); i++) { if (spot == self) { self->cnt = i; } } // some maps like aerowalk or ztndm* have spawn points hanging some distance // above the ground, fix them setsize(self, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); VectorCopy(self->s.v.origin, saved_org); HM_name_map_spawn(self); droptofloor(self); if (self->s.v.origin[2] < saved_org[2] - 64) setorigin(self, PASSVEC3(saved_org)); setsize(self, 0, 0, 0, 0, 0, 0); } // I'v put next code in function, since it appear frequently void k_respawn(gedict_t *p, qbool body) { gedict_t *swap = self; self = p; // warning self->s.v.deadflag = DEAD_RESPAWNABLE; self->wreg_attack = 0; self->s.v.button0 = 0; self->s.v.button1 = 0; self->s.v.button2 = 0; // make a copy of the dead body for appearances sake if (body) { CopyToBodyQue(self); } // set default spawn parms SetRespawnParms(); // respawn PutClientInServer(); self = swap; } /* ============ ClientKill Player entered the suicide command ============ */ void ClientKill(void) { if (cvar("sv_paused")) { return; // kill not allowed during pause } if (k_standby) { return; } if (isRACE() && race_handle_event(self, NULL, "kill")) { return; } if (ISDEAD(self) || !self->s.v.takedamage) { return; // already dead } if (self->ct != ctPlayer) { return; // not a player } if (isRA()) { G_sprint(self, PRINT_HIGH, "Can't suicide in RA mode\n"); return; } if (isCA() && match_in_progress) { if ((ra_match_fight != 2) || ca_round_pause) { G_sprint (self, PRINT_HIGH, "Can't suicide at this time\n"); return; } else if ((ra_match_fight == 2) && !ca_round_pause) { self->can_respawn = false; // No respawning after suicide in wipeout mode self->seconds_to_respawn = 999; // no countdown } } if (isCTF() && (match_in_progress == 2) && ((g_globalvars.time - match_start_time) < 10)) { G_sprint(self, PRINT_HIGH, "Can't suicide during first 10 seconds of CTF match\n"); return; } if (g_globalvars.time < self->suicide_time) { G_sprint(self, PRINT_HIGH, "Only one suicide in 1 second\n"); return; } self->suicide_time = g_globalvars.time + 1; self->deathtype = dtSUICIDE; T_Damage(self, self, self, 999999); } float CheckSpawnPoint(vec3_t v) { return false; } /* ============ SelectSpawnPoint Returns the entity to spawn at ============ */ gedict_t* Sub_SelectSpawnPoint(char *spawnname) { gedict_t *spot; gedict_t *spots; // chain of "valid" spots gedict_t *thing; int numspots; // count of "valid" spots int totalspots; int pcount; int k_spw = cvar("k_spw"); int weight_sum = 0; // used by "fair spawns" // testinfo_player_start is only found in regioned levels spot = find(world, FOFCLSN, "testplayerstart"); if (spot) { return spot; } // K_SPW_0_NONRANDOM changes "Normal QW respawns" to "pre-qtest nonrandom respawns" #ifdef K_SPW_0_NONRANDOM if (k_spw == 0) { static gedict_t *last_spot = g_edicts; // basically, g_edicts is same as world, but we can't initialize static variable with world. last_spot = ez_find(last_spot, spawnname); if (!last_spot) // wrap around { last_spot = ez_find(world, spawnname); } return last_spot; } #endif // ok, find all spots that don't have players nearby spots = world; totalspots = numspots = 0; for (spot = world; (spot = find(spot, FOFCLSN, spawnname));) { totalspots++; pcount = 0; // find count of nearby players for 'spot' for (thing = world; (thing = trap_findradius(thing, spot->s.v.origin, 84));) { if ((thing->ct != ctPlayer) || ISDEAD(thing) || (thing == self)) { continue; // ignore non player, or dead played, or self } // k_spw 2 and 3 and 4 feature, if player is spawned not far away and run // around spot - treat this spot as not valid. // k_1spawn store this "not far away" time. // k_1spawn is _also_ set after player passed teleport if (!(((k_spw == 2) || (k_spw == 3) || (k_spw == 4)) && (match_in_progress == 2) && (thing->k_1spawn < g_globalvars.time))) { // G_bprint(2, "ignore player: %s\n", thing->netname); pcount++; // ignore spot } } // NOTE: k_spw != 4 if (!k_yawnmode && k_spw && (k_spw != 4) && (match_in_progress == 2) && (self->k_lastspawn == spot)) { // G_bprint(2, "ignore spot\n"); pcount++; // ignore this spot in this case, protection from spawn twice on the same spot } if (!pcount) // valid spawn spot { spot->s.v.goalentity = EDICT_TO_PROG(spots); spots = spot; numspots++; // Calculate weight sum (only goes up to MAX_SPAWN_WEIGHTS spots) if (totalspots && totalspots <= MAX_SPAWN_WEIGHTS) { weight_sum += self->spawn_weights[totalspots - 1]; } } } if (match_in_progress == 2) // protect(in some case) player from be spawnfragged for some time { self->k_1spawn = g_globalvars.time + 2.6; } if (!numspots) { // ack, they are all full, just pick one at random // G_bprint (PRINT_HIGH, "%s\n", "Ackk! All spots are full. Selecting random spawn spot"); if (!(spot = find_idx(i_rnd(0, totalspots - 1), FOFCLSN, spawnname))) { totalspots = 1; // proper count is not so important, something going wrong anyway... if (!(spot = Do_FindIntermission("info_player_deathmatch"))) { if (!(spot = Do_FindIntermission("info_player_start"))) { spot = world; } } } if (!match_in_progress || k_spw == 1 || (k_spw == 2 && !k_checkx)) { vec3_t v1, v2; trap_makevectors(isRA() ? spot->mangle : spot->s.v.angles); // stupid ra uses mangles instead of angles for (thing = world; (thing = trap_findradius(thing, spot->s.v.origin, 84));) { if ((thing->ct != ctPlayer) || ISDEAD(thing) || (thing == self)) { continue; // ignore non player, or dead played, or self } VectorMA(thing->s.v.origin, -15.0, g_globalvars.v_up, v1); VectorMA(v1, 160.0, g_globalvars.v_forward, v2); traceline(PASSVEC3(v1), PASSVEC3(v2), false, thing); VectorCopy(g_globalvars.trace_endpos, v1); VectorMA(v1, 30.0, g_globalvars.v_forward, v2); traceline(PASSVEC3(v1), PASSVEC3(v2), false, thing); if (g_globalvars.trace_fraction < 1) { VectorMA(g_globalvars.trace_endpos, -35.0, g_globalvars.v_forward, v1); } VectorMA(v1, 15.0, g_globalvars.v_up, v2); setorigin(thing, PASSVEC3(v2)); // FIXME: wtf is going on? } } if ((totalspots > 2) && (match_in_progress == 2)) { self->k_lastspawn = spot; } return spot; } // We now have the number of spots available on the map in numspots // Generate a random number between 0 and numspots // Yawnmode: use new "fair spawns" model // Because of array limits, fall back to old spawn model on maps with more than MAX_SPAWN_WEIGHTS spots // - Molgrum if (k_yawnmode && (match_in_progress == 2) && (totalspots <= MAX_SPAWN_WEIGHTS)) { float f; gedict_t *spawnp; int i = 0; // Setup randomization f = i_rnd(0, weight_sum); // Get a random spawn point for (spot = spots; i < numspots; i++) { f = f - self->spawn_weights[(int)spot->cnt]; // Finished randomizing if (f < 0) { break; } // Prevent spawn spot from becoming world if (PROG_TO_EDICT(spot->s.v.goalentity ) != world) { spot = PROG_TO_EDICT(spot->s.v.goalentity); } } spawnp = spot; spot = spots; // Fix weights f = self->spawn_weights[(int)spawnp->cnt] / 2; for (i = 0; i < numspots; i++) { if (spot == spawnp) { self->spawn_weights[(int)spot->cnt] -= f; } else { self->spawn_weights[(int)spot->cnt] += (f / (float)(numspots - 1)); } spot = PROG_TO_EDICT(spot->s.v.goalentity); } return spawnp; } else { // Original spawnmodes numspots = i_rnd(0, numspots - 1); for (spot = spots; numspots > 0; numspots--) { spot = PROG_TO_EDICT(spot->s.v.goalentity); } if ((totalspots > 2) && (match_in_progress == 2)) { self->k_lastspawn = spot; } return spot; } } gedict_t* SelectSpawnPoint(char *spawnname) { gedict_t *k_lastspawn = self->k_lastspawn; // we need remember this before calling Sub_SelectSpawnPoint() gedict_t *spot = Sub_SelectSpawnPoint(spawnname); // k_spw 4 feature, recheck spawn poit second time if we select same spawn point in row, so it low chance to get same spawn point if ((match_in_progress == 2) && (k_lastspawn == spot) && (cvar("k_spw") == 4 || cvar("k_clan_arena") == 2)) { self->k_lastspawn = k_lastspawn; spot = Sub_SelectSpawnPoint(spawnname); } return spot; } qbool CanConnect(void) { gedict_t *p; char *t; int from; int usrid; int tmid; int playerCount = 0; if (k_sv_locktime && !VIP(self)) { // don't allow none vip in this case int seconds = k_sv_locktime - g_globalvars.time; G_sprint(self, 2, "%s: %d second%s\n", redtext("server is temporary locked"), seconds, count_s(seconds)); // can't connect return false; } else if (!match_in_progress || k_matchLess || k_bloodfest) { // no checks in matchLess mode, in bloodfest, or if there is no game in progress if (!k_bloodfest || !match_in_progress) { // in non bloodfest mode always announce but do not announce during bloodfest round. G_bprint(2, "%s entered the game\n", self->netname); } // can connect return true; } else if (cvar("k_lockmode") == 2) { // don't allow anyway G_sprint(self, 2, "Match in progress, server locked\n" "Please reconnect as spectator\n"); // can't connect return false; } else if ((cvar("k_lockmode") == 1) || isCA()) { // allow players in existing teams, but different behavior for team/duel/ffa/CA if (isDuel() || isFFA()) { // don't allow if no ghost with same name as for self for (from = 1, p = world; (p = find_plrghst(p, &from));) { if (streq(getname(p), self->netname)) { break; // don't kick, find "ghost" with equal name } } if (!p) { G_sprint(self, 2, "%s in progress, server locked\n" "Please reconnect as spectator\n", isDuel() ? "Duel" : "Match"); // can't connect return false; } } else if (isCA()) { // do nothing here } else if ((isTeam() || isCTF())) { // don't allow if no ghost or player with team as for self t = getteam(self); for (from = 0, p = world; (p = find_plrghst(p, &from));) { if (p != self && streq(getteam(p), t)) { break; // don't kick, find "player" or "ghost" with equal team } } if (!p) { G_sprint(self, 2, "Match in progress, server locked\n" "Set your team before connecting\n" "or reconnect as spectator\n"); // can't connect return false; } // only allow a player to (re)connect, if the // maximum number of player per team is not yet reached for (p = world; (p = find_plr_same_team(p, t));) { // count players in the team where we are about to join ++playerCount; } if (playerCount >= maxPlayerCount) { G_sprint(self, 2, "Match in progress, server locked\n" "Your team has already maximum player count\n" "Reconnect as spectator\n"); // can't connect return false; } } else { // unknown mode, kick anyway G_sprint(self, 2, "Match in progress, server locked\n" "Please reconnect as spectator\n"); // can't connect return false; } } // don't allow empty team in any case if (tp_num() && strnull(getteam(self)) && !isCA()) { G_sprint(self, 2, "Match in progress,\n" "Set your team before connecting\n" "or reconnect as spectator\n"); // can't connect return false; } // you have to be on read or blue team in CTF mode if (isCTF() && (strneq(getteam(self), "red") && strneq(getteam(self), "blue"))) { G_sprint(self, 2, "Match in progress,\n" "Set your team (red or blue) before connecting\n" "or reconnect as spectator\n"); // can't connect return false; } // don't allow if exclusive if ((CountPlayers() >= k_attendees) && cvar("k_exclusive")) { G_sprint(self, 2, "Sorry, server is full\n" "Please reconnect as spectator\n"); // can't connect return false; } if (match_in_progress != 2) // actually that match_in_progress == 1 { G_bprint(2, "%s entered the game\n", self->netname); // can connect return true; } for (usrid = 1; usrid < k_userid; usrid++) // search for ghost for this player (localinfo) { if (streq(ezinfokey(world, va("%d", (int)usrid)), self->netname)) { break; } } if (usrid < k_userid) // ghost probably found (localinfo) { for (p = world; (p = find(p, FOFCLSN, "ghost"));) // search ghost entity { if (p->cnt2 == usrid) { break; } } if (p) // found ghost entity { qbool isCa = isCA(); qbool teamEqual = streq(getteam(self), getteam(p)); // check teams only for team mode if ((isTeam() || isCTF()) && !teamEqual && !isCa) { G_sprint(self, 2, "Please join your old team and reconnect\n"); return false; // _can't_ connect } // In CA, if current team doesn't match old team then just don't restore stats/gamestate // Otherwise restore frags and set ca_ready else if (isCa && !teamEqual) { // if player's team isn't what it was before, then he will be a "dead" player until the match is over self->ca_ready = 0; G_bprint(2, "%s entered the game\n", self->netname); } else { ghostClearScores(p); self->ps = p->ps; // restore player stats self->s.v.frags = p->s.v.frags; self->deaths = p->deaths; self->friendly = p->friendly; self->ca_ready = isCa ? p->ca_ready : 0; // return to the game if playing clan arena if (isCa && !self->ca_ready) { G_bprint(2, "%s entered the game\n", self->netname); } else if (isTeam() || isCTF()) { self->k_teamnum = p->k_teamnum; // we alredy have team in localinfo G_bprint(2, "%s \220%s\221 %s %d %s%s\n", self->netname, getteam(self), redtext("rejoins the game with"), (int)self->s.v.frags, redtext("frag"), redtext(count_s(self->s.v.frags))); } else { self->k_teamnum = 0; // force check is we have team in localinfo or not below G_bprint(2, "%s %s %d %s%s\n", self->netname, redtext("rejoins the game with"), (int)self->s.v.frags, redtext("frag"), redtext(count_s(self->s.v.frags))); } localcmd("localinfo %d \"\"\n", usrid); // remove ghost in localinfo ent_remove(p); // remove ghost entity } } else // ghost entity not found { localcmd("localinfo %d \"\"\n", usrid); // remove ghost in localinfo if (isTeam() || isCTF()) { G_bprint(2, "%s \220%s\221 %s\n", self->netname, getteam(self), redtext("reenters the game without stats")); } else { G_bprint(2, "%s %s\n", self->netname, redtext("reenters the game without stats")); } } } else { // ghost not found (localinfo) if (isCA()) { G_bprint(2, "%s entered the game\n", self->netname); } else if (isTeam() || isCTF()) { G_bprint(2, "%s \220%s\221 %s\n", self->netname, getteam(self), redtext("arrives late")); } else { G_bprint(2, "%s %s\n", self->netname, redtext("arrives late")); } } // check is we have team in localinfo or not if (!strnull(t = getteam(self))) { for (tmid = 665; tmid < k_teamid && !self->k_teamnum;) { tmid++; if (streq(t, ezinfokey(world, va("%d", tmid)))) { self->k_teamnum = tmid; } } if (!self->k_teamnum) // team not found in localinfo, so put it in { tmid++; localcmd("localinfo %d \"%s\"\n", tmid, getteam(self)); k_teamid = tmid; self->k_teamnum = tmid; } } else { self->k_teamnum = 666; } return true; } //////////////// // GlobalParams: // time // self // params /////////////// void ClientConnect(void) { gedict_t *p; int i, totalspots; VIP_ShowRights(self); k_nochange = 0; if (coop) { // set proper team. SetUserInfo(self, "team", "coop", 0); // sends this to client - so he get right team too. stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team " "coop" "\n"); } // qqshka: force damn colors in CTF. if (isCTF()) { int red = 0; // Keeps track of which team and colors to set for new player // If matchless CTF, make sure team is red or blue if (k_matchLess) { if (!(streq(getteam(self), "red") || streq(getteam(self), "blue"))) { // Compare number of blue and red players. If red > blue (i.e. red > 0), set new player to blue. gedict_t *p; for (p = world; (p = find_plr(p));) { if (streq(getteam(p), "red")) { red++; } else { red--; } } SetUserInfo(self, "team", red > 0 ? "blue" : "red", 0); if (red > 0) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team " "blue" "\n"); } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team " "red" "\n"); } G_bprint(PRINT_HIGH, "%s automatically set to team: %s\n", self->netname, redtext(red > 0 ? "blue" : "red")); } G_sprint(self, PRINT_HIGH, "To change teams, /disconnect, /team red or /team blue, then /reconnect\n"); } // Force colors red = streq(getteam(self), "red"); // set proper colors. SetUserInfo(self, "topcolor", red ? "4" : "13", 0); SetUserInfo(self, "bottomcolor", red ? "4" : "13", 0); // sends this to client - so he get right colors too. stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %s\n", red ? "4" : "13"); } if (!CanConnect()) { stuffcmd(self, "disconnect\n"); // FIXME: stupid way return; } newcomer = self; self->ct = ctPlayer; self->classname = "player"; self->k_accepted = 1; // ok, we allowed to connect // if bloodfest is active then set player as unready and kill him later in PutClientInServer() // if match in progress then set client ready anyway. // if there matchless mode then set client ready too. if (k_bloodfest) { self->ready = 0; } else { self->ready = ((match_in_progress || k_matchLess) ? 1 : 0); } // if the guy started connecting during intermission and // thus missed the svc_intermission, we'd better let him know if (intermission_running) { SendIntermissionToClient(); } // ILLEGALFPS[ // Zibbo's frametime checking code self->uptimebugpolicy = 0; self->real_time = 0; // delay on checking/displaying illegal FPS. self->fDisplayIllegalFPS = g_globalvars.time + 10 + g_random() * 5; self->fIllegalFPSWarnings = 0; ZeroFpsStats(); // ILLEGALFPS] CheckRate(self, ""); if (k_captains == 2) { // in case of team picking, check if there is a free spot for player number 1-16 int i; for (i = 1, p = world; p && i <= MAX_CLIENTS; i++) { for (p = world; (p = find_plr(p)) && (p == self || p->s.v.frags != i);) { ; // empty } } // if we found a spot, set the player into it if (!p) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color 0\nteam \"\"\nskin \"\"\n"); self->s.v.frags = i - 1; } } if (isRA()) { ra_in_que(self); // put cleint in ra queue, so later we can move it to loser or winner } // Yawnmode: reset spawn weights at server join (can handle max MAX_SPAWN_WEIGHTS spawn points atm) // Just count the spots totalspots = find_cnt(FOFCLSN, "info_player_deathmatch") + find_cnt(FOFCLSN, "info_player_team1_deathmatch") + find_cnt(FOFCLSN, "info_player_team2_deathmatch"); // Don't use this spawn model for maps with more than MAX_SPAWN_WEIGHTS spawns (shouldn't even happen) if (totalspots <= MAX_SPAWN_WEIGHTS) { // Set the spawn weights to number of spots for (i = 0; i < totalspots; i++) { self->spawn_weights[i] = totalspots; } } SendSpecInfo(NULL, self); // get all spectator info MakeMOTD(); #ifdef BOT_SUPPORT BotClientConnectedEvent (self); #endif } //////////////// // GlobalParams: // time // self // called after ClientConnect /////////////// void PutClientInServer(void) { gedict_t *spot; int items; int tele_flags; int i; self->trackent = 0; self->ca_alive = (isCA() ? CA_CheckAlive(self) : true); self->deathtype = dtNONE; self->classname = "player"; self->s.v.health = 100; self->s.v.takedamage = DAMAGE_AIM; self->s.v.solid = SOLID_SLIDEBOX; self->s.v.movetype = MOVETYPE_WALK; self->show_hostile = 0; self->s.v.max_health = 100; self->s.v.flags = FL_CLIENT; self->air_finished = g_globalvars.time + 12; self->dmg = 2; // initial water damage self->super_damage_finished = 0; self->radsuit_finished = 0; self->invisible_finished = 0; self->invincible_finished = 0; self->s.v.effects = 0; self->spawn_time = g_globalvars.time; self->axhitme = 0; self->lastwepfired = 0; self->lgc_state = lgcUndershaft; self->control_start_time = 0; for (i = itNONE; i < itMAX; i++) { self->it_pickup_time[i] = 0; } for (i = wpNONE; i < wpMAX; i++) { self->wp_pickup_time[i] = 0; } // the spawn falling damage bug workaround self->jump_flag = 0; self->swim_flag = 0; // brokenankle self->brokenankle = 0; // ctf self->on_hook = false; self->hook_out = false; self->maxspeed = cvar("sv_maxspeed"); // qqshka - ctf stuff, discard haste rune modifier after u die self->regen_time = -1; self->carrier_hurt_time = -1; self->ctf_flag = 0; self->invincible_time = 0; DecodeLevelParms(); if (!((int)self->s.v.weapon & (int)self->s.v.items)) self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); self->attack_finished = g_globalvars.time; self->th_pain = player_pain; self->th_die = PlayerDie; self->s.v.deadflag = DEAD_NO; // paustime is set by teleporters to keep the player from moving a while self->pausetime = 0; if (isHoonyModeAny() && (spot = HM_choose_spawn_point(self))) { // Nothing more to do } #ifdef BOT_SUPPORT else if (FrogbotOptionEnabled(FB_OPTION_DEBUG_MOVEMENT) && self->isBot && match_in_progress && streq(mapname, "povdmm4")) { gedict_t *highest = NULL; for (spot = world; (spot = ez_find(spot, "info_player_deathmatch"));) { if ((highest == NULL) || (spot->s.v.origin[2] > highest->s.v.origin[2])) { highest = spot; } } spot = highest; } #endif else if (deathmatch || k_bloodfest) { // first spawn in CTF on corresponding base, later used info_player_deathmatch. // qqshka: I found that it sux and added variable which force players spawn ONLY on the base, // so maps like qwq3wcp9 works fine! if (isCTF() && ((match_start_time == g_globalvars.time) || (cvar("k_ctf_based_spawn") == 1))) { spot = SelectSpawnPoint( streq(getteam(self), "red") ? "info_player_team1" : "info_player_team2"); } // Pick between neutral spawn points in the mid of the map and spawn points within home base // to avoid the fish in a barrel problem where flag position is overrun by str/quad/pent and // players are instagibbed over and over again. else if (isCTF() && (cvar("k_ctf_based_spawn") == 2)) { spot = SelectSpawnPoint(g_random() <= 0.5 ? "info_player_deathmatch" : streq(getteam(self), "red") ? "info_player_team1_deathmatch" : "info_player_team2_deathmatch"); } else if (isRA() && (isWinner(self) || isLoser(self))) { spot = SelectSpawnPoint("info_teleport_destination"); } else { spot = SelectSpawnPoint("info_player_deathmatch"); } } else { spot = SelectSpawnPoint(coop ? "info_player_coop" : "info_player_start"); } HM_log_spawn_point(self, spot); VectorCopy(spot->s.v.origin, self->s.v.origin); self->s.v.origin[2] += 1; if (isRA()) { VectorCopy(spot->mangle, self->s.v.angles); } else { VectorCopy(spot->s.v.angles, self->s.v.angles); } self->s.v.fixangle = true; // oh, this is a hack! setmodel(self, "progs/eyes.mdl"); modelindex_eyes = self->s.v.modelindex; setmodel(self, "progs/player.mdl"); modelindex_player = self->s.v.modelindex; if (intermission_running) { intermission_set_player_flags(self); } setsize(self, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); SetVector(self->s.v.view_ofs, 0, 0, 22); SetVector(self->s.v.velocity, 0, 0, 0); self->walkframe = 0; player_stand1(); trap_makevectors(self->s.v.angles); // Play sound and add tele splash. // In RA mode do that only for winner or loser. // Do NOT do that in RACE. tele_flags = TFLAGS_FOG_DST_SPAWN; if (isRACE()) { race_set_one_player_movetype_and_etc(self); } else if (isRA()) { if (isWinner(self) || isLoser(self)) { if (initial_match_spawns) { self->spawn_effect_queued = true; } else { tele_flags |= TFLAGS_FOG_DST | TFLAGS_SND_DST; } } } else if (isCA()) { if (ISLIVE(self)) { if (initial_match_spawns) { self->spawn_effect_queued = true; } else { tele_flags |= TFLAGS_FOG_DST | TFLAGS_SND_DST; } } } else { if (initial_match_spawns) { self->spawn_effect_queued = true; } else { tele_flags |= TFLAGS_FOG_DST | TFLAGS_SND_DST; } } if (isRA()) { ra_PutClientInServer(); // drop down to best weapon actually hold if (!((int)self->s.v.weapon & (int)self->s.v.items)) { self->s.v.weapon = W_BestWeapon(); } W_SetCurrentAmmo(); // important shit, not only ammo teleport_player(self, self->s.v.origin, self->s.v.angles, tele_flags); #ifdef BOT_SUPPORT BotClientEntersEvent(self, spot); #endif return; } if (spot->s.v.items && isHoonyModeAny()) { char *armorExplanation = "a"; float armortype = 0.0f; float armorvalue = 0.0f; items = spot->s.v.items; if (items & IT_ARMOR3) { armortype = (k_yawnmode ? 0.8 : 0.8); // Yawnmode: changed armor protection armorvalue = max(0, min(spot->s.v.armorvalue, 200)); armorExplanation = "&cf00ra&cfff"; } else if (items & IT_ARMOR2) { armortype = (k_yawnmode ? 0.6 : 0.6); // Yawnmode: changed armor protection armorvalue = max(0, min(spot->s.v.armorvalue, 150)); armorExplanation = "&cff0ya&cfff"; } else if (items & IT_ARMOR1) { armortype = (k_yawnmode ? 0.4 : 0.3); // Yawnmode: changed armor protection armorvalue = max(0, min(spot->s.v.armorvalue, 100)); armorExplanation = "&c0b0ga&cfff"; } // Fix flags on ammo items |= (spot->s.v.ammo_shells ? IT_SHELLS : 0); items |= (spot->s.v.ammo_nails ? IT_NAILS : 0); items |= (spot->s.v.ammo_rockets ? IT_ROCKETS : 0); items |= (spot->s.v.ammo_cells ? IT_CELLS : 0); // They always get axe & shotgun. items |= (IT_SHOTGUN | IT_AXE); if (!match_in_progress) { int itemvalues[] = { IT_SUPER_SHOTGUN, IT_NAILGUN, IT_SUPER_NAILGUN, IT_GRENADE_LAUNCHER, IT_ROCKET_LAUNCHER, IT_LIGHTNING }; char *itemnames[] = { "ssg", "ng", "sng", "gl", "rl", "lg" }; int i; qbool first = true; // Tell the player what they would have received here if (!strnull(spot->targetname)) { G_sprint(self, 2, "This spawn is: %s\n", redtext(spot->targetname)); } G_sprint(self, 2, "Spawning here gives you:\n"); G_sprint(self, 2, " %d%s, %dh\n", (int)armorvalue, armorExplanation, (int)spot->s.v.health); for (i = 0; i < sizeof(itemvalues) / sizeof(itemvalues[0]); ++i) { if (items & itemvalues[i]) { G_sprint(self, 2, "%s%s", first ? " " : ",", itemnames[i]); first = false; } } if (!first) { G_sprint(self, 2, "\n"); } else { G_sprint(self, 2, " (no extra weapons)\n"); } } if (match_in_progress == 2) { self->s.v.items = items; // Copy ammo - if none specified, spawn with default self->s.v.ammo_shells = spot->s.v.ammo_shells; self->s.v.ammo_nails = spot->s.v.ammo_nails; self->s.v.ammo_rockets = spot->s.v.ammo_rockets; self->s.v.ammo_cells = spot->s.v.ammo_cells; if ((self->s.v.ammo_shells == 0) && (self->s.v.ammo_nails == 0) && (self->s.v.ammo_rockets == 0) && (self->s.v.ammo_cells == 0)) { self->s.v.ammo_shells = 25; } // Set armor self->s.v.armortype = armortype; self->s.v.armorvalue = armorvalue; // Set health - if none specified, spawn with default self->s.v.health = max(0, min(spot->s.v.health, 250)); if (self->s.v.health == 0) { self->s.v.health = 100; } // If any megahealth items are set to this spawn, set to track this player if (!strnull(spot->targetname)) { gedict_t *p; for (p = world; (p = find(p, FOFCLSN, "item_health"));) { if (p->s.v.spawnflags == 2 && streq(spot->targetname, p->target)) { // Pretend item was taken by this player p->model = ""; p->s.v.solid = SOLID_NOT; p->s.v.nextthink = g_globalvars.time + max(0, min(p->initial_spawn_delay, 5)) + 0.2; // bit extra otherwise 1 frame after the other p->think = (func_t) item_megahealth_rot; p->s.v.owner = EDICT_TO_PROG(self); // Set flag on player items |= IT_SUPERHEALTH; } } } } } if ((deathmatch == 4 || k_bloodfest) && (match_in_progress == 2)) { float dmm4_invinc_time = cvar("dmm4_invinc_time"); if (cvar("k_midair")) { dmm4_invinc_time = -1; // means off self->s.v.ammo_shells = 0; self->s.v.ammo_nails = 0; self->s.v.ammo_cells = 0; self->s.v.ammo_rockets = 255; self->s.v.armorvalue = 200; self->s.v.armortype = 0.8; self->s.v.health = 250; items = IT_AXE | IT_ROCKET_LAUNCHER | IT_ARMOR3; } else if (cvar("k_instagib")) { self->s.v.ammo_shells = 999; self->s.v.ammo_nails = 0; self->s.v.ammo_cells = 0; self->s.v.ammo_rockets = 0; self->s.v.armorvalue = 0; self->s.v.armortype = 0; self->s.v.health = 250; items = IT_AXE; items |= IT_SHOTGUN; } else if (lgc_enabled()) { self->s.v.ammo_cells = 255; self->s.v.armorvalue = 200; self->s.v.armortype = 0.8; self->s.v.health = 250; // Red armor + LG items = IT_LIGHTNING | IT_ARMOR3; } else if (tot_mode_enabled()) { self->s.v.ammo_nails = 255; self->s.v.ammo_shells = 255; self->s.v.ammo_rockets = 255; self->s.v.ammo_cells = 255; self->s.v.armorvalue = self->isBot ? 0 : 200; self->s.v.armortype = self->isBot ? 0 : 0.8; self->s.v.health = self->isBot ? FrogbotHealth() : 250; items = self->s.v.items; items |= IT_NAILGUN; items |= IT_SUPER_NAILGUN; items |= IT_SUPER_SHOTGUN; items |= IT_ROCKET_LAUNCHER; items |= IT_GRENADE_LAUNCHER; items |= IT_LIGHTNING; items &= ~( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); if (!self->isBot) items |= IT_ARMOR3; } else { self->s.v.ammo_nails = 255; self->s.v.ammo_shells = 255; self->s.v.ammo_rockets = 255; self->s.v.ammo_cells = 255; self->s.v.armorvalue = 200; self->s.v.armortype = 0.8; self->s.v.health = 250; #ifdef HITBOXCHECK self->s.v.armorvalue = 30000; self->s.v.health = 30000; #endif items = self->s.v.items; items |= IT_NAILGUN; items |= IT_SUPER_NAILGUN; items |= IT_SUPER_SHOTGUN; items |= IT_ROCKET_LAUNCHER; items |= IT_GRENADE_LAUNCHER; items |= IT_LIGHTNING; items &= ~( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); // remove all armors items |= IT_ARMOR3; // add red armor } // 0 evalutes to DMM4_INVINCIBLE_DEFAULT, negative value disable invincible dmm4_invinc_time = ( dmm4_invinc_time ? bound(0, dmm4_invinc_time, DMM4_INVINCIBLE_MAX) : DMM4_INVINCIBLE_DEFAULT); if (dmm4_invinc_time > 0) { items |= IT_INVULNERABILITY; self->invincible_time = 1; self->invincible_finished = g_globalvars.time + dmm4_invinc_time; } self->s.v.items = items; // default to spawning with rl, except if instagib or gren_mode is on if (cvar("k_instagib")) { self->s.v.weapon = IT_SHOTGUN; } else if (cvar("k_dmm4_gren_mode")) { self->s.v.weapon = IT_GRENADE_LAUNCHER; } else { self->s.v.weapon = IT_ROCKET_LAUNCHER; } } if (deathmatch == 5 && match_in_progress == 2) { self->s.v.ammo_nails = 80; self->s.v.ammo_shells = 30; self->s.v.ammo_rockets = 10; self->s.v.ammo_cells = 30; self->s.v.armorvalue = 200; self->s.v.armortype = 0.8; self->s.v.health = 200; items = self->s.v.items; items |= IT_NAILGUN; items |= IT_SUPER_NAILGUN; items |= IT_SUPER_SHOTGUN; items |= IT_ROCKET_LAUNCHER; items |= IT_GRENADE_LAUNCHER; items |= IT_LIGHTNING; items &= ~( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); // remove all armors items |= IT_ARMOR3; // add red armor items |= IT_INVULNERABILITY; self->s.v.items = items; self->invincible_time = 1; self->invincible_finished = g_globalvars.time + 3; // default to spawning with rl self->s.v.weapon = IT_ROCKET_LAUNCHER; } // regardless of dmm add hook if ctf.. could play instagib ctf etc if (isCTF()) { if (cvar("k_ctf_hook")) { self->s.v.items = (int)self->s.v.items | IT_HOOK; } if (cvar("k_ctf_ga") && deathmatch < 4 && match_in_progress == 2) { self->s.v.armorvalue = 50; self->s.v.armortype = 0.3; self->s.v.items = (int)self->s.v.items | IT_ARMOR1; // add green armor } } if (isCA()) { CA_PutClientInServer(); } // remove particular weapons in dmm4 if (deathmatch == 4 && match_in_progress == 2) { int k_disallow_weapons = (int)cvar("k_disallow_weapons") & DA_WPNS; self->s.v.items = (int)self->s.v.items & ~k_disallow_weapons; } // drop down to best weapon actually hold if (!((int)self->s.v.weapon & (int)self->s.v.items)) { self->s.v.weapon = W_BestWeapon(); } W_SetCurrentAmmo(); // Allow players connect during round in bloodfest, but make them dead. if (k_bloodfest && match_in_progress && !self->ready) { setorigin(self, PASSVEC3(self->s.v.origin)); // kill him, so every damn entity field set properly. self->deathtype = dtSUICIDE; T_Damage(self, self, self, 999999); } else { teleport_player(self, self->s.v.origin, self->s.v.angles, tele_flags); } g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte(MSG_ONE, 38 /*svc_updatestatlong*/); WriteByte(MSG_ONE, 18 /*STAT_MATCHSTARTTIME*/); WriteLong(MSG_ONE, g_matchstarttime); if (match_in_progress == 2) { //berzerk will not affect players that logs in during berzerk if (cvar("k_bzk") && k_berzerk) { self->s.v.items = (int)self->s.v.items | IT_QUAD; self->super_time = 1; self->super_damage_finished = g_globalvars.time + 3600; } } #ifdef BOT_SUPPORT BotClientEntersEvent(self, spot); #endif } /* =============================================================================== RULES =============================================================================== */ // frag difference to win on tiebreak overtime int tiecount(void) { return (deathmatch == 4 ? 2 : 3); } // check sudden death end // call this on player death void Check_SD(gedict_t *p) { if (!match_in_progress) { return; } if (!k_sudden_death || (p->ct != ctPlayer)) { return; } switch ((int)k_sudden_death) { case SD_NORMAL: EndMatch(0); return; case SD_TIEBREAK: { gedict_t *ed1 = get_ed_scores1(), *ed2 = get_ed_scores2(); int sc = get_scores1() - get_scores2(); if ((isDuel() || isFFA()) && ed1 && ed2) { sc = ed1->s.v.frags - ed2->s.v.frags; } if (((isDuel() || isFFA()) && ed1 && ed2) // duel or ffa || (isTeam() || isCTF()) // some team ) { if (abs(sc) >= tiecount()) { EndMatch(0); } } // unknown so end match else { EndMatch(0); } return; } } } /* ============ CheckRules Exit deathmatch games upon conditions ============ */ void CheckRules(void) { if (!match_in_progress) { return; } if (!isHoonyModeAny() && fraglimit && self->s.v.frags >= fraglimit) { EndMatch(0); } } //============================================================================ void PlayerDeathThink(void) { float forward; float respawn_time; if (k_standby) { return; } if (((int)(self->s.v.flags)) & FL_ONGROUND) { forward = vlen(self->s.v.velocity); forward = forward - 20; if (forward <= 0) { SetVector(self->s.v.velocity, 0, 0, 0); } else { VectorNormalize(self->s.v.velocity); VectorScale(self->s.v.velocity, forward, self->s.v.velocity); } } // { autospawn respawn_time = (cvar("k_midair") || cvar("k_instagib")) ? 2 : 5; if ((dtSUICIDE == self->deathtype) || isRA() || isCA()) { respawn_time = -999999; // force respawn ASAP if suicides or in RA mode } if ((g_globalvars.time - self->dead_time) > respawn_time) { // do not allow respawn in bloodfest mode. if (k_bloodfest && match_in_progress) { return; } k_respawn(self, true); return; } // } // wait for all buttons released if (self->s.v.deadflag == DEAD_DEAD) { if (self->s.v.button2 || self->s.v.button1 || self->s.v.button0 || self->wreg_attack) { return; } self->s.v.deadflag = DEAD_RESPAWNABLE; return; } // wait for any button down if (!self->s.v.button2 && !self->s.v.button1 && !self->s.v.button0 && !self->wreg_attack) { return; } // do not allow respawn in bloodfest mode. if (k_bloodfest && match_in_progress) { return; } k_respawn(self, true); } void PlayerJump(void) { //vec3_t start, end; if ((self->spawn_time + 0.05) > g_globalvars.time) { self->s.v.velocity[2] = -270; // discard +jump till 50 ms after respawn, like ktpro self->s.v.flags = (int)self->s.v.flags & ~FL_JUMPRELEASED; return; } if (((int)(self->s.v.flags)) & FL_WATERJUMP) { return; } if (self->s.v.waterlevel >= 2) { // play swiming sound if (self->swim_flag < g_globalvars.time) { self->swim_flag = g_globalvars.time + 1; // Yawnmode: don't play swimming sound to cut older clients without smartjump some slack // - Molgrum if (!k_yawnmode) { if (g_random() < 0.5) { sound(self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM); } else { sound(self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM); } } } return; } if (!(((int)(self->s.v.flags)) & FL_ONGROUND)) { return; } if (!(((int)(self->s.v.flags)) & FL_JUMPRELEASED)) { return; // don't pogo stick } self->s.v.flags -= (((int)(self->s.v.flags)) & FL_JUMPRELEASED); // self->s.v.button2 = 0; self->was_jump = true; if (!can_prewar(false)) { self->s.v.velocity[2] = -270; } // check the flag and jump if we can if (!self->brokenankle) { self->s.v.button2 = 0; // player jumping sound //crt - get rid of jump sound for spec if (!isRA() || (isWinner(self) || isLoser(self))) { sound(self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM); } // JUMPBUG[ // the engine checks velocity_z and won't perform the jump if it's < zero! // qqshka - i know this is shit - but ktpro does it, and probably server engine even ignor this hack if (self->s.v.velocity[2] < 0) { self->s.v.velocity[2] = 0; } // JUMPBUG] } else { self->s.v.velocity[2] = -270; } } /* =========== WaterMove ============ */ void WaterMove(void) { //dprint (ftos(self->s.v.waterlevel)); if (self->s.v.movetype == MOVETYPE_NOCLIP) { return; } if (ISDEAD(self)) { return; } if (self->s.v.waterlevel != 3) { #ifdef BOT_SUPPORT if (self->isBot && self->s.v.waterlevel) { BotWaterJumpFix(); } #endif if (self->air_finished < g_globalvars.time) { sound(self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM); } else if (self->air_finished < (g_globalvars.time + 9)) { sound(self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM); } self->air_finished = g_globalvars.time + 12; self->dmg = 2; #ifdef BOT_SUPPORT if (self->isBot) { BotOutOfWater(self); } #endif } else if (self->air_finished < g_globalvars.time) { // drown! if (self->pain_finished < g_globalvars.time) { self->dmg = self->dmg + 2; if (self->dmg > 15) { self->dmg = 10; } switch ((int)self->s.v.watertype) { case CONTENT_LAVA: self->deathtype = dtLAVA_DMG; break; // funny, we can drown in lava ? case CONTENT_SLIME: self->deathtype = dtSLIME_DMG; break; // and in slime ? default: self->deathtype = dtWATER_DMG; break; // and sure we can drown in water } T_Damage(self, world, world, self->dmg); self->pain_finished = g_globalvars.time + 1; } } #ifdef BOT_SUPPORT if (self->isBot) { BotWaterMove(self); } #endif if (!self->s.v.waterlevel) { if (((int)(self->s.v.flags)) & FL_INWATER) { // play leave water sound sound(self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM); self->s.v.flags -= FL_INWATER; } return; } // in race, touching lava or slime cancels the run if (isRACE() && race_handle_event(self, NULL, "watermove")) { return; } if (self->s.v.watertype == CONTENT_LAVA) { // do damage if (self->dmgtime < g_globalvars.time) { if (self->radsuit_finished > g_globalvars.time) { self->dmgtime = g_globalvars.time + 1; } else { self->dmgtime = g_globalvars.time + 0.2; } self->deathtype = dtLAVA_DMG; T_Damage(self, world, world, 10 * self->s.v.waterlevel); } } else if (self->s.v.watertype == CONTENT_SLIME) { // do damage if ((self->dmgtime < g_globalvars.time) && (self->radsuit_finished < g_globalvars.time)) { self->dmgtime = g_globalvars.time + 1; self->deathtype = dtSLIME_DMG; T_Damage(self, world, world, 4 * self->s.v.waterlevel); } } if (!(((int)(self->s.v.flags)) & FL_INWATER)) { // player enter water sound if (self->s.v.watertype == CONTENT_LAVA) { sound(self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM); } if (self->s.v.watertype == CONTENT_WATER) { sound(self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM); } if (self->s.v.watertype == CONTENT_SLIME) { sound(self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM); } self->s.v.flags += FL_INWATER; self->dmgtime = 0; } } void MakeGhost(void) { gedict_t *ghost; float f1 = 1; float f2 = 0; int i; if (k_matchLess) // no ghost in matchless mode { return; } if (!cvar("k_lockmode")) { return; // no ghost if lockmode is disabled } while ((f1 < k_userid) && !f2) { if (strnull(ezinfokey(world, va("%d", (int)f1)))) { f2 = 1; } else { f1++; } } if (!f2) { k_userid++; } for (i = itNONE; i < itMAX; i++) { adjust_pickup_time(&self->it_pickup_time[i], &self->ps.itm[i].time); } for (i = wpNONE; i < wpMAX; i++) { adjust_pickup_time(&self->wp_pickup_time[i], &self->ps.wpn[i].time); } if (self->control_start_time) { self->ps.control_time += g_globalvars.time - self->control_start_time; self->control_start_time = 0; } ghost = spawn(); ghost->s.v.owner = EDICT_TO_PROG(world); ghost->classname = "ghost"; ghost->cnt2 = f1; ghost->k_teamnum = self->k_teamnum; ghost->s.v.frags = self->s.v.frags; ghost->deaths = self->deaths; ghost->friendly = self->friendly; ghost->ready = 0; ghost->suicides = self->suicides; ghost->kills = self->kills; ghost->ps = self->ps; // save player stats ghost->ghost_dt = g_globalvars.time; // save drop time ghost->ghost_clr = (int)bound(0, iKey(self, "topcolor"), 13) << 8; ghost->ghost_clr |= (int)bound(0, iKey(self, "bottomcolor"), 13); // save colors // G_bprint( PRINT_HIGH, "name num: %d team num %d\n", (int)ghost->cnt2, (int)ghost->k_teamnum); localcmd("localinfo %d \"%s\"\n", (int)f1, self->netname); trap_executecmd(); } void set_important_fields(gedict_t *p) { p->s.v.takedamage = DAMAGE_NO; p->s.v.solid = SOLID_NOT; p->s.v.movetype = MOVETYPE_NONE; p->s.v.deadflag = DEAD_DEAD; p->s.v.health = 0; p->s.v.frame = 0; p->s.v.modelindex = 0; p->model = ""; p->s.v.nextthink = -1; p->ct = ctNone; p->k_accepted = 0; p->classname = ""; // clear client classname on disconnect } //////////////// // GlobalParams: // self /////////////// void ClientDisconnect(void) { extern void mv_stop_playback(void); k_nochange = 0; // force recalculate frags scores if (!self->k_accepted) { set_important_fields(self); // set classname == "" and etc return; } mv_stop_playback(); del_from_specs_favourites(self); ra_ClientDisconnect(); if (match_in_progress == 2 && self->ct == ctPlayer) { G_bprint( PRINT_HIGH, "%s left the game with %.0f frags\n", self->netname, self->s.v.frags); sound(self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE); MakeGhost(); } DropRune(); PlayerDropFlag(self, false); // s: added conditional function call here if (self->v.elect_type != etNone) { G_bprint(2, "Election aborted\n"); AbortElect(); } set_important_fields(self); // set classname == "" and etc // s: added conditional function call here if (self->k_kicking) { ExitKick(self); } if (capt_num(self)) { G_bprint(2, "A %s has left\n", redtext("captain")); ExitCaptain(); } if (k_captains == 2) { CheckFinishCaptain(); } if (cvar("k_idletime") > 0) { IdlebotCheck(); } if (!(CountPlayers() - CountBots())) { void Spawn_DefMapChecker(float timeout); int old_matchless = k_matchLess; #ifdef BOT_SUPPORT int old_bots_enabled = bots_enabled(); #endif // Well, not quite sure if it OK, k_matchLess C global variable really must be set ONCE per map. // At the same time, k_matchless cvar should be set ONCE per whole server run, so it should be OK. // So here we try to put server back to non matchless mode. k_matchLess = cvar("k_matchless"); // turn off coop mode. FIXME: coop really should be real mode some day. cvar_fset("coop", 0); if (match_in_progress) { EndMatch(1); // skip demo, make some other stuff } // if race is on, turn it off when all players are gone if (isRACE()) { ToggleRace(); } // Execute configs/reset.cfg and set k_defmode. execute_rules_reset(); // Change map. if (old_matchless != k_matchLess) { changelevel(mapname); // force reload current map ASAP! } else if (!cvar("lock_practice") && k_practice) { changelevel(mapname); // force reload current map in practice mode anyway, ASAP } #ifdef BOT_SUPPORT else if (bots_enabled() != old_bots_enabled) { changelevel(mapname); // need to reload map, dimensions of entities will need to change } #endif else { Spawn_DefMapChecker(10); // delayed map reload, may be skipped due to different settings } } } void BackFromLag(void) { int timing_players_action = TA_ALL & (int)cvar("timing_players_action"); self->k_timingWarnTime = 0; if (timing_players_action & TA_INFO) { G_bprint(2, "%s %s\n", self->netname, redtext("is back from lag")); } if (timing_players_action & TA_INVINCIBLE) { self->s.v.takedamage = self->k_timingTakedmg; self->s.v.solid = self->k_timingSolid; self->s.v.movetype = self->k_timingMovetype; } } #define S_AXE ( 1<<0 ) #define S_SG ( 1<<1 ) #define S_SSG ( 1<<2 ) #define S_NG ( 1<<3 ) #define S_SNG ( 1<<4 ) #define S_GL ( 1<<5 ) #define S_RL ( 1<<6 ) #define S_LG ( 1<<7 ) #define S_LGLastFrag ( 1<<8 ) #define S_ALL ( S_AXE | S_SG | S_SSG | S_NG | S_SNG | S_GL | S_RL | S_LG | S_LGLastFrag ) #define S_DEF ( S_GL | S_RL | S_LG ) /* default */ void wp_wrap_cat(char *s, char *buf, int size) { const int max_line = 40; // 320 / 8 = 40 char *n_pos = strrchr(buf, '\n'); int s_len = strlen(s), b_len = strlen(n_pos ? n_pos : buf); strlcat(buf, (s_len + b_len > max_line) ? "\n" : " ", size); strlcat(buf, s, size); } void Print_Wp_Stats(void) { char buf[1024] = { 0 }; qbool ktpl = (iKey(self, "ktpl") ? true : false); int i, lw = iKey(self, "lw") + (ktpl ? 12 : 0), lw_x = iKey(self, "lw_x"); int _wps = S_ALL & iKey(self, "wps"); int wps = (_wps ? _wps : S_DEF); // if wps is not set - show S_DEF weapons gedict_t *g = self->ct == ctSpec ? PROG_TO_EDICT(self->s.v.goalentity) : NULL; gedict_t *e = self->ct == ctPlayer ? self : (g ? g : world); // stats of whom we want to show #if 0 /* percentage */ float axe = wps & S_AXE ? 100.0 * e->ps.wpn[wpAXE].hits / max(1, e->ps.wpn[wpAXE].attacks) : 0; #else /* just count of direct hits */ float axe = wps & S_AXE ? e->ps.wpn[wpAXE].hits : 0; #endif float sg = wps & S_SG ? 100.0 * e->ps.wpn[wpSG].hits / max(1, e->ps.wpn[wpSG].attacks) : 0; float ssg = wps & S_SSG ? 100.0 * e->ps.wpn[wpSSG].hits / max(1, e->ps.wpn[wpSSG].attacks) : 0; float ng = wps & S_NG ? 100.0 * e->ps.wpn[wpNG].hits / max(1, e->ps.wpn[wpNG].attacks) : 0; float sng = wps & S_SNG ? 100.0 * e->ps.wpn[wpSNG].hits / max(1, e->ps.wpn[wpSNG].attacks) : 0; #if 0 /* percentage */ float gl = wps & S_GL ? 100.0 * e->ps.wpn[wpGL].hits / max(1, e->ps.wpn[wpGL].attacks) : 0; float rl = wps & S_RL ? 100.0 * e->ps.wpn[wpRL].hits / max(1, e->ps.wpn[wpRL].attacks) : 0; #else /* just count of direct hits */ float gl = wps & S_GL ? e->ps.wpn[wpGL].hits : 0; float rl = wps & S_RL ? max(0.001, e->ps.wpn[wpRL].hits) : 0; #endif float lg = wps & S_LG ? max(0.001, 100.0 * e->ps.wpn[wpLG].hits / max(1, e->ps.wpn[wpLG].attacks)) : 0; float lgLastFrag = wps & S_LGLastFrag ? max(0.001, 100.0 * e->ps.wpn[wpLG].lastfragdisplayhits / max(1, e->ps.wpn[wpLG].lastfragdisplayattacks)) : 0; if ((i = lw) > 0) { i = bound(0, i, sizeof(buf) - 1); memset((void*) buf, (int)'\n', i); buf[i] = 0; } if ((e == world) || (e->ct != ctPlayer)) { // spec tracking no one G_centerprint(self, "%s%s", buf, redtext("Tracking no one (+wp_stats)")); self->need_clearCP = 1; self->wp_stats_time = g_globalvars.time + WP_STATS_UPDATE; return; } if (!axe && !sg && !ssg && !ng && !sng && !gl && !rl && !lg && !lgLastFrag) { return; // sanity } if ((i = lw_x) > 0) { int offset = strlen(buf); i = bound(0, i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)' ', i); buf[i + offset] = 0; } if (ktpl) { if (lg) { strlcat(buf, lg ? va("%s:%.1f ", redtext("lg"), lg) : "", sizeof(buf)); } if (lgLastFrag) { strlcat(buf, lgLastFrag ? va("%s:%.1f ", redtext("lglf"), lgLastFrag) : "", sizeof(buf)); } if (rl) { strlcat(buf, rl ? va("%s:%.0f ", redtext("rl"), rl) : "", sizeof(buf)); } if (gl) { strlcat(buf, gl ? va("%s:%.0f ", redtext("gl"), gl) : "", sizeof(buf)); } if (axe) { strlcat(buf, axe ? va("%s:%.0f ", redtext("axe"), axe) : "", sizeof(buf)); } if (sg) { strlcat(buf, sg ? va("%s:%.1f ", redtext("sg"), sg) : "", sizeof(buf)); } if (ssg) { strlcat(buf, ssg ? va("%s:%.1f ", redtext("ssg"), ssg) : "", sizeof(buf)); } if (ng) { strlcat(buf, ng ? va("%s:%.1f ", redtext("ng"), ng) : "", sizeof(buf)); } if (sng) { strlcat(buf, sng ? va("%s:%.1f ", redtext("sng"), sng) : "", sizeof(buf)); } } else { if (lg) { wp_wrap_cat(lg ? va("%s:%.1f", redtext("lg"), lg) : "", buf, sizeof(buf)); } if (lgLastFrag) { wp_wrap_cat(lgLastFrag ? va("%s:%.1f", redtext("lglf"), lgLastFrag) : "", buf, sizeof(buf)); } if (rl) { wp_wrap_cat(rl ? va("%s:%.0f", redtext("rl"), rl) : "", buf, sizeof(buf)); } if (gl) { wp_wrap_cat(gl ? va("%s:%.0f", redtext("gl"), gl) : "", buf, sizeof(buf)); } if (axe) { wp_wrap_cat(axe ? va("%s:%.0f", redtext("axe"), axe) : "", buf, sizeof(buf)); } if (sg) { wp_wrap_cat(sg ? va("%s:%.1f", redtext("sg"), sg) : "", buf, sizeof(buf)); } if (ssg) { wp_wrap_cat(ssg ? va("%s:%.1f", redtext("ssg"), ssg) : "", buf, sizeof(buf)); } if (ng) { wp_wrap_cat(ng ? va("%s:%.1f", redtext("ng"), ng) : "", buf, sizeof(buf)); } if (sng) { wp_wrap_cat(sng ? va("%s:%.1f", redtext("sng"), sng) : "", buf, sizeof(buf)); } } if ((i = lw_x) < 0) { int offset = strlen(buf); i = bound(0, -i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)' ', i); buf[i + offset] = 0; } if ((i = lw) < 0) { int offset = strlen(buf); i = bound(0, -i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)'\n', i); buf[i + offset] = 0; } if (strnull(buf)) { return; // sanity } self->need_clearCP = 1; self->wp_stats_time = g_globalvars.time + WP_STATS_UPDATE; G_centerprint(self, "%s", buf); } /* * Function is called when a player or spectator enables continuous score display with +scores console command. * */ void Print_Scores(void) { char buf[1024] = { 0 }, *last_va; int i, minutes = 0, seconds = 0, ts = 0, es = 0, ls = iKey(self, "ls") + (iKey(self, "ktpl") ? 12 : 0); qbool sc_ok = false; gedict_t *p, *ed1, *ed2; gedict_t *g = self->ct == ctSpec ? PROG_TO_EDICT(self->s.v.goalentity) : NULL; gedict_t *e = self->ct == ctPlayer ? self : (g ? g : world); // stats of whom we want to show if ((i = ls) > 0) { i = bound(0, i, sizeof(buf) - 1); memset((void*) buf, (int)'\n', i); buf[i] = 0; } if ((e == world) || (e->ct != ctPlayer)) { // spec tracking no one G_centerprint(self, "%s%s", buf, redtext("Tracking no one (+scores)")); self->need_clearCP = 1; self->sc_stats_time = g_globalvars.time + SC_STATS_UPDATE; return; } if ((p = find(world, FOFCLSN, "timer")) && (match_in_progress == 2)) { minutes = p->cnt; seconds = p->cnt2; if (seconds == 60) { seconds = 0; } else { minutes--; } } if (isCTF()) { gedict_t *flag1 = find(world, FOFCLSN, "item_flag_team1"); gedict_t *flag2 = find(world, FOFCLSN, "item_flag_team2"); char *r_f = "", *b_f = "", *rune = ""; if (flag1 && flag2) { switch ((int)flag1->cnt) { case FLAG_AT_BASE: r_f = " "; break; case FLAG_CARRIED: r_f = "R"; break; case FLAG_DROPPED: r_f = "\322"; break; default: r_f = " "; } switch ((int)flag2->cnt) { case FLAG_AT_BASE: b_f = " "; break; case FLAG_CARRIED: b_f = "B"; break; case FLAG_DROPPED: b_f = "\302"; break; default: b_f = " "; } if (e->ctf_flag & CTF_RUNE_RES) { rune = "res"; } else if (e->ctf_flag & CTF_RUNE_STR) { rune = "str"; } else if (e->ctf_flag & CTF_RUNE_HST) { rune = "hst"; } else if (e->ctf_flag & CTF_RUNE_RGN) { rune = "rgn"; } else { rune = " "; } strlcat(buf, va("%s \205%s\205%s\205 ", rune, r_f, b_f), sizeof(buf)); } } if (k_sudden_death) { strlcat(buf, va("%s:%-5.5s", redtext("tl"), redtext(k_sudden_death == SD_NORMAL ? "sd" : "tb")), sizeof(buf)); } else { strlcat(buf, va("%s:%02d:%02d", redtext("tl"), minutes, seconds), sizeof(buf)); } if (k_showscores) { int s1 = get_scores1(); int s2 = get_scores2(); char *t1 = cvar_string("_k_team1"); char *t2 = getteam(e); ts = streq(t1, t2) ? s1 : s2; es = streq(t1, t2) ? s2 : s1; sc_ok = true; } else if ((ed1 = get_ed_scores1()) && (ed2 = get_ed_scores2())) { ts = e->s.v.frags; es = ed1 == e ? ed2->s.v.frags : ed1->s.v.frags; sc_ok = true; } last_va = ""; if (sc_ok) { if (isCTF()) { strlcat(buf, last_va = va(" \x90%d\x91", ts - es), sizeof(buf)); } else { if ((current_umode < um2on2on2) || (current_umode > um4on4on4)) { strlcat(buf, last_va = va(" \364:%d \345:%d \x90%d\x91", ts, es, ts - es), sizeof(buf)); } else { // if the current UserMode is 2on2on2, 3on3on3, 4on4on4, we have 3 teams int s1 = get_scores1(); int s2 = get_scores2(); int s3 = get_scores3(); char *t1 = cvar_string("_k_team1"); char *t2 = cvar_string("_k_team2"); char *t3 = cvar_string("_k_team3"); char *t = getteam(e); if (streq(t1, t)) { // the tracked player is in Team 1 strlcat(buf, last_va = va(" \364:%d \345:%d \x90%d\x91 \345:%d \x90%d\x91", s1, s2, s1 - s2 , s3, s1 - s3), sizeof(buf)); } else if (streq(t2, t)) { // the tracked player is in Team 2 strlcat(buf, last_va = va(" \364:%d \345:%d \x90%d\x91 \345:%d \x90%d\x91", s2, s1, s2 - s1 , s3, s2 - s3), sizeof(buf)); } else if (streq(t3, t)) { // the tracked player is in Team 3 strlcat(buf, last_va = va(" \364:%d \345:%d \x90%d\x91 \345:%d \x90%d\x91", s3, s1, s3 - s1 , s2, s3 - s2), sizeof(buf)); } } } } // add spaces, so line in most cases is don't move from side to side during frags changes if ((i = (isCTF() ? sizeof(" [-zzzzz]") - 1 : sizeof(" t:xxxxx e:yyyyy [-zzzzz]") - 1) - strlen(last_va)) > 0) { int offset = strlen(buf); i = bound(0, i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)' ', i); buf[i + offset] = 0; } if ((i = ls) < 0) { int offset = strlen(buf); i = bound(0, -i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)'\n', i); buf[i + offset] = 0; } if (strnull(buf)) { return; // sanity } self->need_clearCP = 1; self->sc_stats_time = g_globalvars.time + SC_STATS_UPDATE; G_centerprint(self, "%s", buf); } // qqshka - ripped from ktpro float v_for_jump(int frametime_ms) { if (cvar("k_no_fps_physics")) { return 1; } // G_bprint(2, "MS: %d\n", frametime_ms); if (frametime_ms > 44) { return 1.05; } else if (frametime_ms > 38) { return 1.041; } else if (frametime_ms > 33) { return 1.035; } else if (frametime_ms > 28) { return 1.032; } else if (frametime_ms > 24) { return 1.029; } else if (frametime_ms > 22) { return 1.025; } else if (frametime_ms > 19) { return 1.02; } else if (frametime_ms > 18) { return 1.015; } else if (frametime_ms > 16) { return 1.01; } else if (frametime_ms > 15) { return 1.005; } else if (frametime_ms > 14) { return 1; } else if (frametime_ms > 13) { return 1; } else if (frametime_ms > 12) { return 1; } else if (frametime_ms > 11) { return 0.9991; } else if (frametime_ms > 10) { return 0.9982; } else if (frametime_ms > 9) { return 0.9961; } else if (frametime_ms > 8) { return 0.9941; } else if (frametime_ms > 7) { return 0.9886; } else if (frametime_ms > 6) { return 0.9882; } else if (frametime_ms > 5) { return 0.9865; } else if (frametime_ms > 4) { return 0.9855; } else if (frametime_ms > 3) { return 0.9801; } else if (frametime_ms > 2) { return 0.9783; } else { return 0.9652; } } void ZeroFpsStats(void) { // zero these so the average/highest FPS is calculated for each delay period. self->fAverageFrameTime = 0; self->fFrameCount = 0; self->fLowestFrameTime = 0.999; self->fHighestFrameTime = 0.0001f; } void mv_playback(void); //////////////// // GlobalParams: // time // frametime // self /////////////// /* ================ PlayerPreThink Called every frame before physics are run ================ */ void PlayerPreThink(void) { float r; qbool zeroFps = false; if (self->k_timingWarnTime) { BackFromLag(); } if (self->sc_stats && self->sc_stats_time && (self->sc_stats_time <= g_globalvars.time) && (match_in_progress != 1) && !isRACE()) { Print_Scores(); } if (self->wp_stats && self->wp_stats_time && (self->wp_stats_time <= g_globalvars.time) && (match_in_progress != 1) && !isRACE()) { Print_Wp_Stats(); } if (self->was_jump) { self->s.v.velocity[2] *= v_for_jump(self->fCurrentFrameTime * 1000); self->was_jump = false; } #ifdef BOT_SUPPORT if (bots_enabled()) { BotPreThink(self); } #endif // ILLEGALFPS[ self->fAverageFrameTime += g_globalvars.frametime; self->fFrameCount += 1; self->fCurrentFrameTime = g_globalvars.frametime; if (g_globalvars.frametime < self->fLowestFrameTime) { self->fLowestFrameTime = g_globalvars.frametime; } if (g_globalvars.frametime > self->fHighestFrameTime) { self->fHighestFrameTime = g_globalvars.frametime; } if (self->fDisplayIllegalFPS < g_globalvars.time && framechecks && !self->isBot) { float fps; // client uptime check // code by Zibbo r = self->fAverageFrameTime * 100 / (g_globalvars.time - self->real_time); if ((r > 103) && !match_in_progress) { G_sprint( self, PRINT_HIGH, "Warning: It seems that your machine has a too long uptime causing a bug in your QW client. Please restart your machine and fix this message.\n"); if (r > 105) { self->uptimebugpolicy += 1; } } if (self->uptimebugpolicy > 3) { G_bprint(PRINT_HIGH, "\n%s gets kicked for too long uptime\n", self->netname); G_sprint(self, PRINT_HIGH, "Please reboot your machine to get rid of the problem\n"); stuffcmd(self, "disconnect\n"); // FIXME: stupid way } // ends here fps = (self->fAverageFrameTime / self->fFrameCount); fps = fps ? (1.0f / fps) : 1; // G_bprint(2, "%s FPS: %3.1f\n", self->netname, fps); if (fps > current_maxfps + 2) // 2 fps fluctuation is allowed :( { float peak = self->fLowestFrameTime ? (1.0f / self->fLowestFrameTime) : 1; G_bprint( PRINT_HIGH, "\n" "Warning: %s has abnormally high frame rates, " "highest FPS = %3.1f, average FPS = %3.1f!\n", self->netname, peak, fps); self->fIllegalFPSWarnings += 1; if (self->fIllegalFPSWarnings > 3) { // kick the player from server! // s: changed the text a bit :) G_bprint(PRINT_HIGH, "%s gets kicked for potential cheat\n", self->netname); G_sprint(self, PRINT_HIGH, "Please reboot your machine to try to get rid of the problem\n"); stuffcmd(self, "disconnect\n"); // FIXME: stupid way } } zeroFps = true; } // zero these so the average/highest FPS is calculated for each delay period. if ((self->fDisplayIllegalFPS < g_globalvars.time) || zeroFps) { self->real_time = g_globalvars.time; // delay on checking/displaying illegal FPS. // s: changed to 15 for more accurate calculation (lag screws it up) self->fDisplayIllegalFPS = g_globalvars.time + 15; ZeroFpsStats(); } // ILLEGALFPS] mv_playback(); if (intermission_running) { IntermissionThink(); // otherwise a button could be missed between return; // the think tics } if (isRA()) { RocketArenaPre(); } trap_makevectors(self->s.v.v_angle); // is this still used CheckRules(); // FIXME: really? // WaterMove(); if (self->s.v.deadflag >= DEAD_DEAD) { self->super_damage_finished = 0; // moved from PlayerDie() PlayerDeathThink(); return; } if (self->s.v.deadflag == DEAD_DYING) { // Sometimes (rarely) the death animation functions in player.qc aren't // invoked on death for some reason (couldn't figure out why). This leads to a // state when the player stands still after dying and can't respawn or even // suicide and has to reconnect. This is checked and fixed here if ((g_globalvars.time > (self->dead_time + 0.1)) && ((self->s.v.frame < 41) || (self->s.v.frame > 102))) // FIXME: hardcoded range of dead frames { StartDie(); } return; // dying, so do nothing } CA_player_pre_think(); race_player_pre_think(); // brokenankle included here if (self->s.v.button2 || self->brokenankle) { PlayerJump(); } else { self->s.v.flags = ((int)(self->s.v.flags)) | FL_JUMPRELEASED; } // teleporters can force a non-moving pause time if (g_globalvars.time < self->pausetime) { SetVector(self->s.v.velocity, 0, 0, 0); } if ((g_globalvars.time > self->attack_finished) && (self->s.v.currentammo == 0) && (self->s.v.weapon != IT_AXE) && (self->s.v.weapon != IT_HOOK)) { self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); } // CTF if (self->on_hook) { GrappleService(); } if (self->ctf_flag & CTF_RUNE_RGN) { if (self->regen_time < g_globalvars.time) { self->regen_time = g_globalvars.time; if (self->s.v.health < 150) { self->s.v.health += 5; if (self->s.v.health > 150) { self->s.v.health = 150; } self->regen_time += 1 / ((cvar("k_ctf_rune_power_rgn") / 2) + 1); #ifdef BOT_SUPPORT FrogbotSetHealthArmour(self); #endif RegenerationSound(self); } if (self->s.v.armorvalue < 150 && self->s.v.armorvalue > 0) { self->s.v.armorvalue += 5; if (self->s.v.armorvalue > 150) { self->s.v.armorvalue = 150; } self->regen_time += 0.5; #ifdef BOT_SUPPORT FrogbotSetHealthArmour(self); #endif RegenerationSound(self); } } } VectorCopy(self->s.v.velocity, self->old_vel); } ///////////////////////////////////////////////////////////////// /* ================ CheckPowerups Check for turning off powerups ================ */ extern void ktpro_autotrack_on_powerup_out(gedict_t *dude); void CheckPowerups(void) { if (ISDEAD(self)) { return; } // invisibility if (self->invisible_finished) { // sound and screen flash when items starts to run out if (self->invisible_sound < g_globalvars.time) { sound(self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE); self->invisible_sound = g_globalvars.time + ((g_random() * 3) + 1); } if (self->invisible_finished < g_globalvars.time + 3) { if (self->invisible_time == 1) { G_sprint(self, PRINT_HIGH, "Ring of Shadows magic is fading\n"); stuffcmd(self, "bf\n"); sound(self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM); self->invisible_time = g_globalvars.time + 1; } if (self->invisible_time < g_globalvars.time) { self->invisible_time = g_globalvars.time + 1; stuffcmd(self, "bf\n"); } } if (self->invisible_finished < g_globalvars.time) { // just stopped self->s.v.items = (int)self->s.v.items & ~IT_INVISIBILITY; if (cvar("k_instagib")) { G_bprint( PRINT_HIGH, "%s lost his powers\n", self->netname); self->s.v.health = min(200, self->s.v.health); } self->invisible_finished = 0; self->invisible_time = 0; if (vw_enabled) { W_SetCurrentAmmo(); // set the correct .vw_index } self->s.v.modelindex = modelindex_player; // don't use eyes adjust_pickup_time(&self->it_pickup_time[itRING], &self->ps.itm[itRING].time); ktpro_autotrack_on_powerup_out(self); } else { // use the eyes self->s.v.frame = 0; self->vw_index = 0; self->s.v.modelindex = modelindex_eyes; } } // invincibility if (self->invincible_finished) { // sound and screen flash when items starts to run out if (self->invincible_finished < (g_globalvars.time + 3)) { if (self->invincible_time == 1) { if (!cvar("k_instagib")) { G_sprint(self, PRINT_HIGH, "Protection is almost burned out\n"); } stuffcmd(self, "bf\n"); sound(self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM); self->invincible_time = g_globalvars.time + 1; } if (self->invincible_time < g_globalvars.time) { self->invincible_time = g_globalvars.time + 1; stuffcmd(self, "bf\n"); } } if (self->invincible_finished < g_globalvars.time) { // just stopped self->s.v.items -= IT_INVULNERABILITY; self->invincible_time = 0; self->invincible_finished = 0; adjust_pickup_time(&self->it_pickup_time[itPENT], &self->ps.itm[itPENT].time); ktpro_autotrack_on_powerup_out(self); } } // super damage if (self->super_damage_finished) { // sound and screen flash when items starts to run out if ((self->super_damage_finished < (g_globalvars.time + 3)) && !k_berzerk) { if (self->super_time == 1) { if (deathmatch == 4 && !tot_mode_enabled()) { G_sprint(self, PRINT_HIGH, "OctaPower is wearing off\n"); } else { G_sprint(self, PRINT_HIGH, "Quad Damage is wearing off\n"); } stuffcmd(self, "bf\n"); sound(self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM); self->super_time = g_globalvars.time + 1; } if (self->super_time < g_globalvars.time) { self->super_time = g_globalvars.time + 1; stuffcmd(self, "bf\n"); } } if ((self->super_damage_finished < g_globalvars.time) && !k_berzerk) { // just stopped self->s.v.items -= IT_QUAD; if (!k_practice) // #practice mode# { if (deathmatch == 4 && !tot_mode_enabled()) { self->s.v.ammo_cells = 255; self->s.v.armorvalue = 1; self->s.v.armortype = 0.8; self->s.v.health = min(100, self->s.v.health); } } self->super_damage_finished = 0; self->super_time = 0; adjust_pickup_time(&self->it_pickup_time[itQUAD], &self->ps.itm[itQUAD].time); ktpro_autotrack_on_powerup_out(self); } } // suit if (self->radsuit_finished) { self->air_finished = g_globalvars.time + 12; // don't drown // sound and screen flash when items starts to run out if (self->radsuit_finished < g_globalvars.time + 3) { if (self->rad_time == 1) { G_sprint(self, PRINT_HIGH, "Air supply in Biosuit expiring\n"); stuffcmd(self, "bf\n"); sound(self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM); self->rad_time = g_globalvars.time + 1; } if (self->rad_time < g_globalvars.time) { self->rad_time = g_globalvars.time + 1; stuffcmd(self, "bf\n"); } } if (self->radsuit_finished < g_globalvars.time) { // just stopped self->s.v.items -= IT_SUIT; self->rad_time = 0; self->radsuit_finished = 0; ktpro_autotrack_on_powerup_out(self); } } } void CheckLightEffects(void) { qbool dim = false; qbool brl = false; qbool r = false; qbool g = false; qbool b = false; #ifdef BOT_SUPPORT // Keep colours for markers when in editing mode if (FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { return; } #endif // remove particular EF_xxx self->s.v.effects = (int)self->s.v.effects & ~(EF_DIMLIGHT | EF_BRIGHTLIGHT | EF_BLUE | EF_RED | EF_GREEN); // well, EF_xxx may originate from different sources, check it all if (self->ctf_flag & CTF_FLAG) { dim = true; } if ((self->invincible_finished > g_globalvars.time) && (deathmatch != 4)) { r = true; } if (self->radsuit_finished > g_globalvars.time) { g = true; } //if ( self->racer && race.status && !match_in_progress ) // g = true; // RACE (disabled with multi-racing) if (k_bloodfest && ISLIVE(self)) { g = true; } if (self->super_damage_finished > g_globalvars.time) { b = true; } if (!match_in_progress && !match_over && !k_matchLess && !self->ready && cvar("k_sready") && !isRACE()) { b = true; } // apply all EF_xxx if (dim) { self->s.v.effects = (int)self->s.v.effects | EF_DIMLIGHT; } if (brl) { self->s.v.effects = (int)self->s.v.effects | EF_BRIGHTLIGHT; } if (r) { self->s.v.effects = (int)self->s.v.effects | EF_RED; } if (g) { self->s.v.effects = (int)self->s.v.effects | EF_GREEN; } if (b) { self->s.v.effects = (int)self->s.v.effects | EF_BLUE; } } void check_callalias(void); /////////// // BothPostThink // // called for players and specs // ////////// void BothPostThink(void) { if (self->shownick_time && (self->shownick_time <= g_globalvars.time)) { self->shownick_time = 0; } if (!self->wp_stats && self->wp_stats_time && (self->wp_stats_time <= g_globalvars.time)) { self->wp_stats_time = 0; } if (!self->sc_stats && self->sc_stats_time && (self->sc_stats_time <= g_globalvars.time)) { self->sc_stats_time = 0; } if (self->need_clearCP && !self->shownick_time && !self->wp_stats_time && !self->sc_stats_time) { self->need_clearCP = 0; G_centerprint(self, "%s", ""); // clear center print } KickThink(); check_callalias(); } void W_WeaponFrame(void); void mv_record(void); void CheckStuffRune(void); // ==================================== // { new weapon stats WS_ void WS_Mark(gedict_t *p, weaponName_t wp) { if ((wp <= wpNONE) || (wp >= wpMAX)) { return; } p->wpstats_mask |= (1 << wp); } // force reset "new weapon stats" void WS_Reset(gedict_t *p) { int i; for (i = wpNONE + 1; i < wpMAX; i++) { WS_Mark(p, i); } } // spec changed pov, we need update him with new stats void WS_OnSpecPovChange(gedict_t *s, qbool force) { int i; gedict_t *p = s; if (s->ct == ctSpec) { p = PROG_TO_EDICT(s->s.v.goalentity); if (p->ct != ctPlayer) { return; // spec tracking whatever but not a player } } if (!(force || iKey(s, "wpsx"))) { return; // spec not interesting in new weapon stats } for (i = wpNONE + 1; i < wpMAX; i++) { // send it to spec, do not put it in demos stuffcmd_flags(s, STUFFCMD_IGNOREINDEMO, "//wps %d %s %d %d\n", NUM_FOR_EDICT(p) - 1, WpName(i), p->ps.wpn[i].attacks, p->ps.wpn[i].hits); } } void WS_CheckUpdate(gedict_t *p) { int i, j, trackers_cnt; gedict_t *trackers[MAX_CLIENTS], *s; if (!p->wpstats_mask) { return; } i = EDICT_TO_PROG(p); trackers_cnt = 0; memset(trackers, 0, sizeof(trackers)); for (s = world; (s = find_client(s));) { if (trackers_cnt >= MAX_CLIENTS) // should not be the case { G_Error("WS_CheckUpdate: trackers_cnt >= MAX_CLIENTS"); } if (s->ct == ctPlayer) { if (s != p) { continue; // we search for self only in players } } else { if (i != s->s.v.goalentity) { continue; // spec do not track this player } } if (!iKey(s, "wpsx")) { continue; // client not interesting in new weapon stats } trackers[trackers_cnt++] = s; // remember this spec } for (i = wpNONE + 1; i < wpMAX; i++) { if (!(p->wpstats_mask & (1 << i))) { continue; } // put it in demo only stuffcmd_flags(p, STUFFCMD_DEMOONLY, "//wps %d %s %d %d\n", NUM_FOR_EDICT(p) - 1, WpName(i), p->ps.wpn[i].attacks, p->ps.wpn[i].hits); // send it to clients, do not put it in demos for (j = 0; j < trackers_cnt; j++) { stuffcmd_flags(trackers[j], STUFFCMD_IGNOREINDEMO, "//wps %d %s %d %d\n", NUM_FOR_EDICT(p) - 1, WpName(i), p->ps.wpn[i].attacks, p->ps.wpn[i].hits); } } p->wpstats_mask = 0; } void info_wpsx_update(gedict_t* p, char* from, char* to) { qbool newly_enabled = atoi(to) && !atoi(from); if (newly_enabled) { WS_OnSpecPovChange(p, true); } } // } end of new weapon stats // ==================================== void CheckLand(void) { // clear the flag if we landed if ((int)self->s.v.flags & FL_ONGROUND) { self->brokenankle = 0; } // check to see if player landed and play landing sound if ((self->jump_flag < -300) && (((int)(self->s.v.flags)) & FL_ONGROUND)) { // Falling often results in 5-5 points of damage through 2 frames. // This fixes the bug self->s.v.velocity[2] = 0; if (self->s.v.watertype == CONTENT_WATER) { sound(self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM); } else if (self->jump_flag < jumpf_flag) { gedict_t *gre = PROG_TO_EDICT(self->s.v.groundentity); // set the flag if needed if (self->s.v.waterlevel < 2) { if (!get_fallbunny()) { self->brokenankle = 1; // Yes we have just broken it } } self->deathtype = dtFALL; T_Damage(self, world, world, 5); sound(self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM); if (gre && (gre->s.v.takedamage == DAMAGE_AIM) && (gre != self)) { // we landed on someone's head, hurt him gre->deathtype = dtSTOMP; T_Damage(gre, self, self, 10); } } else { sound(self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM); } } self->jump_flag = self->s.v.velocity[2]; } //////////////// // GlobalParams: // time // self /////////////// void PlayerPostThink(void) { //dprint ("post think\n"); WS_CheckUpdate(self); if (intermission_running) { setorigin(self, PASSVEC3(intermission_spot->s.v.origin)); SetVector(self->s.v.velocity, 0, 0, 0); // don't stray off the intermission spot too far return; } if (self->s.v.deadflag) { return; } //team // WaterMove function call moved here from PlayerPreThink to avoid // occurrence of the spawn lavaburn bug and to fix the problem on spawning // and playing the leave water sound if the player died underwater. WaterMove(); CheckLand(); CheckPowerups(); CheckLightEffects(); // NOTE: guess, this must be after CheckPowerups(), so u r warned. CheckStuffRune(); CTF_CheckFlagsAsKeys(); mv_record(); #ifdef BOT_SUPPORT if (bots_enabled()) { BotsThinkTime(self); } #endif W_WeaponFrame(); race_player_post_think(); { float velocity = sqrt( self->s.v.velocity[0] * self->s.v.velocity[0] + self->s.v.velocity[1] * self->s.v.velocity[1]); if (!match_in_progress && !match_over && !k_captains && !k_matchLess && !isHoonyModeAny()) { if (iKey(self, "kf") & KF_SPEED) { float velocity_vert_abs = fabs(self->s.v.velocity[2]); self->s.v.armorvalue = (int)(velocity < 1000 ? velocity + 1000 : -velocity); self->s.v.frags = (int)(velocity) / 1000; self->s.v.ammo_shells = 100 + (int)(velocity_vert_abs) / 100000000; self->s.v.ammo_nails = 100 + (int)(velocity_vert_abs) % 1000000 / 10000; self->s.v.ammo_rockets = 100 + (int)(velocity_vert_abs) % 10000 / 100; self->s.v.ammo_cells = 100 + (int)(velocity_vert_abs) % 100; } else if (isCA()) { // do nothing } else { self->s.v.armorvalue = 0; self->s.v.frags = 0; } } if (match_in_progress == 2) { self->ps.vel_frames++; self->ps.velocity_sum += velocity; if (self->ps.velocity_max < velocity) { self->ps.velocity_max = velocity; } } } } #define MAX_MEMBERS (10) // max members per team // clnum origin(3 ints) health armor items nick void SendTeamInfo(gedict_t *t) { int cl, cnt, h, a, shells, nails, rockets, cells; gedict_t *p, *s; char *tm, *nick; s = (t->ct == ctSpec ? PROG_TO_EDICT(t->s.v.goalentity) : t); if (s->ct != ctPlayer) { return; } tm = getteam(s); for (cnt = 0, p = world; (p = find_plr(p));) { if (cnt >= MAX_MEMBERS) { break; } if (p == s) { continue; // ignore self } if (strneq(tm, getteam(p))) { continue; // on different team } if (k_bloodfest && !ISLIVE(p)) { continue; // do not send it if mate is dead in bloodfest mode. } if (t->trackent && t->trackent == NUM_FOR_EDICT(p)) { continue; // we pseudo speccing such player, no point to send info about him } if (isCA() && !ISLIVE(p)) { continue; // see CA_SendTeamInfo for custom CA/wipeout teaminfo } if (strnull(nick = ezinfokey(p, "k_nick"))) // get nick, if any, do not send name, client can guess it too { nick = ezinfokey(p, "k"); } if (nick[0] && nick[1] && nick[2] && nick[3]) { nick[4] = 0; // truncate nick to 4 symbols } cnt++; cl = NUM_FOR_EDICT(p) - 1; h = bound(0, (int)p->s.v.health, 999); a = bound(0, (int)p->s.v.armorvalue, 999); shells = bound(0, (int)p->s.v.ammo_shells, 999); nails = bound(0, (int)p->s.v.ammo_nails, 999); rockets = bound(0, (int)p->s.v.ammo_rockets, 999); cells = bound(0, (int)p->s.v.ammo_cells, 999); stuffcmd_flags(t, STUFFCMD_IGNOREINDEMO, "//tinfo %d %d %d %d %d %d %d \"%s\" %d %d %d %d\n", cl, (int)p->s.v.origin[0], (int)p->s.v.origin[1], (int)p->s.v.origin[2], h, a, (int)p->s.v.items, nick, shells, nails, rockets, cells); } } void CheckTeamStatus(void) { gedict_t *p; int k_teamoverlay; if (!isTeam() && !isCTF() && !coop) { return; // non team game } if (isRACE()) { return; // could advance in the future by working out ongoing positions and sending those? } if ((g_globalvars.time - lastTeamLocationTime) < TEAM_LOCATION_UPDATE_TIME) { return; } lastTeamLocationTime = g_globalvars.time; k_teamoverlay = cvar("k_teamoverlay"); for (p = world; (p = find_client(p));) { int ti; if (!k_teamoverlay) // teamoverlay turned off { if (p->ct != ctSpec) // sent overlay to spec only then { continue; } } if ((ti = iKey(p, "ti")) < 0) { continue; // user specifie no team info } // check for ezquake or user specifie use team info even non ezquake client if ((ti > 0) || (p->ezquake_version > 0)) { SendTeamInfo(p); } } } void SendSpecInfo(gedict_t *spec, gedict_t *target_client) { gedict_t *t, *p; int cl, tr; if (spec) // if spec has a value, we only want to send that spec's info { cl = NUM_FOR_EDICT(spec) - 1; tr = NUM_FOR_EDICT(PROG_TO_EDICT(spec->s.v.goalentity)) - 1; // num for player spec is tracking for (p = world; (p = find_client(p));) { if (p == spec) continue; // ignore self stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "//spi %d %d\n", cl, tr); } } else { for (t = world; (t = find_spc(t));) { cl = NUM_FOR_EDICT(t) - 1; tr = NUM_FOR_EDICT(PROG_TO_EDICT(t->s.v.goalentity)) - 1; // num for player spec is tracking if (target_client && target_client != t) { stuffcmd_flags(target_client, STUFFCMD_IGNOREINDEMO, "//spi %d %d\n", cl, tr); } else // if no target client is specified, send to everyone { for (p = world; (p = find_client(p));) { if (p == t) continue; // ignore self stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "//spi %d %d\n", cl, tr); } } } } } void TookWeaponHandler(gedict_t *p, int new_wp, qbool from_backpack) { weaponName_t wp; switch (new_wp) { // guess which weapon he took case IT_AXE: wp = wpAXE; break; case IT_SHOTGUN: wp = wpSG; break; case IT_SUPER_SHOTGUN: wp = wpSSG; break; case IT_NAILGUN: wp = wpNG; break; case IT_SUPER_NAILGUN: wp = wpSNG; break; case IT_GRENADE_LAUNCHER: wp = wpGL; break; case IT_ROCKET_LAUNCHER: wp = wpRL; break; case IT_LIGHTNING: wp = wpLG; break; default: wp = wpNONE; } p->ps.wpn[wp].ttooks++; // total weapon tooks if (!from_backpack) { p->ps.wpn[wp].sttooks++; // spawned item tooks } // player does't have this weapon before took if (!((int)p->s.v.items & new_wp)) { if (!from_backpack) { p->ps.wpn[wp].stooks++; // spawned item tooks } p->ps.wpn[wp].tooks++; adjust_pickup_time(&p->wp_pickup_time[wp], &p->ps.wpn[wp].time); p->wp_pickup_time[wp] = g_globalvars.time; } } void StatsHandler(gedict_t *targ, gedict_t *attacker) { int items = targ->s.v.items; weaponName_t wp; char *attackerteam, *targteam; int i; attackerteam = getteam(attacker); targteam = getteam(targ); for (i = itNONE; i < itMAX; i++) { adjust_pickup_time(&targ->it_pickup_time[i], &targ->ps.itm[i].time); } for (i = wpNONE; i < wpMAX; i++) { adjust_pickup_time(&targ->wp_pickup_time[i], &targ->ps.wpn[i].time); } // update spree stats if (strneq(attackerteam, targteam) || !tp_num()) { attacker->ps.spree_current++; if (attacker->super_damage_finished > 0) { attacker->ps.spree_current_q++; } } targ->ps.spree_max = max(targ->ps.spree_current, targ->ps.spree_max); targ->ps.spree_max_q = max(targ->ps.spree_current_q, targ->ps.spree_max_q); targ->ps.spree_current = targ->ps.spree_current_q = 0; if (isDuel()) { // player dieing loses control if (targ->control_start_time) { targ->ps.control_time += g_globalvars.time - targ->control_start_time; targ->control_start_time = 0; } // player killing with spree of 2 gains control if (attacker->ps.spree_current >= 2 && !attacker->control_start_time) { attacker->control_start_time = g_globalvars.time; } // FIXME: We should want to consider other times when control switches. // Some ideas: // - if one player gets a much larger stack (Mega + RA) we can probably assume // they have taken control. This could be detected on Mega / RA pickup. // - if one player takes RA multiple times in a row, they may indicate they // have won control but not yet killed the opponent, or opponent is hiding. // This could be detected on RA pickup. } if (attacker->ct == ctPlayer) { switch (targ->deathtype) { case dtAXE: wp = wpAXE; break; case dtSG: wp = wpSG; break; case dtSSG: wp = wpSSG; break; case dtNG: wp = wpNG; break; case dtSNG: wp = wpSNG; break; case dtGL: wp = wpGL; break; case dtRL: wp = wpRL; break; case dtLG_BEAM: case dtLG_DIS: case dtLG_DIS_SELF: wp = wpLG; break; default: wp = wpNONE; } if (targ == attacker) { targ->ps.wpn[wp].suicides++; } else if ((isTeam() || isCTF()) && streq(targteam, attackerteam) && !strnull(attackerteam)) { // team kill attacker->ps.wpn[wp].tkills++; } else { // normal kill attacker->ps.wpn[wp].kills++; targ->ps.wpn[wp].deaths++; // hmm, may be add some priority? so if targ have rl and gl bump only wpn[wpRL].ekills ? if ((items & IT_AXE)) { attacker->ps.wpn[wpAXE].ekills++; } if ((items & IT_SHOTGUN)) { attacker->ps.wpn[wpSG].ekills++; } if ((items & IT_SUPER_SHOTGUN)) { attacker->ps.wpn[wpSSG].ekills++; } if ((items & IT_NAILGUN)) { attacker->ps.wpn[wpNG].ekills++; } if ((items & IT_SUPER_NAILGUN)) { attacker->ps.wpn[wpSNG].ekills++; } if ((items & IT_GRENADE_LAUNCHER)) { attacker->ps.wpn[wpGL].ekills++; } if ((items & IT_ROCKET_LAUNCHER)) { attacker->ps.wpn[wpRL].ekills++; } if ((items & IT_LIGHTNING)) { attacker->ps.wpn[wpLG].ekills++; } } } } // Instagib rewards are suspended till I figure out if that would be useful or not -- deurk // static int i_agmr_height = 0; // used for instagib, reset to 0 on each map reload... float Instagib_Obituary(gedict_t *targ, gedict_t *attacker) { float playerheight = 0; if (!cvar("k_instagib") || (attacker->ct != ctPlayer)) { return playerheight; } traceline(PASSVEC3(targ->s.v.origin), targ->s.v.origin[0], targ->s.v.origin[1], targ->s.v.origin[2] - 2048, true, targ); playerheight = targ->s.v.absmin[2] - g_globalvars.trace_endpos[2] + 1; if ((int)attacker->s.v.flags & FL_ONGROUND) { if ((playerheight >= 250) && (playerheight < 400)) { G_bprint(2, "%s from %s: height %d\n", redtext("AirGib"), attacker->netname, (int)playerheight); } else if ((playerheight >= 400) && (playerheight < 1000)) { G_bprint(2, "%s from %s: height %d\n", redtext("Great AirGib"), attacker->netname, (int)playerheight); } else if (playerheight >= 1000) { G_bprint(2, "%s from %s: height %d\n", redtext("Amazing AirGib"), attacker->netname, (int)playerheight); } if (playerheight > 45) { attacker->ps.i_height += playerheight; attacker->ps.i_maxheight = max(attacker->ps.i_maxheight, playerheight); attacker->ps.i_airgibs++; } } if (targ != attacker) { if (targ->deathtype == dtAXE) { attacker->ps.i_axegibs++; attacker->s.v.frags += 1; } else if (targ->deathtype == dtSTOMP) { attacker->ps.i_stompgibs++; attacker->s.v.frags += 3; } else if ((targ->deathtype == dtSG) || (targ->deathtype == dtSSG)) { attacker->ps.i_cggibs++; } } /* Instagib rewards are suspended till I figure out if that would be useful or not -- deurk if ( attacker->ps.i_height > 2000 ) { if ( !i_agmr_height ) { if ( !attacker->i_agmr ) { i_agmr_height = attacker->ps.i_height; attacker->i_agmr = 1; attacker->s.v.frags += 5; G_bprint( 2, "%s acquired the %s rune!\n", attacker->netname, redtext("AirGib Master")); } } else if ( attacker->ps.i_height > i_agmr_height ) { gedict_t *p; for( p = world; (p = find_client( p )); ) { if ( p->ct != ctPlayer || p == attacker || !p->i_agmr ) continue; i_agmr_height = attacker->ps.i_height; p->i_agmr = 0; p->s.v.frags -= 5; attacker->i_agmr = 1; attacker->s.v.frags += 5; G_bprint( 2, "%s took the %s rune from %s!\n", attacker->netname, redtext("AirGib Master"), p->netname); } } } */ return playerheight; } /* =========== ClientObituary called when a player dies ============ */ extern void ktpro_autotrack_on_death(gedict_t *dude); void ClientObituary(gedict_t *targ, gedict_t *attacker) { float playerheight; char *deathstring, *deathstring2; char *attackerteam, *targteam; char *attackername, *victimname; // Set it so it should update scores at next attempt. k_nochange = 0; if (match_in_progress != 2) { return; // nothing TODO in non match } if (isCA() && (ra_match_fight != 2)) { return; // nothing TODO in CA mode while countdown } if (targ->ct != ctPlayer) { return; } refresh_plus_scores(); //ZOID 12-13-96: self.team doesn't work in QW. Use keys attackerteam = getteam(attacker); targteam = getteam(targ); StatsHandler(targ, attacker); ktpro_autotrack_on_death(targ); playerheight = Instagib_Obituary(targ, attacker); if ((targ->deathtype == dtWATER_DMG) || (targ->deathtype == dtEXPLO_BOX) || (targ->deathtype == dtFALL) || ((targ->deathtype == dtSQUISH) && (attacker->ct != ctPlayer)) || (targ->deathtype == dtCHANGELEVEL) || (targ->deathtype == dtFIREBALL) || (targ->deathtype == dtSLIME_DMG) || (targ->deathtype == dtLAVA_DMG) || (targ->deathtype == dtTRIGGER_HURT)) { attackername = "world"; } else { attackername = attacker->netname; } victimname = targ->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%f\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, cleantext(attackername), cleantext(victimname), death_type(targ->deathtype), (int)(attacker->super_damage_finished > g_globalvars.time ? 1 : 0), (int)targ->s.v.armorvalue, (int)playerheight, g_globalvars.time - targ->spawn_time); if (isRA()) { ra_ClientObituary(targ, attacker); return; } if (isCA()) { CA_ClientObituary(targ, attacker); } if (k_bloodfest && !targ->ready) { return; // someone connecting during round of bloodfest and got pseudo death. } targ->deaths += 1; // somehow dead, bump counter if ((isTeam() || isCTF()) && streq(targteam, attackerteam) && !strnull(attackerteam) && (targ != attacker)) { attacker->friendly += 1; // bump teamkills counter } else if ((targ == attacker) || (attacker->ct != ctPlayer)) { attacker->suicides += 1; } else if (attacker->ct == ctPlayer) { attacker->kills += 1; } // { !!! THIS TELEFRAGS TYPES DOES'T HANDLE TEAM KILLS I DUNNO WHY !!! // mortal trying telefrag someone who has 666 if (dtTELE2 == targ->deathtype) { G_bprint(PRINT_MEDIUM, "Satan's power deflects %s's telefrag\n", victimname); targ->s.v.frags -= 1; logfrag(targ, targ); return; } // double 666 telefrag (can happen often in deathmatch 4) if (dtTELE3 == targ->deathtype) { G_bprint(PRINT_MEDIUM, "%s was telefragged by %s's Satan's power\n", victimname, attackername); targ->s.v.frags -= 1; logfrag(targ, targ); return; } // } if (attacker->ct == ctPlayer) // so, inside this "if" targ and attacker is players { if (targ == attacker) { // killed self if (!isHoonyModeDuel() && !isCA()) { targ->s.v.frags -= (dtSUICIDE == targ->deathtype ? 2 : 1); } logfrag(targ, targ); if (dtGL == targ->deathtype) { deathstring = " tries to put the pin back in\n"; } else if (dtRL == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " discovers blast radius\n"; break; default: deathstring = " becomes bored with life\n"; break; } } else if (dtLG_DIS_SELF == targ->deathtype) { deathstring = va(" electrocutes %s\n", g_himself(targ)); } else if (dtSQUISH == targ->deathtype) { //similar code present in case where !(attacker->ct == ctPlayer) deathstring = " was squished\n"; } else if (dtLG_DIS == targ->deathtype) { if (targ->s.v.watertype == CONTENT_SLIME) { deathstring = " discharges into the slime\n"; } else if (targ->s.v.watertype == CONTENT_LAVA) { deathstring = " discharges into the lava\n"; } else { switch ((int)(g_random() * 2)) { case 0: deathstring = " heats up the water\n"; break; default: deathstring = " discharges into the water\n"; break; } } } else if (dtSUICIDE == targ->deathtype) { deathstring = " suicides\n"; } else { deathstring = " somehow becomes bored with life\n"; // hm, and how it is possible? } G_bprint(PRINT_MEDIUM, "%s%s", victimname, deathstring); if (isHoonyModeDuel()) { HM_suicide(targ); } return; } else if (((isTeam() || isCTF()) && streq(targteam, attackerteam) && !strnull(attackerteam)) || coop) { // teamkill if ((dtTELE1 != targ->deathtype) || cvar("k_tp_tele_death")) { // -1 frag always if non "teledeath", and -1 on "teledeath" if allowed // also relax this rules on first seconds of match if ((g_globalvars.time - match_start_time) > 1) { attacker->s.v.frags -= 1; logfrag(attacker, attacker); //ZOID 12-13-96: killing a teammate logs as suicide } } // some deathtypes have specific death messages if (dtTELE1 == targ->deathtype) { G_bprint(PRINT_MEDIUM, "%s was telefragged by %s teammate\n", victimname, g_his(targ)); return; } else if (dtSQUISH == targ->deathtype) { G_bprint(PRINT_MEDIUM, "%s squished a teammate\n", attackername); return; } else if (dtSTOMP == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " was jumped by "; break; default: deathstring = " was crushed by "; break; } G_bprint(PRINT_MEDIUM, "%s%s%s teammate\n", victimname, deathstring, g_his(targ)); return; } // basic death messages switch ((int)(g_random() * 4)) { case 0: deathstring = va(" checks %s glasses\n", g_his(attacker)); break; case 1: deathstring = " loses another friend\n"; break; case 2: deathstring = " gets a frag for the other team\n"; break; default: deathstring = " mows down a teammate\n"; break; } G_bprint(PRINT_MEDIUM, "%s%s", attackername, deathstring); return; } else { // normal kill, Kteams version if (!cvar("k_dmgfrags") && !cvar("k_midair") && !lgc_enabled()) { // add frag only if not a case of k_dmgfrags attacker->s.v.frags += 1; } if (isCA()) { //Clan Arena give points for frags even with k_dmgfrags attacker->s.v.frags += 1; } logfrag(attacker, targ); attacker->victim = victimname; targ->killer = attackername; if ((targ->spawn_time + 2) > g_globalvars.time) { attacker->ps.spawn_frags++; } if (isCTF()) // handle various ctf bonuses { CTF_Obituary(targ, attacker); } deathstring2 = "\n"; // default is "\n" if (dtTELE1 == targ->deathtype) { deathstring = " was telefragged by "; } else if (dtSQUISH == targ->deathtype) { G_bprint(PRINT_MEDIUM, "%s squishes %s\n", attackername, victimname); if (isHoonyModeDuel()) { HM_next_point(attacker, targ); } return; // !!! return !!! } else if (dtSTOMP == targ->deathtype) { if (cvar("k_instagib")) { deathstring = " was literally stomped into particles by "; deathstring2 = "!\n"; } else { switch ((int)(g_random() * 5)) { case 0: deathstring = " softens "; deathstring2 = "'s fall\n"; break; case 1: deathstring = " tried to catch "; break; case 2: deathstring = " was jumped by "; break; case 3: deathstring = " was crushed by "; break; default: G_bprint(PRINT_MEDIUM, "%s stomps %s\n", attackername, victimname); if (isHoonyModeDuel()) { HM_next_point(attacker, targ); } return; // !!! return !!! } } } else if (dtNG == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " was body pierced by "; break; default: deathstring = " was nailed by "; break; } } else if (dtSNG == targ->deathtype) { switch ((int)(g_random() * 3)) { case 0: deathstring = " was punctured by "; break; case 1: deathstring = " was perforated by "; break; default: deathstring = " was ventilated by "; break; } if (targ->s.v.health < -40) // quad modifier { deathstring = " was straw-cuttered by "; } } else if (dtGL == targ->deathtype) { deathstring = " eats "; deathstring2 = "'s pineapple\n"; if (targ->s.v.health < -40) { deathstring = " was gibbed by "; deathstring2 = "'s grenade\n"; } } else if (dtRL == targ->deathtype) { deathstring = (targ->s.v.health < -40 ? " was gibbed by " : " rides "); deathstring2 = "'s rocket\n"; if ((attacker->super_damage_finished > 0) && (targ->s.v.health < -40) && (!cvar("k_midair"))) { switch ((int)(g_random() * 3)) { case 0: deathstring = " was brutalized by "; break; case 1: deathstring = " was smeared by "; break; default: G_bprint(PRINT_MEDIUM, "%s rips %s a new one\n", attackername, victimname); // hoonymode shouldn't have quad but just in case... if (isHoonyModeDuel()) { HM_next_point(attacker, targ); } return; // !!! return !!! } deathstring2 = "'s quad rocket\n"; } } else if (dtAXE == targ->deathtype) { if (cvar("k_instagib")) { deathstring = " was axed to pieces by "; deathstring2 = "!\n"; } else { deathstring = " was ax-murdered by "; } } else if (dtHOOK == targ->deathtype) { deathstring = " was hooked by "; } else if (dtSG == targ->deathtype) { deathstring = " chewed on "; deathstring2 = "'s boomstick\n"; if (targ->s.v.health < -40) { if (cvar("k_instagib")) { deathstring = " was instagibbed by "; } else { deathstring = " was lead poisoned by "; } deathstring2 = "\n"; } } else if (dtSSG == targ->deathtype) { if (attacker->super_damage_finished > 0) { deathstring = " ate 8 loads of "; } else { deathstring = " ate 2 loads of "; } if (cvar("k_instagib")) { deathstring = " was instagibbed by "; deathstring2 = "\n"; } else { deathstring2 = "'s buckshot\n"; } } else if (dtLG_BEAM == targ->deathtype) { if (targ->s.v.health < -40) { // quad shaft deathstring = " gets a natural disaster from "; deathstring2 = "\n"; } else { // normal shaft in most cases deathstring = " accepts "; deathstring2 = "'s shaft\n"; } } else if (dtLG_DIS == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " drains "; deathstring2 = "'s batteries\n"; break; default: deathstring = " accepts "; deathstring2 = "'s discharge\n"; } } else { G_cprint("Unknown death: normal death kt version\n"); deathstring = " killed by "; deathstring2 = " ?\n"; } if (!cvar("k_midair")) { G_bprint(PRINT_MEDIUM, "%s%s%s%s", victimname, deathstring, attackername, deathstring2); } } if (isHoonyModeDuel()) { HM_next_point(attacker, targ); } return; } else // attacker->ct != ctPlayer { if (!isHoonyModeDuel()) { targ->s.v.frags -= 1; // killed self } logfrag(targ, targ); if ((int)attacker->s.v.flags & FL_MONSTER) { deathstring = ObituaryForMonster(attacker->classname); // deathstring = " killed by monster? :)\n"; } else if (dtEXPLO_BOX == targ->deathtype) { deathstring = " blew up\n"; } else if (dtFALL == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " cratered\n"; break; default: deathstring = va(" fell to %s death\n", g_his(targ)); break; } } else if ((dtNG == targ->deathtype) || (dtSNG == targ->deathtype)) { deathstring = " was spiked\n"; } else if (dtLASER == targ->deathtype) { deathstring = " was zapped\n"; } else if (dtFIREBALL == targ->deathtype) { deathstring = " ate a lavaball\n"; } else if (dtCHANGELEVEL == targ->deathtype) { deathstring = " tried to leave\n"; } else if (dtSQUISH == targ->deathtype) { deathstring = " was squished\n"; } else if (dtWATER_DMG == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " sleeps with the fishes\n"; break; default: deathstring = " sucks it down\n"; break; } } else if (dtSLIME_DMG == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " gulped a load of slime\n"; break; default: deathstring = " can't exist on slime alone\n"; break; } } else if (dtLAVA_DMG == targ->deathtype) { switch ((int)(g_random() * 2)) { case 0: deathstring = " turned into hot slag\n"; break; default: deathstring = " visits the Volcano God\n"; break; } if (targ->s.v.health < -15) { deathstring = " burst into flames\n"; } } else if (dtTRIGGER_HURT == targ->deathtype) { deathstring = " died\n"; } else { deathstring = " died\n"; } G_bprint(PRINT_MEDIUM, "%s%s", victimname, deathstring); if (isHoonyModeDuel()) { HM_suicide(targ); } } } qbool PlayerCanPause(gedict_t *p) { qbool playerCanPause = false; char *matchtag = ezinfokey(world, "matchtag"); // Check for matchtag. If it is set, it is an official (probably), so pause might be allowed. if ((NULL != matchtag) && matchtag[0]) { // matchtag is found. Let's see if the player can still pause. if (p->k_pauseRequests > 0) { p->k_pauseRequests--; playerCanPause = true; } } return playerCanPause; } QW-Group-ktx-d05d6ca/src/coach.c000066400000000000000000000145031475442401000164430ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // coach.c #include "g_local.h" int coach_num(gedict_t *p) { if ((p->k_coach == 1) || (p->k_coach == 2)) { return p->k_coach; } return 0; } qbool is_coach(gedict_t *p) { if (p->k_coach) { return true; } return false; } void CancelCoaches(void) { gedict_t *p; k_coaches = 0; for (p = world; (p = find_plr(p));) { if (coach_num(p)) { G_sprint(p, 2, "You are no longer a %s\n", redtext("coach")); } p->k_coach = 0; if (is_elected(p, etCoach)) // just for sanity { AbortElect(); } } } void ExitCoach(void) { if (!coach_num(self)) { return; } self->k_coach = 0; k_coaches--; G_bprint(2, "%s coach present\n", (floor(k_coaches) ? "\x90\x31\x91" : redtext("No"))); // if 'nospecs' is active, a demoted coach must be kicked if (cvar("_k_nospecs")) { stuffcmd(self, "disconnect\n"); // FIXME: stupid way } } void VoteCoach(void) { int till; gedict_t *p, *electguard; // s: check if we are being elected or we are a coach already if (is_elected(self, etCoach)) { G_bprint(2, "%s %s!\n", self->netname, redtext("aborts election")); AbortElect(); return; } if (coach_num(self)) { G_bprint(2, "%s is no longer a %s\n", self->netname, redtext("coach")); ExitCoach(); return; } if (match_in_progress || intermission_running) { return; } if (!isTeam() && !isCTF()) { G_sprint(self, 2, "No team picking in non team mode\n"); return; } if (CountPlayers() < 3) { G_sprint(self, 2, "Not enough players present\n"); return; } if (k_coaches == 2) { G_sprint(self, 2, "Only 2 coaches are allowed\n"); return; } // s: no coach election if any election in progress if (get_votes( OV_ELECT)) { G_sprint(self, 2, "An election is already in progress\n"); return; } if ((till = Q_rint(self->v.elect_block_till - g_globalvars.time)) > 0) { G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } // s: no coaches with team "" if (strnull(getteam(self))) { G_sprint(self, 2, "Set your team name first\n"); return; } // search if a coach already has the same team for (p = world; (p = find_spc(p)) && !coach_num(p);) { ; // empty } if (p) { if (streq(getteam(self), getteam(p))) { G_sprint(self, 2, "A %s with team \x90%s\x91 already exists\n" "Choose a new team name\n", redtext("coach"), getteam(p)); return; } } // announce the election self->v.elect = 1; self->v.elect_type = etCoach; k_coaches += 0.5; G_bprint(2, "%s has %s status!\n", self->netname, redtext("requested coach")); for (p = world; (p = find_client(p));) { if ((p != self) && (p->ct == ctPlayer)) { G_sprint(p, 2, "Type %s in console to approve\n", redtext("yes")); } } G_sprint(self, 2, "Type %s to abort election\n", redtext("coach")); // s: spawn the cool dude electguard = spawn(); // Check the 1 minute timeout for election electguard->s.v.owner = EDICT_TO_PROG(world); electguard->classname = "electguard"; electguard->think = (func_t) ElectThink; electguard->s.v.nextthink = g_globalvars.time + 60; } void BecomeCoach(gedict_t *p) { gedict_t *coach = p; // warning, below 'p' is overwritten for (p = world; (p = find_plr(p)) && !coach_num(p);) { ; // empty } coach->k_coach = (p && coach_num(p) == 1) ? 2 : 1; // a coach cannot autotrack // coach->autotrack = atNone; k_coaches = floor(k_coaches) + 1; G_bprint(2, "%s becomes a %s\n", coach->netname, redtext("coach")); // s: if both coaches are already elected, start choosing players if (k_coaches < 2) { G_bprint(2, "One more %s should be elected\n", redtext("coach")); } } // A coach might only track players from his/her own team. // This function takes care of not allowing a coach to track enemy players. // It is called whenever a track change is detected for a coach, but unfortunately // it is called only after the track change. // The function can have multiple outcomes: // 1) the coach is jumped to a team mate -> nothing to do // 2) the coach is jumped to an enemy player // 2a) we are able to located a team mate -> start tracking that player instead // 2b) we are not able to find a team mate -> stop tracking completely // // The function returns true if there was a forced track change; false other wise qbool TrackChangeCoach(gedict_t *p) { gedict_t *target; int id; target = PROG_TO_EDICT(p->s.v.goalentity); // we only going to update the tracked player, if we are tracking at all // probably a paranoid check, as the function should not be called if the 'target' of the // spectator is not changed. if (((int)(target - world) >= 1) && ((int)(target - world) <= MAX_CLIENTS)) { // we are tracking someone. check team of the tracked player if (strneq(getteam(p), getteam(target))) { // team is not matching, so let's trying to locate a player within the coach's team // start from the currently tracked player, and go through the player list target = find_plr_same_team(target, getteam(p)); if (!target) { // we haven't found a team mate. lets restart the search from the 1st player target = find_plr_same_team(world, getteam(p)); } if (NULL != target) { // team mate found, lets track this play if ((id = GetUserID(target)) > 0) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "track %d\n", id); } } else { // no suitable player to track (all of them in enemy team) -> just stop tracking G_centerprint(p, "Found no suitable player to track"); // this is kind of ugly way to disable tracking, but I have no other idea :/ stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "-attack;wait;+attack;wait;-attack\n"); } return true; } } return false; } QW-Group-ktx-d05d6ca/src/combat.c000066400000000000000000000745521475442401000166450ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void ClientObituary(gedict_t *e1, gedict_t *e2); void BotPlayerKilledEvent(gedict_t *targ, gedict_t *attacker, gedict_t *inflictor); void bloodfest_killed_hook(gedict_t *killed, gedict_t *attacker); #define DEATHTYPE( _dt_, _dt_str_ ) #_dt_str_, char *deathtype_strings[] = { #include "deathtype.h" }; #undef DEATHTYPE const int deathtype_strings_cnt = sizeof(deathtype_strings) / sizeof(deathtype_strings[0]); char* death_type(deathType_t dt) { return deathtype_strings[(int)bound(0, dt, deathtype_strings_cnt - 1)]; } //============================================================================ qbool ISLIVE(gedict_t *e) { if (!e) { return false; } if (e->ct == ctPlayer) { return ((e->s.v.health > 0) && e->ca_alive); } return (e->s.v.health > 0); } qbool ISDEAD(gedict_t *e) { return !ISLIVE(e); } //============================================================================ /* ============ CanDamage Returns true if the inflictor can directly damage the target. Used for explosions and melee attacks. ============ */ qbool CanDamage(gedict_t *targ, gedict_t *inflictor) { vec3_t dif; // bmodels need special checking because their origin is 0,0,0 if (targ->s.v.movetype == MOVETYPE_PUSH) { traceline(PASSVEC3(inflictor->s.v.origin), 0.5 * (targ->s.v.absmin[0] + targ->s.v.absmax[0]), 0.5 * (targ->s.v.absmin[1] + targ->s.v.absmax[1]), 0.5 * (targ->s.v.absmin[2] + targ->s.v.absmax[2]), true, self); if (g_globalvars.trace_fraction == 1) { return true; } if (PROG_TO_EDICT(g_globalvars.trace_ent) == targ) { return true; } return false; } traceline(PASSVEC3(inflictor->s.v.origin), PASSVEC3(targ->s.v.origin), true, self); if (g_globalvars.trace_fraction == 1) { return true; } // 1998-09-16 CanDamage fix by Maddes/Kryten start // testing middle of half-size bounding box dif[2] = 0; // ...front right dif[1] = targ->s.v.maxs[1] * 0.5; dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...front left dif[0] = targ->s.v.mins[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back left dif[1] = targ->s.v.mins[1] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back right dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // testing top of half-sized bounding box dif[2] = targ->s.v.maxs[2] * 0.5; // ...front right dif[1] = targ->s.v.maxs[1] * 0.5; dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...front left dif[0] = targ->s.v.mins[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back left dif[1] = targ->s.v.mins[1] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back right dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // testing bottom of half-sized bounding box dif[2] = targ->s.v.mins[2] * 0.5; // ...front right dif[1] = targ->s.v.maxs[1] * 0.5; dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...front left dif[0] = targ->s.v.mins[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back left dif[1] = targ->s.v.mins[1] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // ...back right dif[0] = targ->s.v.maxs[0] * 0.5; traceline(PASSVEC3(inflictor->s.v.origin), targ->s.v.origin[0] + dif[0], targ->s.v.origin[1] + dif[1], targ->s.v.origin[2] + dif[2], true, self); if (g_globalvars.trace_fraction == 1) { return true; } // 1998-09-16 CanDamage fix by Maddes/Kryten end return false; } /* ============ Killed ============ */ void Killed(gedict_t *targ, gedict_t *attacker, gedict_t *inflictor) { gedict_t *oself; #ifdef BOT_SUPPORT BotPlayerKilledEvent(targ, attacker, inflictor); #endif if (lgc_enabled()) { lgc_register_kill(attacker); } oself = self; self = targ; if (self->s.v.health < -99) { self->s.v.health = -99; // don't let sbar look bad if a player } self->dead_time = g_globalvars.time; if (self->ct == ctPlayer) { ; // empty } else if ((self->s.v.movetype == MOVETYPE_PUSH) || (self->s.v.movetype == MOVETYPE_NONE)) { // doors, triggers, etc if (self->th_die) { self->th_die(); } self = oself; return; } self->s.v.enemy = EDICT_TO_PROG(attacker); // bump the monster counter if (((int)(self->s.v.flags)) & FL_MONSTER) { float resp_time = bound(0, cvar("k_monster_spawn_time"), 999999); // for nightmare mode self->monster_desired_spawn_time = ( resp_time ? g_globalvars.time + resp_time + resp_time * g_random() * 0.5 : 0); g_globalvars.killed_monsters++; WriteByte( MSG_ALL, SVC_KILLEDMONSTER); // in coop, killing a monster gives you a frag if (coop) { if (attacker->ct == ctPlayer) { attacker->s.v.frags++; } } } ClientObituary(self, attacker); self->s.v.takedamage = DAMAGE_NO; self->touch = (func_t) SUB_Null; self->s.v.effects = 0; monster_death_use(); if (self->th_die) { self->th_die(); } self = oself; // KTEAMS: check if sudden death is the case if (!isHoonyModeAny()) { Check_SD(targ); // check fraglimit if (fraglimit && (((targ->s.v.frags >= fraglimit) && (targ->ct == ctPlayer)) || ((attacker->s.v.frags >= fraglimit) && (attacker->ct == ctPlayer)))) { EndMatch(0); } if (fraglimit && isTeam()) { // in team modes fraglimit can be a sum of frags of all players in the team if ((get_scores1() >= fraglimit) || (get_scores2() >= fraglimit) || (get_scores3() >= fraglimit)) { EndMatch(0); } } } if (k_bloodfest) { bloodfest_killed_hook(targ, attacker); } } #ifndef Q3_VM // qvm have some bugs/round problem as i get from SD-Angel, so this trick static float newceil(float f) { return ceil(((int)(f * 1000.0)) / 1000.0); } #else // native use lib ceil function #define newceil ceil #endif // this was part of T_Damage(), but I split it, so less mess void MidairDamageBonus(gedict_t *attacker, gedict_t *targ, float midheight) { char *rank, *icon; rank = icon = ""; attacker->ps.mid_total++; if (midheight > 1024) { attacker->ps.mid_platinum++; attacker->s.v.frags += 8; rank = "platinum"; icon = "\211"; } else if (midheight > 512) { attacker->ps.mid_gold++; attacker->s.v.frags += 4; rank = "gold"; icon = "\210"; } else if (midheight > 256) { attacker->ps.mid_silver++; attacker->s.v.frags += 2; rank = "silver"; icon = "\204"; } else { attacker->ps.mid_bronze++; attacker->s.v.frags += 1; rank = "bronze"; icon = "\213"; } G_bprint(2, "%s %-15s \133%s\135 by %s on %s\n", icon, dig3s("%s midair", rank), dig3s("%7.1f", midheight), attacker->netname, targ->netname); if (attacker->ps.mid_total > 1) { attacker->ps.mid_totalheight += midheight; attacker->ps.mid_avgheight = attacker->ps.mid_totalheight / attacker->ps.mid_total; } else { attacker->ps.mid_totalheight = attacker->ps.mid_avgheight = midheight; } if (attacker->ps.mid_maxheight < midheight) { attacker->ps.mid_maxheight = midheight; } } /* ============ T_Damage The damage is coming from inflictor, but get mad at attacker This should be the only function that ever reduces health. ============ */ gedict_t *damage_attacker, *damage_inflictor; static int dmg_is_splash = 0; void T_Damage(gedict_t *targ, gedict_t *inflictor, gedict_t *attacker, float damage) { vec3_t dir; gedict_t *oldself; float save; float take; int i, c1 = 8, c2 = 4, hdp; float dmg_dealt = 0, virtual_take = 0, unbound_dmg_dealt = 0; float non_hdp_damage; // save damage before handicap apply for kickback calculation float native_damage = damage; // save damage before apply any modificator char *attackerteam, *targteam, *attackername, *victimname; qbool tp4teamdmg = false; //midair and instagib float playerheight = 0, midheight = 0; qbool midair = false, inwater = false, do_dmg = false, rl_dmg = false, stomp_dmg = false; // used by buttons and triggers to set activator for target firing damage_attacker = attacker; damage_inflictor = inflictor; attackerteam = getteam(attacker); targteam = getteam(targ); // can't apply damage to dead if (!targ->s.v.takedamage || ISDEAD(targ)) { return; } // can't damage other players in race if (isRACE() && (attacker != targ)) { if ((targ->ct == ctPlayer) && (attacker->ct == ctPlayer)) { return; } } if (isCA()) { if (dtWATER_DMG == targ->deathtype // No drowning in CA || dtFALL == targ->deathtype) // No fall damage in CA { return; } // ignore almost all damage in CA while coutdown else if (match_in_progress && (ra_match_fight != 2)) { if (!(dtTELE1 == targ->deathtype // always do tele damage || dtTELE2 == targ->deathtype // always do tele damage || dtTELE3 == targ->deathtype // always do tele damage || dtSUICIDE == targ->deathtype)) // do suicide damage anyway { return; } } // don't accept any damage in CA modes if no_pain is true if ((targ->no_pain || (attacker->no_pain && attacker->in_play)) && (match_in_progress == 2)) { if (attacker == targ) { tp4teamdmg = true; // don't take damage but still get stopped/bounced by weapon fire } else { if (targ->in_play && (targ->invincible_sound < g_globalvars.time) && strneq(targteam, attackerteam)) { sound(targ, CHAN_AUTO, "items/protect3.wav", 0.75, ATTN_NORM); targ->invincible_sound = g_globalvars.time + 2; } return; } } } if ((int)cvar("k_midair")) { midair = true; } // in bloodfest boss damage factor. if (k_bloodfest && attacker->bloodfest_boss) { damage *= 4; } // check for quad damage powerup on the attacker // midair quad makes rockets fast, but no change to damage if ((attacker->super_damage_finished > g_globalvars.time) && strneq(inflictor->classname, "door") && (dtSTOMP != targ->deathtype) && !midair) { // in dmm4 quad is octa actually, unless tot_mode_enabled(), // then it's possible to set custom multiplier damage *= (deathmatch != 4 ? 4 : tot_mode_enabled() ? FrogbotQuadMultiplier() : 8); } // ctf strength rune if (attacker->ctf_flag & CTF_RUNE_STR) { damage *= (cvar("k_ctf_rune_power_str") / 2) + 1; } // ctf resistance rune if (targ->ctf_flag & CTF_RUNE_RES) { damage /= (cvar("k_ctf_rune_power_res") / 2) + 1; ResistanceSound(targ); } // did we hurt enemy flag carrier? if ((targ->ctf_flag & CTF_FLAG) && (!streq(targteam, attackerteam))) { attacker->carrier_hurt_time = g_globalvars.time; } // in teamplay 4 we do no armor or health damage to teammates (unless telefrag), but do apply velocity changes if (tp_num() == 4&& streq(targteam, attackerteam) && ( isCA() || targ != attacker ) && !TELEDEATH(targ)) { tp4teamdmg = true; } if (midair || cvar("k_instagib")) { traceline(PASSVEC3(targ->s.v.origin), targ->s.v.origin[0], targ->s.v.origin[1], targ->s.v.origin[2] - 2048, true, targ); playerheight = targ->s.v.absmin[2] - g_globalvars.trace_endpos[2] + (cvar("k_instagib") ? 1 : 0); } // get some data before apply damage in mid air mode if (midair) { inwater = (((int)targ->s.v.flags & FL_INWATER) && targ->s.v.waterlevel > 1); if (streq(inflictor->classname, "rocket")) { midheight = targ->s.v.origin[2] - inflictor->s.v.oldorigin[2]; } rl_dmg = (targ->ct == ctPlayer && dtRL == targ->deathtype); stomp_dmg = (targ->ct == ctPlayer && dtSTOMP == targ->deathtype); if (!rl_dmg) { // damage types which ignore "lowheight" do_dmg = targ->ct != ctPlayer // always do damage to non player, secret doors etc... || dtWATER_DMG == targ->deathtype // always do water damage || dtLAVA_DMG == targ->deathtype // always do lava damage || dtSLIME_DMG == targ->deathtype // always do slime damage || dtSTOMP == targ->deathtype // always do stomp damage || dtTELE1 == targ->deathtype // always do tele damage || dtTELE2 == targ->deathtype // always do tele damage || dtTELE3 == targ->deathtype // always do tele damage || dtSUICIDE == targ->deathtype; // do suicide damage anyway } } non_hdp_damage = damage; // save damage before handicap apply for kickback calculation // #handicap# if (attacker != targ) // attack no self { if ((attacker->ct == ctPlayer) && (targ->ct == ctPlayer)) // player vs player { if ((hdp = GetHandicap(attacker)) != 100) // skip checks if hdp == 100 { if ((dtAXE == targ->deathtype) || (dtSG == targ->deathtype) || (dtSSG == targ->deathtype) || (dtNG == targ->deathtype) || (dtSNG == targ->deathtype) || (dtGL == targ->deathtype) || (dtRL == targ->deathtype) || (dtLG_BEAM == targ->deathtype) || (dtLG_DIS == targ->deathtype) || (dtLG_DIS_SELF == targ->deathtype)) // even that impossible { damage *= 0.01f * hdp; } } } } // save damage based on the target's armor level save = newceil(targ->s.v.armortype * damage); if (tp4teamdmg) { save = 0; // we do not touch armor } if (save >= targ->s.v.armorvalue) { save = targ->s.v.armorvalue; targ->s.v.armortype = 0; // lost all armor targ->s.v.items -= ((int)targ->s.v.items & ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)); } dmg_dealt += save; if (match_in_progress == 2) { targ->s.v.armorvalue = targ->s.v.armorvalue - save; } take = newceil(damage - save); // mid air damage modificators if (midair) { int k_midair_minheight, midair_minheight; k_midair_minheight = (int)cvar("k_midair_minheight"); if (k_midair_minheight == 1) { midair_minheight = 128; } else if (k_midair_minheight == 2) { midair_minheight = 256; } else if (k_midair_minheight == 3) { midair_minheight = 512; } else if (k_midair_minheight == 4) { midair_minheight = 1024; } else { midair_minheight = 64; } if (rl_dmg || stomp_dmg) { take = 9999; } if ((playerheight < midair_minheight) && rl_dmg) { take = 0; // no dmg done if target is not high enough } if ((playerheight < 45) && !inwater && rl_dmg) { take = 0; // no rl dmg in such case } if (!rl_dmg && !do_dmg) { take = 0; // unknown damage for midair, so do not damage } if (rl_dmg && (targ == attacker)) { take = 0; // no self rl damage } } // instagib damage modificators if (cvar("k_instagib")) { if (inflictor->ct == ctPlayer) { take = 5000; } if (attacker == targ) { take = 0; } } // helps kill player in prewar at "wrong" places if ((match_in_progress != 2) && (native_damage > 450)) { take = 99999; } // team play damage avoidance and godmode or invincibility check virtual_take = max(0, take); // virtual_take used for calculating dmg_dealt only in case of k_dmgfrags // ignore this checks for suicide damage if (dtSUICIDE != targ->deathtype) { if ((int)targ->s.v.flags & FL_GODMODE) { take = 0; // what if god was one of us } else if (targ->invincible_finished >= g_globalvars.time) { if (targ->invincible_sound < g_globalvars.time) { sound(targ, CHAN_AUTO, "items/protect3.wav", 1, ATTN_NORM); targ->invincible_sound = g_globalvars.time + 2; } take = 0; } else if (((tp_num() == 1) || ((tp_num() == 3) && (targ != attacker))) && !strnull(attackerteam) && streq(targteam, attackerteam) && (attacker->ct == ctPlayer) && strneq( inflictor->classname, "door") && !TELEDEATH(targ)) // do telefrag damage in tp { // teamplay == 1 don't damage self and mates (armor affected anyway) // teamplay == 3 don't damage mates, do damage to self (armor affected anyway) take = 0; } else if (tp4teamdmg) { take = 0; // we do not touch health } } take = max(0, take); // avoid negative take, if any unbound_dmg_dealt = dmg_dealt; if (cvar("k_dmgfrags")) { if (TELEDEATH(targ)) { // tele doesn't count for any dmgfrags damage dmg_dealt = 0; } else if (targ->invincible_finished >= g_globalvars.time) { // damage dealt _not_ capped by victim's health if victim has pent unbound_dmg_dealt += virtual_take; dmg_dealt += virtual_take; } else { // damage dealt capped by victim's health unbound_dmg_dealt += virtual_take; dmg_dealt += bound(0, virtual_take, targ->s.v.health); } } else { // damage dealt capped by victim's health unbound_dmg_dealt += virtual_take; dmg_dealt += bound(0, take, targ->s.v.health); } // add to the damage total for clients, which will be sent as a single // message at the end of the frame // FIXME: remove after combining shotgun blasts? if (targ->ct == ctPlayer) { targ->s.v.dmg_take += take; targ->s.v.dmg_save += save; targ->s.v.dmg_inflictor = EDICT_TO_PROG(inflictor); } unbound_dmg_dealt = bound(0, unbound_dmg_dealt, 9999); if ((sv_extensions & SV_EXTENSIONS_MVDHIDDEN) && ((int)unbound_dmg_dealt > 0) && ((attacker->ct == ctPlayer) || (targ->ct == ctPlayer))) { int damage_flags = (dmg_is_splash ? MVDHIDDEN_DMGDONE_SPLASHDAMAGE : 0); // MVD damage: always send WriteShort(MSG_MULTICAST, mvdhidden_dmgdone); WriteShort(MSG_MULTICAST, damage_flags | targ->deathtype); WriteShort(MSG_MULTICAST, NUM_FOR_EDICT(attacker)); WriteShort(MSG_MULTICAST, NUM_FOR_EDICT(targ)); WriteShort(MSG_MULTICAST, (short)unbound_dmg_dealt); trap_multicast(PASSVEC3(targ->s.v.origin), MULTICAST_MVD_HIDDEN); } // Only send to clients during standby if (!match_in_progress && ((int)unbound_dmg_dealt > 0) && (attacker->ct == ctPlayer) && (targ->ct == ctPlayer)) { int di = atoi(ezinfokey(attacker, "di")); if (di && ((di == 2) || (attacker != targ))) { qbool has_eyes = ((int)targ->s.v.items) & IT_INVISIBILITY; stuffcmd_flags(attacker, STUFFCMD_IGNOREINDEMO, "//ktx di %d %d %d %d %d %d %d\n", PASSINTVEC3(targ->s.v.origin), targ->deathtype, (short)unbound_dmg_dealt, dmg_is_splash ? 1 : 0, SameTeam(attacker, targ) && !has_eyes ? 1 : 0); } } if (save) { if ((streq(inflictor->classname, "worldspawn") || strnull(attacker->classname)) || (targ->deathtype == dtWATER_DMG) || (targ->deathtype == dtEXPLO_BOX) || (targ->deathtype == dtFALL) || (targ->deathtype == dtSQUISH) || (targ->deathtype == dtCHANGELEVEL) || (targ->deathtype == dtFIREBALL) || (targ->deathtype == dtSLIME_DMG) || (targ->deathtype == dtLAVA_DMG) || (targ->deathtype == dtTRIGGER_HURT)) { attackername = "world"; } else { attackername = attacker->netname; } victimname = targ->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t1\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, cleantext(attackername), cleantext(victimname), death_type(targ->deathtype), (int)(attacker->super_damage_finished > g_globalvars.time ? 1 : 0), dmg_is_splash, (int)save); } // figure momentum add if ((inflictor != world) && ((targ->s.v.movetype == MOVETYPE_WALK) || (k_bloodfest && ((int)targ->s.v.flags & FL_MONSTER)))) { float nailkick; for (i = 0; i < 3; i++) { dir[i] = targ->s.v.origin[i] - (inflictor->s.v.absmin[i] + inflictor->s.v.absmax[i]) * 0.5; } VectorNormalize(dir); dir[2] = ((dtLG_DIS_SELF == targ->deathtype || dtLG_DIS == targ->deathtype) && dir[2] < 0) ? -dir[2] : dir[2]; if (midair && (non_hdp_damage < 60) && (attacker != targ)) { c1 = 11; c2 = 6; } // Yawnmode: nails increases kickback // - Molgrum if (k_yawnmode && streq(inflictor->classname, "spike")) { nailkick = 1.2; } else { nailkick = 1.0; } for (i = 0; i < 3; i++) { targ->s.v.velocity[i] += dir[i] * non_hdp_damage * c1 * nailkick * (midair && playerheight >= 45 ? (1 + (playerheight - 45) / 64) : 1); } if (midair && (playerheight < 45)) { targ->s.v.velocity[2] += dir[2] * non_hdp_damage * c2 * nailkick; // only for z component } if (k_bloodfest && ((int)targ->s.v.flags & FL_MONSTER)) { targ->s.v.flags = (int)targ->s.v.flags & ~FL_ONGROUND; } #ifdef BOT_SUPPORT targ->fb.path_state |= AIR_ACCELERATION; #endif } #ifdef BOT_SUPPORT BotDamageInflictedEvent(attacker, targ); #endif if ((match_in_progress == 2) && ((int)cvar("k_dmgfrags") || lgc_enabled())) { if ((attacker->ct == ctPlayer) && (targ->ct == ctPlayer) && (attacker != targ)) { if (isDuel() || isFFA() || strneq(attackerteam, targteam)) { int dmg_frags; attacker->ps.dmg_frags += dmg_dealt; // add dealt dmg_frags = attacker->ps.dmg_frags / 100; // 1 frag = 100 damage attacker->s.v.frags = (int)(attacker->s.v.frags + dmg_frags); attacker->ps.dmg_frags -= dmg_frags * 100; } } } // do the damage if ((match_in_progress == 2) || (dtSUICIDE == targ->deathtype) // do suicide damage anyway || TELEDEATH(targ) || (k_practice && targ->ct != ctPlayer) // #practice mode# || (take >= 99999)) // do such huge damage even in prewar, prewar because indirectly here match_in_progress != 2 { targ->s.v.health -= take; // G_bprint( 2, "%s %f\n", targ->classname, targ->s.v.health ); if (take) { if ((streq(inflictor->classname, "worldspawn") || strnull(attacker->classname)) || (targ->deathtype == dtWATER_DMG) || (targ->deathtype == dtEXPLO_BOX) || (targ->deathtype == dtFALL) || (targ->deathtype == dtSQUISH) || (targ->deathtype == dtCHANGELEVEL) || (targ->deathtype == dtFIREBALL) || (targ->deathtype == dtSLIME_DMG) || (targ->deathtype == dtLAVA_DMG) || (targ->deathtype == dtTRIGGER_HURT)) { attackername = "world"; } else { attackername = attacker->netname; } victimname = targ->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t0\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, cleantext(attackername), cleantext(victimname), death_type(targ->deathtype), (int)(attacker->super_damage_finished > g_globalvars.time ? 1 : 0), dmg_is_splash, (int)take); } if (!targ->s.v.health || (dtSUICIDE == targ->deathtype)) { targ->s.v.health = -1; // qqshka, no zero health, heh, imo less bugs after this } } // show damage in sbar if ((match_in_progress != 2) && ISLIVE(targ) && !k_matchLess) { if (!midair || ((int)targ->s.v.flags & FL_ONGROUND)) { if (targ->ct == ctPlayer) { targ->s.v.currentammo = 1000 + Q_rint(damage); } if ((attacker != targ) && (attacker->ct == ctPlayer)) { attacker->s.v.health = 1000 + Q_rint(damage); } } } // update damage stats like: give/taked/team damage if ((attacker->ct == ctPlayer) && (targ->ct == ctPlayer)) { int weapon = wpNONE; switch (targ->deathtype) { case dtAXE: weapon = wpAXE; break; case dtSG: weapon = wpSG; break; case dtSSG: weapon = wpSSG; break; case dtNG: weapon = wpNG; break; case dtSNG: weapon = wpSNG; break; case dtGL: weapon = wpGL; break; case dtRL: weapon = wpRL; break; case dtLG_BEAM: case dtLG_DIS: weapon = wpLG; break; } if (attacker == targ) { // self damage attacker->ps.dmg_self += dmg_dealt; } else { int items = targ->s.v.items; if (tp_num() && streq(attackerteam, targteam)) { attacker->ps.dmg_team += dmg_dealt; attacker->ps.wpn[weapon].tdamage += dmg_dealt; // damage to enemy weapon if (items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) { attacker->ps.dmg_tweapon += dmg_dealt; } } else { attacker->ps.dmg_g += dmg_dealt; targ->ps.dmg_t += dmg_dealt; attacker->ps.wpn[weapon].edamage += dmg_dealt; // damage to enemy weapon if (items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) { attacker->ps.dmg_eweapon += dmg_dealt; } } // real hits if (take || save) { if (dtRL == targ->deathtype) { attacker->ps.wpn[wpRL].rhits++; } if (dtGL == targ->deathtype) { attacker->ps.wpn[wpGL].rhits++; } } // virtual hits if (virtual_take || save) { if (dtRL == targ->deathtype) { attacker->ps.wpn[wpRL].vhits++; // virtual given rl damage attacker->ps.dmg_g_rl += (virtual_take + save); } if (dtGL == targ->deathtype) { attacker->ps.wpn[wpGL].vhits++; } } } } // mid air bonuses if (midair && (match_in_progress == 2) && (attacker != targ) && take && rl_dmg) { MidairDamageBonus(attacker, targ, midheight); } if (midair && (match_in_progress == 2) && stomp_dmg) { attacker->ps.mid_stomps++; targ->s.v.frags -= 3; } #ifdef BOT_SUPPORT FrogbotSetHealthArmour(targ); #endif // if targed killed, do appropriate action and return if (ISDEAD(targ)) { Killed(targ, attacker, inflictor); return; } // react to the damage - call pain function oldself = self; self = targ; if ((int)self->s.v.flags & FL_MONSTER) { GetMadAtAttacker(attacker); } if (self->th_pain) { self->th_pain(attacker, take); } self = oldself; } void T_RadiusDamageApply(gedict_t *inflictor, gedict_t *attacker, gedict_t *head, float damage, deathType_t dtype) { float points; vec3_t org; if (head->s.v.takedamage) { org[0] = inflictor->s.v.origin[0] - (head->s.v.origin[0] + (head->s.v.mins[0] + head->s.v.maxs[0]) * 0.5); org[1] = inflictor->s.v.origin[1] - (head->s.v.origin[1] + (head->s.v.mins[1] + head->s.v.maxs[1]) * 0.5); org[2] = inflictor->s.v.origin[2] - (head->s.v.origin[2] + (head->s.v.mins[2] + head->s.v.maxs[2]) * 0.5); points = 0.5 * vlen(org); if (points < 0) { points = 0; } points = damage - points; if (head == attacker) { points = points * 0.5; } // no out of water discharge damage if k_dis 2 else if ((cvar("k_dis") == 2) && (dtLG_DIS == dtype) && !head->s.v.waterlevel) { points = 0; } if (points > 0) { if (CanDamage(head, inflictor)) { head->deathtype = dtype; dmg_is_splash = 1; // mark damage as splash if (cvar("k_instagib") || isRACE()) // in instagib splash applied to inflictor only, for coil jump { if (head == attacker) { T_Damage(head, inflictor, attacker, points); } } else { // shamblers only take half damage from rocket/grenade explosions if (streq(head->classname, "monster_shambler") && !cvar("k_bloodfest")) { points = points / 2; } T_Damage(head, inflictor, attacker, points); } dmg_is_splash = 0; // unmark splash } } } } /* ============ T_RadiusDamage ============ */ void T_RadiusDamage(gedict_t *inflictor, gedict_t *attacker, float damage, gedict_t *ignore, deathType_t dtype) { gedict_t *head; if (isRACE()) { attacker->s.v.solid = SOLID_BBOX; T_RadiusDamageApply(inflictor, attacker, attacker, damage, dtype); attacker->s.v.solid = SOLID_NOT; return; } head = trap_findradius(world, inflictor->s.v.origin, damage + 40); while (head) { if (head != ignore) { T_RadiusDamageApply(inflictor, attacker, head, damage, dtype); } head = trap_findradius(head, inflictor->s.v.origin, damage + 40); } } /* ============ T_BeamDamage ============ */ void T_BeamDamage(gedict_t *attacker, float damage) { vec3_t tmpv; float points; gedict_t *head; head = trap_findradius(world, attacker->s.v.origin, damage + 40); while (head) { if (head->s.v.takedamage) { VectorSubtract(attacker->s.v.origin, head->s.v.origin, tmpv) points = 0.5 * vlen(tmpv); if (points < 0) { points = 0; } points = damage - points; if (head == attacker) { points = points * 0.5; } if (points > 0) { if (CanDamage(head, attacker)) { T_Damage(head, attacker, attacker, points); } } } head = trap_findradius(head, attacker->s.v.origin, damage + 40); } } QW-Group-ktx-d05d6ca/src/commands.c000066400000000000000000006667061475442401000172110ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // commands.c #include "g_local.h" #include "stats.h" int max_cmd_len = 0; qbool is_rules_change_allowed(void); void SendMessage(char *name); float CountRPlayers(void); float CountTeams(void); void PlayerFastReady(void); void PlayerSlowReady(void); void PlayerBreak(void); void ReqAdmin(void); void AdminForceStart(void); void AdminForceBreak(void); void AdminForceMap(void); void TogglePreWar(void); void ToggleMapLock(void); void AdminKick(void); void m_kick(void); void YesKick(void); void DontKick(void); void VoteAdmin(void); void VoteYes(void); void VoteNo(void); void VoteCaptain(void); void VoteCoach(void); void nospecs(void); void teamoverlay(void); void votecoop(void); void RandomPickup(void); void ShowDMM(void); void ChangeDM(float dmm); void ChangeLock(void); void ChangeOvertime(void); void ChangeOvertimeUp(void); void ChangeTP(void); void ToggleFallBunny(void); // { CTF void FlagStatus(void); void TossFlag(void); void norunes(void); void nohook(void); void hooksmooth(void); void hookfast(void); void hookclassic(void); void hookcrhook(void); void noga(void); void mctf(void); void CTFBasedSpawn(void); // } CTF void FragsDown(void); void FragsUp(void); void ListWhoNot(void); void ModStatus1(void); void ModStatus2(void); void ModStatusVote(void); void LastStats(void); void PlayerStats(void); void PlayerStatus(void); void PlayerStatusN(void); void PlayerStatusS(void); void PrintScores(void); void ReportMe(void); void SendKillerMsg(void); void SendNewcomerMsg(void); void SendVictimMsg(void); void ShowNick(void); void ShowCmds(void); void ShowMaps(void); //void ShowMessages(void); void ShowOpts(void); void ShowQizmo(void); void ShowRules(void); void ShowVersion(void); void ShowCharsetTableOctal(void); void ShowCharsetTableHexa(void); void killquad(void); void bloodfest(void); void antilag(void); void ToggleDischarge(void); void ToggleDropPack(void); void ToggleDropQuad(void); void ToggleDropRing(void); void ToggleFairPacks(void); void ToggleFreeze(void); void ToggleMidair(void); void SetMidairMinHeight(void); void ToggleFreshTeams(void); void ToggleFreshPacks(void); void ToggleFreshGuns(void); void ToggleFreshTime(void); void ToggleNoSweep(void); void ToggleInstagib(void); void ToggleLGC(void); void ToggleCGKickback(void); void ToggleToT(void); void TogglePowerups(void); void TogglePuPickup(void); void ToggleQEnemy(void); void ToggleQLag(void); void ToggleQPoint(void); /* new FDP bits https://www.quakeworld.nu/wiki/FPD void ToggleSkinForcing(void); void ToggleColorForcing(void); void TogglePitchSpeedLimit(void); void ToggleYawSpeedLimit(void); */ void ToggleRespawns(void); void ToggleSpawnPoints(void); void ToggleBerzerk(void); void ToggleSpecTalk(void); void ToggleSpeed(void); void VotePickup(void); void UserMode(float umode); void Wp_Reset(void); void Wp_Stats(float on); void Sc_Stats(float on); void t_jump(float j_type); void hdptoggle(void); void handicap(void); void noweapon(void); void toggletracklist(void); void tracklist(void); void toggleklist(void); void klist(void); void fpslist(void); void krnd(void); void agree_on_map(void); void favx_add(float fav_num); void xfav_go(float fav_num); void fav_add(void); void fav_del(void); void fav_all_del(void); void fav_next(void); void fav_show(void); void AutoTrack(float autoTrackType); void next_best(void); void next_pow(void); void Pos_Show(void); void Pos_Save(void); void Pos_Move(void); void Pos_Set(float set_type); void Sh_Speed(void); void lastscores(void); void SwapAll(void); void motd_show(void); void TogglePractice(void); // { yawn mode void ToggleYawnMode(void); void setTeleportCap(void); // } void infolock(void); void infospec(void); void moreinfo(void); void s_p_cmd(void); void s_lr_cmd(float l); void s_t_cmd(void); void mmode(void); void multi(void); void cmdinfo(void); void cmduinfo(void); void cmd_wreg(void); void ClientKill(void); void sv_time(void); void GrenadeMode(void); void ToggleReady(void); void fp_toggle(float type); void dlist(void); void dinfo(void); void sv_lock(void); void force_spec(void); void teleteam(void); void upplayers(float type); void downplayers(float type); void iplist(void); void dmgfrags(void); void no_lg(void); void no_gl(void); void mv_cmd_playback(void); void mv_cmd_record(void); void mv_cmd_stop(void); void callalias(void); void fcheck(void); void mapcycle(void); void airstep(void); void ToggleExclusive(void); void ToggleNewCoopNm(void); void ToggleVwep(void); void TogglePause(void); void ToggleArena(void); void Spawn666Time(void); void noitems(void); // spec void ShowCamHelp(void); void TeamSay(float fsndname); void TimeDown(float t); void TimeUp(float t); void TimeSet(float t); void cmdslist_dl(void); void mapslist_dl(void); // { RACE void r_cdel(void); void r_clear_route(void); void r_Xset(float t); void r_changestatus(float t); void r_changefollowstatus(float t); void r_timeout(void); void r_falsestart(void); void r_mode(void); void r_all_break(void); void r_route(void); void r_print(void); void race_display_line(void); void display_scores(void); void display_record_details(void); void race_chasecam_change(void); void race_chasecam_freelook_change(void); void race_download_record_demo(void); void race_pacemaker(void); void race_simultaneous_toggle(void); void race_match_toggle(void); qbool race_match_mode(void); void race_switch_usermode(const char *displayName, int players_per_team); void race_scoring_system_toggle(void); void race_hide_players_toggle(void); // } // { CHEATS void giveme(void); static void dropitem(void); static void removeitem(void); static void dumpent(void); // } // { Frogbots void FrogbotsCommand(void); // } // { Private games void private_game_vote(void); void private_game_toggle(qbool enable); // } void ListGameModes(void); // Save the first 5 demo markers to print at the end. demo_marker_t demo_markers[10]; int demo_markers_count = 10; int demo_marker_index = 0; void ClearDemoMarkers(void) { demo_marker_index = 0; } void DemoMark(void) { stuffcmd(self, "//demomark\n"); if (match_in_progress <= 1) { return; } // Do not add marker if there was already a marker just a few seconds ago. if ((demo_marker_index > 0) && ((g_globalvars.time - demo_markers[demo_marker_index - 1].time) < 5)) { return; } if (demo_marker_index < demo_markers_count) { int total = (int)(g_globalvars.time - match_start_time); demo_markers[demo_marker_index].time = g_globalvars.time; strlcpy(demo_markers[demo_marker_index].markername, getname(self), sizeof(demo_markers[demo_marker_index].markername)); demo_marker_index++; G_sprint(self, 2, "Added demo marker: \220%d:%02d\221\n", (total / 60), (total % 60)); } else { G_sprint(self, 2, "Demo markers full!\n"); } } // CD - commands descriptions const char CD_NODESC[] = "no desc"; #define CD_VOTEMAP "alternative map vote system" #define CD_COMMANDS "show commands list" #define CD_SCORES "print match time/scores" #define CD_STATS "show player stats" #define CD_EFFI "show player efficiencies" #define CD_OPTIONS "match control commands" #define CD_READY "when you feel ready" #define CD_SLOWREADY "like ready, but don't activate the idlebot" #define CD_BREAK "unready / vote matchend" #define CD_STATUS1 "show server settings" #define CD_STATUS2 "more server settings" #define CD_WHO "player teamlist" #define CD_WHOSKIN "player skinlist" #define CD_WHONOT "players not ready" #define CD_LIST "whonot to everyone" #define CD_WHOVOTE "info on received votes" #define CD_SPAWN "toggle spawn modes" #define CD_SPAWNPOINTS "toggle visible spawn points" #define CD_POWERUPS "quad, \230\230\230, ring & suit" #define CD_PUPICKUP "change powerups pickup policy" #define CD_ANTILAG "toggle antilag" #define CD_DISCHARGE "underwater discharges" #define CD_DM "show deathmatch mode" #define CD_DMM1 "set deathmatch mode 1" #define CD_DMM2 "set deathmatch mode 2" #define CD_DMM3 "set deathmatch mode 3" #define CD_DMM4 "set deathmatch mode 4" #define CD_DMM5 "set deathmatch mode 5" #define CD_TP "change teamplay mode" #define CD_TIMEDOWN1 "-1 mins match time" #define CD_TIMEUP1 "+1 mins match time" #define CD_TIMEDOWN "-5 mins match time" #define CD_TIMEUP "+5 mins match time" #define CD_FALLBUNNY "toggle fallbunny" #define CD_FRAGSDOWN "-10 fraglimit" #define CD_FRAGSUP "+10 fraglimit" #define CD_KILLQUAD "kill the quad mode" #define CD_BLOODFEST "blood fest mode (coop/single only)" #define CD_DROPQUAD "drop quad when killed" #define CD_DROPRING "drop ring when killed" #define CD_DROPPACK "drop pack when killed" #define CD_SILENCE "toggle spectator talk" #define CD_REPORT "simple teamplay report" #define CD_RULES "show game rules" #define CD_LOCKMODE "change locking mode" #define CD_MAPS "list custom maps" #define CD_ADMIN "toggle admin-mode" #define CD_FORCESTART "force match to start" #define CD_FORCEBREAK "force match to end" #define CD_FORCEMAP "force change of map" #define CD_PICKUP "vote for pickup game" #define CD_PREWAR "playerfire before game" #define CD_LOCKMAP "(un)lock current map" #define CD_SPEED "toggle sv_maxspeed" #define CD_FAIRPACKS "best/last weapon dropped" #define CD_ABOUT "mod's info" #define CD_CTOCT "Show octal charset table" #define CD_CTHEX "Show hexadecimal charset table" #define CD_SHOWNICK "pointed player's info" #define CD_TIME5 "set timelimit to 5 mins" #define CD_TIME10 "set timelimit to 10 mins" #define CD_TIME15 "set timelimit to 15 mins" #define CD_TIME20 "set timelimit to 20 mins" #define CD_TIME25 "set timelimit to 25 mins" #define CD_TIME30 "set timelimit to 30 mins" #define CD_KSOUND1 (CD_NODESC) // useless command now #define CD_KSOUND2 (CD_NODESC) // useless command now #define CD_KSOUND3 (CD_NODESC) // useless command now #define CD_KSOUND4 (CD_NODESC) // useless command now #define CD_KSOUND5 (CD_NODESC) // useless command now #define CD_KSOUND6 (CD_NODESC) // useless command now #define CD_QIZMO "qizmo related commands" #define CD_MESSAGES "fun message commands" #define CD_KILLER "message to killer" #define CD_VICTIM "message to victim" #define CD_NEWCOMER "message to last player joined" #define CD_QLAG "lag settings" #define CD_QENEMY "enemy vicinity reporting" #define CD_QPOINT "point function" /* new FDP bits https://www.quakeworld.nu/wiki/FPD #define CD_SFORCING "skin forcing" #define CD_CFORCING "color forcing" #define CD_PITCHSP "pitch speed limiting" #define CD_YAWSP "yaw speed limiting" */ #define CD_KICK "toggle kick mode" #define CD_MKICK "multi kick" #define CD_Y "yes kick" #define CD_N "don't kick" #define CD_OVERTIME "toggle overtime mode" #define CD_OVERTIMEUP "change overtime length" #define CD_ELECT "toggle admin election" #define CD_YES "give vote" #define CD_NO "withdraws vote" #define CD_CAPTAIN "toggle captain election" #define CD_COACH "toggle coach election" #define CD_FREEZE "(un)freeze the map" #define CD_RPICKUP "vote random team pickup" #define CD_1ON1 "duel settings" #define CD_1ON1HM "HoonyMode settings" #define CD_2ON2BLITZ "Blitz 2v2" #define CD_4ON4BLITZ "Blitz 4v4" #define CD_2ON2ON2 "2 on 2 on 2 settings" #define CD_3ON3ON3 "3 on 3 on 3 settings" #define CD_4ON4ON4 "4 on 4 on 4 settings" #define CD_XONX "X on X settings" #define CD_HMSTATS "show stats per hoonymode point" #define CD_2ON2 "2 on 2 settings" #define CD_3ON3 "3 on 3 settings" #define CD_4ON4 "4 on 4 settings" #define CD_10ON10 "10 on 10 settings" #define CD_FFA "FFA settings" #define CD_CTF "CTF settings" #define CD_PRACTICE "toggle practice mode" #define CD_WP_RESET "clear weapon stats" #define CD_PLS_WP_STATS "start print weapon stats" #define CD_MNS_WP_STATS (CD_NODESC) // obvious #define CD_TKFJUMP "toggle allow kfjump" #define CD_TKRJUMP "toggle allow krjump" #define CD_KLIST "mod's list of users" #define CD_HDPTOGGLE "toggle allow handicap" #define CD_HANDICAP "toggle handicap level" #define CD_NOWEAPON "toggle allow any weapon" #define CD_CAM "camera help text" #define CD_TRACKLIST "trackers list" #define CD_FPSLIST "fps list" #define CD_FAV1_ADD "add player to slot 1" #define CD_FAV2_ADD "add player to slot 2" #define CD_FAV3_ADD "........etc.........." #define CD_FAV4_ADD (CD_NODESC) // skip #define CD_FAV5_ADD (CD_NODESC) // skip #define CD_FAV6_ADD (CD_NODESC) // skip #define CD_FAV7_ADD (CD_NODESC) // skip #define CD_FAV8_ADD (CD_NODESC) // skip #define CD_FAV9_ADD (CD_NODESC) // skip #define CD_FAV10_ADD (CD_NODESC) // skip #define CD_FAV11_ADD (CD_NODESC) // skip #define CD_FAV12_ADD (CD_NODESC) // skip #define CD_FAV13_ADD (CD_NODESC) // skip #define CD_FAV14_ADD (CD_NODESC) // skip #define CD_FAV15_ADD (CD_NODESC) // skip #define CD_FAV16_ADD (CD_NODESC) // skip #define CD_FAV17_ADD (CD_NODESC) // skip #define CD_FAV18_ADD (CD_NODESC) // skip #define CD_FAV19_ADD "add player to slot 19" #define CD_FAV20_ADD "add player to slot 20" #define CD_1FAV_GO "set pov to slot 1" #define CD_2FAV_GO "set pov to slot 2" #define CD_3FAV_GO ".......etc........" #define CD_4FAV_GO (CD_NODESC) // skip #define CD_5FAV_GO (CD_NODESC) // skip #define CD_6FAV_GO (CD_NODESC) // skip #define CD_7FAV_GO (CD_NODESC) // skip #define CD_8FAV_GO (CD_NODESC) // skip #define CD_9FAV_GO (CD_NODESC) // skip #define CD_10FAV_GO (CD_NODESC) // skip #define CD_11FAV_GO (CD_NODESC) // skip #define CD_12FAV_GO (CD_NODESC) // skip #define CD_13FAV_GO (CD_NODESC) // skip #define CD_14FAV_GO (CD_NODESC) // skip #define CD_15FAV_GO (CD_NODESC) // skip #define CD_16FAV_GO (CD_NODESC) // skip #define CD_17FAV_GO (CD_NODESC) // skip #define CD_18FAV_GO (CD_NODESC) // skip #define CD_19FAV_GO "set pov to slot 19" #define CD_20FAV_GO "set pov to slot 20" #define CD_FAV_ADD "add player to fav list" #define CD_FAV_DEL "remove player from fav list" #define CD_FAV_ALL_DEL "clear fav list" #define CD_FAV_NEXT "set pov to next fav" #define CD_FAV_SHOW "show fav list" #define CD_PLS_SCORES "show match time and score" #define CD_MNS_SCORES (CD_NODESC) // obvious #define CD_AUTOTRACK "auto tracking" #define CD_AUTOTRACKKTX "auto tracking, ktx version" #define CD_AUTO_POW "auto tracking powerups" #define CD_NEXT_BEST "set pov to next best player" #define CD_NEXT_POW "set pov to next powerup" #define CD_LASTSTATS "show endgame stats" #define CD_LASTSCORES "print last games scores" #define CD_RND "select random value" #define CD_AGREE "agree on last map vote" #define CD_POS_SHOW "info about saved position" #define CD_POS_SAVE "save current position" #define CD_POS_MOVE "move to saved position" #define CD_POS_ORIGIN "set position origin" #define CD_POS_ANGLES "set position angles" #define CD_POS_VELOCITY "set position velocity" #define CD_SH_SPEED "toggle use show speed" #define CD_TOSSRUNE "drop rune (CTF)" #define CD_TOSSFLAG "drop flag (CTF)" #define CD_FLAGSTATUS "show flags status (CTF)" #define CD_NOHOOK "toggle hook (CTF)" #define CD_HOOKSMOOTH "switch Hook style settings: Smooth Hook (CTF)" #define CD_HOOKFAST "switch Hook style settings: Fast Hook (CTF)" #define CD_HOOKCLASSIC "switch Hook style settings: Classic Hook (CTF)" #define CD_HOOKCRHOOK "switch Hook style settings: crhook (CTF)" #define CD_NORUNES "toggle runes (CTF)" #define CD_NOGA "toggle green armor on spawn (CTF)" #define CD_MCTF "disable hook+runes (CTF)" #define CD_CTFBASEDSPAWN "spawn players on the base (CTF)" #define CD_MOTD "show motd" #define CD_INFOLOCK "toggle specinfo perms" #define CD_INFOSPEC "toggle spectator infos" #define CD_MOREINFO "receiving more info" #define CD_S_P "direct player say" #define CD_S_L "continue last s-p u done" #define CD_S_R "reply to last s-p u got" #define CD_S_T "say to group of players" #define CD_S_M "multi say" // anyone have better description? #define CD_MMODE "switch message mode" #define CD_MULTI "change/print multi set" #define CD_KINFO "set self params for mod" #define CD_KUINFO "examine someone params" #define CD_WREG "register reliable wpns" #define CD_KILL "invoke suicide" #define CD_MIDAIR "turn midair mode on/off" #define CD_MIDAIR_MINHEIGHT "midair minimum frag height" #define CD_FRESHTEAMS "freshteams dmm1 settings" #define CD_FRESHPACKS "limit ammo in backpacks" #define CD_FRESHGUNS "limit ammo when sweeping weapons" #define CD_FRESHTIME "toggle weapon time in freshteams" #define CD_NOSWEEP "restrict players from sweeping weapons" #define CD_INSTAGIB "instagib settings" #define CD_BERZERK "berzerk settings" #define CD_LGC "lgc mode" #define CD_CG_KB "toggle coilgun kickback in instagib" #define CD_TIME "show server time" #define CD_GREN_MODE "grenades mode" #define CD_TOGGLEREADY "just toggle ready" #define CD_FP "change floodprot level for players" #define CD_FP_SPEC "change floodprot level for specs" #define CD_DLIST "show demo list" #define CD_DINFO "show demo info" #define CD_LOCK "temporary lock server" #define CD_SWAPALL "swap teams for ctf" // { RA #define CD_RA_BREAK "toggle RA line status" #define CD_RA_POS "RA line position" #define CD_ARENA "toggle rocket arena" // } // { Clan Arena #define CD_CARENA "toggle clan arena" #define CD_WIPEOUT "toggle wipeout" // } // { ToT #define CD_TOT "toggle Tribe of Tjernobyl mode" // } #define CD_FORCE_SPEC "force spec players" // { server side bans #define CD_BAN "timed ban by uid/nick" #define CD_BANIP "timed ban by ip" #define CD_BANREM "remove ban / banlist" // } #define CD_TELETEAM "team telefrag behaviour" #define CD_UPPLAYERS "increase maxclients" #define CD_DOWNPLAYERS "decrease maxclients" #define CD_UPSPECS "increase maxspectators" #define CD_DOWNSPECS "decrease maxspectators" #define CD_IPLIST "list clients ips" #define CD_DMGFRAGS "toggle damage frags" #define CD_NO_LG "alias for /noweapon lg" #define CD_NO_GL "alias for /noweapon gl" // { #define CD_TRX_REC "trick tmp record" #define CD_TRX_PLAY "trick tmp playback" #define CD_TRX_STOP "stop playback/recording" // } #define CD_CALLALIAS "call alias after few secs" #define CD_CHECK "better f_checks handle" #define CD_NEXT_MAP "vote for next map" #define CD_MAPCYCLE "list map cycle" #define CD_YAWNMODE "toggle yawnmode" #define CD_FALLBUNNYCAP "set fallbunny cap (yawn)" #define CD_TELEPORTCAP "set teleport cap (yawn)" #define CD_AIRSTEP "toggle airstep" #define CD_EXCLUSIVE "toggle exclusive mode" #define CD_VWEP "toggle vweps" #define CD_PAUSE "toggle pause" // { RACE #define CD_RACE "toggle race mode" #define CD_R_COUNTDOWN_UP "+1 sec race cowntdown time" #define CD_R_COUNTDOWN_DOWN "-1 sec race cowntdown time" #define CD_R_SSET "set race start checkpoint" #define CD_R_CSET "set race checkpoint" #define CD_R_ESET "set race end checkpoint" #define CD_R_CDEL "remove race current checkpoint" #define CD_R_ROUTE "load predefined routes for map" #define CD_C_ROUTE "clear current route completely" #define CD_R_PRINT "show race route info" #define CD_RREADY "ready for race" #define CD_RBREAK "not ready for race" #define CD_RBREAKALL "force all racers to break" #define CD_RTOGGLE "toggle ready status for race" #define CD_RCANCEL "cancel current race, for racer" #define CD_RTIMEOUT "set race timeout" #define CD_RFALSESTART "set race starting mode" #define CD_RMODE "set race weapon mode" #define CD_RFOLLOW "follow racers with chasecam while waiting in line" #define CD_RNOFOLLOW "don't follow racers with chasecam while waiting in line" #define CD_RFTOGGLE "toggle chasecam status" #define CD_RCHASECAM "cycle between chasecam views" #define CD_RCHASECAMFL "toggle chasecam freelook" #define CD_RLINEUP "show current race line-up" #define CD_RSCORES "show top race times for current map" #define CD_RSCOREDETAIL "show details about a record" #define CD_RDLDEMO "download demo for a record" #define CD_RPACEMAKER "set pacemaker" #define CD_RSIMULMODE "toggle simultaneous racing" #define CD_RMATCHMODE "toggle race match mode" #define CD_RSCORINGMODE "toggle between scoring systems" #define CD_RHIDEPLAYERS "toggle visible players during race" // } #define CD_NOSPECS "allow/disallow spectators" #define CD_NOITEMS "allow/disallow items in game" #define CD_TEAMOVERLAY "allow/disallow teamoverlay" #define CD_SPAWN666TIME "set spawn pent time (dmm4 atm)" #define CD_GIVEME (CD_NODESC) // skip #define CD_DROPITEM (CD_NODESC) // skip #define CD_REMOVEITEM (CD_NODESC) // skip #define CD_DUMPENT (CD_NODESC) // skip #define CD_VOTECOOP "vote for coop on/off" #define CD_COOPNMPU "new nightmare mode (pu drops) on/off" #define CD_MAPSLIST_DL (CD_NODESC) // skip #define CD_CMDSLIST_DL (CD_NODESC) // skip #define CD_DEMOMARK "put mark in the demo" #define CD_BOTCOMMAND "bot configuration" #define CD_PRIVATEGAME "private game (logged in users only)" #define CD_TEAMPLAYMESSAGE "teamplay messages" #define CD_PICKSPAWN "nominate hoonymode spawn" #define CD_ROUNDSUP "increase rounds in match" #define CD_ROUNDSDOWN "decrease rounds in match" #define CD_GAMEMODES "list available game modes" void dummy(void) { } void redirect(void); #define DEF(ptr) ((void (*)(void))(ptr)) cmd_t cmds[] = { { "race", ToggleRace, 0, CF_PLAYER | CF_SPC_ADMIN, CD_RACE }, { "race_countdown_up", DEF(RaceCountdownChange), 1, CF_PLAYER | CF_SPC_ADMIN, CD_R_COUNTDOWN_UP}, { "race_countdown_down", DEF(RaceCountdownChange), -1, CF_PLAYER | CF_SPC_ADMIN, CD_R_COUNTDOWN_DOWN}, { "cm", SelectMap, 0, CF_BOTH | CF_MATCHLESS | CF_NOALIAS, CD_NODESC }, { "mapslist_dl", mapslist_dl, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS | CF_NOALIAS | CF_CONNECTION_FLOOD, CD_MAPSLIST_DL }, { "cmdslist_dl", cmdslist_dl, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS | CF_NOALIAS | CF_CONNECTION_FLOOD, CD_CMDSLIST_DL }, { "votemap", VoteMap, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_VOTEMAP }, { "commands", ShowCmds, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_COMMANDS }, { "scores", PrintScores, 0, CF_BOTH | CF_MATCHLESS, CD_SCORES }, { "stats", PlayerStats, 0, CF_BOTH | CF_MATCHLESS, CD_STATS }, { "effi", PlayerStats, 0, CF_BOTH | CF_MATCHLESS, CD_EFFI }, { "options", ShowOpts, 0, CF_PLAYER, CD_OPTIONS }, { "ready", PlayerFastReady, 0, CF_BOTH | CF_MATCHLESS, CD_READY }, { "slowready", PlayerSlowReady, 0, CF_BOTH | CF_MATCHLESS, CD_SLOWREADY }, { "break", PlayerBreak, 0, CF_BOTH | CF_MATCHLESS, CD_BREAK }, { "status1", ModStatus1, 0, CF_BOTH | CF_MATCHLESS, CD_STATUS1 }, { "status2", ModStatus2, 0, CF_BOTH | CF_MATCHLESS, CD_STATUS2 }, { "who", PlayerStatus, 0, CF_BOTH, CD_WHO }, { "whoskin", PlayerStatusS, 0, CF_BOTH | CF_MATCHLESS, CD_WHOSKIN }, { "whonot", PlayerStatusN, 0, CF_BOTH, CD_WHONOT }, { "list", ListWhoNot, 0, CF_PLAYER | CF_SPC_ADMIN, CD_LIST }, { "whovote", ModStatusVote, 0, CF_BOTH | CF_MATCHLESS, CD_WHOVOTE }, { "spawn", ToggleRespawns, 0, CF_PLAYER | CF_SPC_ADMIN, CD_SPAWN }, { "spawn_show", ToggleSpawnPoints, 0, CF_PLAYER | CF_SPC_ADMIN, CD_SPAWNPOINTS }, { "powerups", TogglePowerups, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_POWERUPS }, { "powerups_pickup", TogglePuPickup, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_PUPICKUP }, { "antilag", antilag, 0, CF_PLAYER | CF_SPC_ADMIN, CD_ANTILAG }, { "discharge", ToggleDischarge, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DISCHARGE }, { "dm", ShowDMM, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DM }, { "dmm1", DEF(ChangeDM), 1, CF_PLAYER | CF_SPC_ADMIN, CD_DMM1 }, { "dmm2", DEF(ChangeDM), 2, CF_PLAYER | CF_SPC_ADMIN, CD_DMM2 }, { "dmm3", DEF(ChangeDM), 3, CF_PLAYER | CF_SPC_ADMIN, CD_DMM3 }, { "dmm4", DEF(ChangeDM), 4, CF_PLAYER | CF_SPC_ADMIN, CD_DMM4 }, { "dmm5", DEF(ChangeDM), 5, CF_PLAYER | CF_SPC_ADMIN, CD_DMM5 }, { "tp", ChangeTP, 0, CF_PLAYER | CF_SPC_ADMIN, CD_TP }, { "timedown1", DEF(TimeDown), 1.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIMEDOWN1 }, { "timeup1", DEF(TimeUp), 1.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIMEUP1 }, { "timedown", DEF(TimeDown), 5.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIMEDOWN }, { "timeup", DEF(TimeUp), 5.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIMEUP }, { "fallbunny", ToggleFallBunny, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FALLBUNNY }, { "fragsdown", FragsDown, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRAGSDOWN }, { "fragsup", FragsUp, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRAGSUP }, { "killquad", killquad, 0, CF_PLAYER | CF_SPC_ADMIN, CD_KILLQUAD }, // qqshka: Pointless to have it, XonX command will turn it off anyway. // { "bloodfest", bloodfest, 0, CF_PLAYER | CF_SPC_ADMIN, CD_BLOODFEST }, { "dropquad", ToggleDropQuad, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DROPQUAD }, { "dropring", ToggleDropRing, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DROPRING }, { "droppack", ToggleDropPack, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DROPPACK }, { "silence", ToggleSpecTalk, 0, CF_PLAYER | CF_SPC_ADMIN, CD_SILENCE }, { "report", ReportMe, 0, CF_PLAYER, CD_REPORT }, { "rules", ShowRules, 0, CF_PLAYER | CF_MATCHLESS, CD_RULES }, { "lockmode", ChangeLock, 0, CF_PLAYER | CF_SPC_ADMIN, CD_LOCKMODE }, { "maps", ShowMaps, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_MAPS }, { "admin", ReqAdmin, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_ADMIN }, { "forcestart", AdminForceStart, 0, CF_BOTH_ADMIN, CD_FORCESTART }, { "forcebreak", AdminForceBreak, 0, CF_BOTH_ADMIN, CD_FORCEBREAK }, { "forcemap", AdminForceMap, 0, CF_BOTH_ADMIN | CF_PARAMS, CD_FORCEMAP }, { "pickup", VotePickup, 0, CF_PLAYER, CD_PICKUP }, { "prewar", TogglePreWar, 0, CF_BOTH_ADMIN, CD_PREWAR }, { "lockmap", ToggleMapLock, 0, CF_BOTH_ADMIN, CD_LOCKMAP }, { "speed", ToggleSpeed, 0, CF_PLAYER, CD_SPEED }, { "fairpacks", ToggleFairPacks, 0, CF_PLAYER, CD_FAIRPACKS }, { "sct_oct", ShowCharsetTableOctal, 0, CF_BOTH, CD_CTOCT }, { "sct_hex", ShowCharsetTableHexa, 0, CF_BOTH, CD_CTHEX }, { "about", ShowVersion, 0, CF_BOTH | CF_MATCHLESS, CD_ABOUT }, { "shownick", ShowNick, 0, CF_PLAYER | CF_PARAMS, CD_SHOWNICK }, { "time5", DEF(TimeSet), 5.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME5 }, { "time10", DEF(TimeSet), 10.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME10 }, { "time15", DEF(TimeSet), 15.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME15 }, { "time20", DEF(TimeSet), 20.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME20 }, { "time25", DEF(TimeSet), 25.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME25 }, { "time30", DEF(TimeSet), 30.0f, CF_PLAYER | CF_SPC_ADMIN, CD_TIME30 }, { "ksound1", DEF(TeamSay), 1, CF_PLAYER, CD_KSOUND1 }, { "ksound2", DEF(TeamSay), 2, CF_PLAYER, CD_KSOUND2 }, { "ksound3", DEF(TeamSay), 3, CF_PLAYER, CD_KSOUND3 }, { "ksound4", DEF(TeamSay), 4, CF_PLAYER, CD_KSOUND4 }, { "ksound5", DEF(TeamSay), 5, CF_PLAYER, CD_KSOUND5 }, { "ksound6", DEF(TeamSay), 6, CF_PLAYER, CD_KSOUND6 }, { "qizmo", ShowQizmo, 0, CF_PLAYER, CD_QIZMO }, // { "messages", ShowMessages, 0, CF_PLAYER | CF_MATCHLESS, CD_MESSAGES }, { "killer", SendKillerMsg, 0, CF_PLAYER | CF_MATCHLESS, CD_KILLER }, { "victim", SendVictimMsg, 0, CF_PLAYER | CF_MATCHLESS, CD_VICTIM }, { "newcomer", SendNewcomerMsg, 0, CF_BOTH | CF_MATCHLESS, CD_NEWCOMER }, { "qlag", ToggleQLag, 0, CF_PLAYER | CF_SPC_ADMIN, CD_QLAG }, { "qenemy", ToggleQEnemy, 0, CF_PLAYER | CF_SPC_ADMIN, CD_QENEMY }, { "qpoint", ToggleQPoint, 0, CF_PLAYER | CF_SPC_ADMIN, CD_QPOINT }, /* new FDP bits https://www.quakeworld.nu/wiki/FPD { "skinforce", ToggleSkinForcing, 0, CF_PLAYER | CF_SPC_ADMIN, CD_SFORCING }, { "colorforce", ToggleColorForcing, 0, CF_PLAYER | CF_SPC_ADMIN, CD_CFORCING }, { "pitchsl", TogglePitchSpeedLimit, 0, CF_PLAYER | CF_SPC_ADMIN, CD_PITCHSP }, { "yawsl", ToggleYawSpeedLimit, 0, CF_PLAYER | CF_SPC_ADMIN, CD_YAWSP }, */ { "kick", AdminKick, 0, CF_BOTH_ADMIN/* FIXME: interference with ezq server kick command | CF_PARAMS */, CD_KICK }, { "mkick", m_kick, 0, CF_BOTH_ADMIN | CF_PARAMS, CD_MKICK }, { "y", YesKick, 0, CF_BOTH_ADMIN, CD_Y }, { "n", DontKick, 0, CF_BOTH_ADMIN, CD_N }, { "overtime", ChangeOvertime, 0, CF_PLAYER | CF_SPC_ADMIN, CD_OVERTIME }, { "overtimeup", ChangeOvertimeUp, 0, CF_PLAYER | CF_SPC_ADMIN, CD_OVERTIMEUP }, { "elect", VoteAdmin, 0, CF_BOTH | CF_MATCHLESS, CD_ELECT }, { "yes", VoteYes, 0, CF_PLAYER | CF_MATCHLESS, CD_YES }, { "no", VoteNo, 0, CF_PLAYER | CF_MATCHLESS, CD_NO }, { "captain", VoteCaptain, 0, CF_PLAYER, CD_CAPTAIN }, { "coach", VoteCoach, 0, CF_SPECTATOR, CD_COACH }, { "freeze", ToggleFreeze, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FREEZE }, { "rpickup", RandomPickup, 0, CF_PLAYER | CF_SPC_ADMIN, CD_RPICKUP }, { "1on1", DEF(UserMode), 1, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_1ON1 }, { "2on2", DEF(UserMode), 2, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_2ON2 }, { "3on3", DEF(UserMode), 3, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_3ON3 }, { "4on4", DEF(UserMode), 4, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_4ON4 }, { "10on10", DEF(UserMode), 5, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_10ON10 }, { "ffa", DEF(UserMode), 6, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_FFA }, { "ctf", DEF(UserMode), 7, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_CTF }, { "hoonymode", DEF(UserMode), 8, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_1ON1HM }, { "blitz2v2", DEF(UserMode), 9, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_2ON2BLITZ }, { "blitz4v4", DEF(UserMode), 10, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_4ON4BLITZ }, { "2on2on2", DEF(UserMode), 11, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_2ON2ON2 }, { "3on3on3", DEF(UserMode), 12, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_3ON3ON3 }, { "4on4on4", DEF(UserMode), 13, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_4ON4ON4 }, { "XonX", DEF(UserMode), 14, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_XONX }, { "wipeout", DEF(UserMode), 15, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_WIPEOUT }, { "carena", DEF(UserMode), 16, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_CARENA }, { "tot", DEF(UserMode), 17, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_TOT }, { "practice", TogglePractice, 0, CF_PLAYER | CF_SPC_ADMIN, CD_PRACTICE }, { "wp_reset", Wp_Reset, 0, CF_PLAYER, CD_WP_RESET }, { "+wp_stats", DEF(Wp_Stats), 2, CF_BOTH | CF_MATCHLESS, CD_PLS_WP_STATS }, { "-wp_stats", DEF(Wp_Stats), 1, CF_BOTH | CF_MATCHLESS, CD_MNS_WP_STATS }, { "tkfjump", DEF(t_jump), 1, CF_BOTH_ADMIN, CD_TKFJUMP }, { "tkrjump", DEF(t_jump), 2, CF_BOTH_ADMIN, CD_TKRJUMP }, { "klist", klist, 0, CF_BOTH | CF_MATCHLESS, CD_KLIST }, { "toggleklist", toggleklist, 0, CF_BOTH | CF_MATCHLESS, CD_TRACKLIST }, { "hdptoggle", hdptoggle, 0, CF_BOTH_ADMIN, CD_HDPTOGGLE }, { "handicap", handicap, 0, CF_PLAYER | CF_PARAMS | CF_MATCHLESS, CD_HANDICAP }, { "noweapon", noweapon, 0, CF_PLAYER | CF_PARAMS | CF_SPC_ADMIN, CD_NOWEAPON }, { "cam", ShowCamHelp, 0, CF_SPECTATOR | CF_MATCHLESS, CD_CAM }, { "tracklist", tracklist, 0, CF_BOTH | CF_MATCHLESS, CD_TRACKLIST }, { "toggletracklist", toggletracklist, 0, CF_BOTH | CF_MATCHLESS, CD_TRACKLIST }, { "fpslist", fpslist, 0, CF_BOTH | CF_MATCHLESS, CD_FPSLIST }, { "fav1_add", DEF(favx_add), 1, CF_SPECTATOR, CD_FAV1_ADD }, { "fav2_add", DEF(favx_add), 2, CF_SPECTATOR, CD_FAV2_ADD }, { "fav3_add", DEF(favx_add), 3, CF_SPECTATOR, CD_FAV3_ADD }, { "fav4_add", DEF(favx_add), 4, CF_SPECTATOR, CD_FAV4_ADD }, { "fav5_add", DEF(favx_add), 5, CF_SPECTATOR, CD_FAV5_ADD }, { "fav6_add", DEF(favx_add), 6, CF_SPECTATOR, CD_FAV6_ADD }, { "fav7_add", DEF(favx_add), 7, CF_SPECTATOR, CD_FAV7_ADD }, { "fav8_add", DEF(favx_add), 8, CF_SPECTATOR, CD_FAV8_ADD }, { "fav9_add", DEF(favx_add), 9, CF_SPECTATOR, CD_FAV9_ADD }, { "fav10_add", DEF(favx_add), 10, CF_SPECTATOR, CD_FAV10_ADD }, { "fav11_add", DEF(favx_add), 11, CF_SPECTATOR, CD_FAV11_ADD }, { "fav12_add", DEF(favx_add), 12, CF_SPECTATOR, CD_FAV12_ADD }, { "fav13_add", DEF(favx_add), 13, CF_SPECTATOR, CD_FAV13_ADD }, { "fav14_add", DEF(favx_add), 14, CF_SPECTATOR, CD_FAV14_ADD }, { "fav15_add", DEF(favx_add), 15, CF_SPECTATOR, CD_FAV15_ADD }, { "fav16_add", DEF(favx_add), 16, CF_SPECTATOR, CD_FAV16_ADD }, { "fav17_add", DEF(favx_add), 17, CF_SPECTATOR, CD_FAV17_ADD }, { "fav18_add", DEF(favx_add), 18, CF_SPECTATOR, CD_FAV18_ADD }, { "fav19_add", DEF(favx_add), 19, CF_SPECTATOR, CD_FAV19_ADD }, { "fav20_add", DEF(favx_add), 20, CF_SPECTATOR, CD_FAV20_ADD }, { "1fav_go", DEF(xfav_go), 1, CF_SPECTATOR, CD_1FAV_GO }, { "2fav_go", DEF(xfav_go), 2, CF_SPECTATOR, CD_2FAV_GO }, { "3fav_go", DEF(xfav_go), 3, CF_SPECTATOR, CD_3FAV_GO }, { "4fav_go", DEF(xfav_go), 4, CF_SPECTATOR, CD_4FAV_GO }, { "5fav_go", DEF(xfav_go), 5, CF_SPECTATOR, CD_5FAV_GO }, { "6fav_go", DEF(xfav_go), 6, CF_SPECTATOR, CD_6FAV_GO }, { "7fav_go", DEF(xfav_go), 7, CF_SPECTATOR, CD_7FAV_GO }, { "8fav_go", DEF(xfav_go), 8, CF_SPECTATOR, CD_8FAV_GO }, { "9fav_go", DEF(xfav_go), 9, CF_SPECTATOR, CD_9FAV_GO }, { "10fav_go", DEF(xfav_go), 10, CF_SPECTATOR, CD_10FAV_GO }, { "11fav_go", DEF(xfav_go), 11, CF_SPECTATOR, CD_11FAV_GO }, { "12fav_go", DEF(xfav_go), 12, CF_SPECTATOR, CD_12FAV_GO }, { "13fav_go", DEF(xfav_go), 13, CF_SPECTATOR, CD_13FAV_GO }, { "14fav_go", DEF(xfav_go), 14, CF_SPECTATOR, CD_14FAV_GO }, { "15fav_go", DEF(xfav_go), 15, CF_SPECTATOR, CD_15FAV_GO }, { "16fav_go", DEF(xfav_go), 16, CF_SPECTATOR, CD_16FAV_GO }, { "17fav_go", DEF(xfav_go), 17, CF_SPECTATOR, CD_17FAV_GO }, { "18fav_go", DEF(xfav_go), 18, CF_SPECTATOR, CD_18FAV_GO }, { "19fav_go", DEF(xfav_go), 19, CF_SPECTATOR, CD_19FAV_GO }, { "20fav_go", DEF(xfav_go), 20, CF_SPECTATOR, CD_20FAV_GO }, { "fav_add", fav_add, 0, CF_SPECTATOR | CF_MATCHLESS, CD_FAV_ADD }, { "fav_del", fav_del, 0, CF_SPECTATOR | CF_MATCHLESS, CD_FAV_DEL }, { "fav_all_del", fav_all_del, 0, CF_SPECTATOR | CF_MATCHLESS, CD_FAV_ALL_DEL }, { "fav_next", fav_next, 0, CF_SPECTATOR | CF_MATCHLESS, CD_FAV_NEXT }, { "fav_show", fav_show, 0, CF_SPECTATOR | CF_MATCHLESS, CD_FAV_SHOW }, { "+scores", DEF(Sc_Stats), 2, CF_BOTH | CF_MATCHLESS, CD_PLS_SCORES }, { "-scores", DEF(Sc_Stats), 1, CF_BOTH | CF_MATCHLESS, CD_MNS_SCORES }, { "autotrack", DEF(AutoTrack), atKTPRO, CF_SPECTATOR | CF_MATCHLESS, CD_AUTOTRACK }, { "autotrackktx", DEF(AutoTrack), atBest, CF_SPECTATOR | CF_MATCHLESS, CD_AUTOTRACKKTX }, { "auto_pow", DEF(AutoTrack), atPow, CF_SPECTATOR | CF_MATCHLESS, CD_AUTO_POW }, { "next_best", next_best, 0, CF_SPECTATOR | CF_MATCHLESS, CD_NEXT_BEST }, { "next_pow", next_pow, 0, CF_SPECTATOR | CF_MATCHLESS, CD_NEXT_POW }, { "laststats", LastStats, 0, CF_BOTH | CF_MATCHLESS, CD_LASTSTATS }, { "lastscores", lastscores, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_LASTSCORES }, { "lastscoresktx", lastscores, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_LASTSCORES }, { "rnd", krnd, 0, CF_BOTH | CF_PARAMS, CD_RND }, { "agree", agree_on_map, 0, CF_PLAYER | CF_MATCHLESS, CD_AGREE }, { "pos_show", Pos_Show, 0, CF_BOTH | CF_PARAMS, CD_POS_SHOW }, { "pos_save", Pos_Save, 0, CF_BOTH | CF_PARAMS, CD_POS_SAVE }, { "pos_move", Pos_Move, 0, CF_BOTH | CF_PARAMS, CD_POS_MOVE }, // VVD: For trick chiters! :-) // Need to think out how to limit using Pos_Set for tricking. // May be to ban pos_velocity? { "pos_origin", DEF(Pos_Set), 1, CF_BOTH | CF_PARAMS, CD_POS_ORIGIN }, { "pos_angles", DEF(Pos_Set), 2, CF_BOTH | CF_PARAMS, CD_POS_ANGLES }, // { "pos_velocity", DEF(Pos_Set), 3, CF_BOTH | CF_PARAMS, CD_POS_VELOCITY }, { "sh_speed", Sh_Speed, 0, CF_BOTH, CD_SH_SPEED }, // { CTF commands { "tossrune", TossRune, 0, CF_PLAYER | CF_MATCHLESS, CD_TOSSRUNE }, { "tossflag", TossFlag, 0, CF_PLAYER | CF_MATCHLESS, CD_TOSSFLAG }, { "nohook", nohook, 0, CF_PLAYER | CF_MATCHLESS, CD_NOHOOK }, { "hook_smooth", hooksmooth, 0, CF_PLAYER | CF_MATCHLESS, CD_HOOKSMOOTH }, { "hook_fast", hookfast, 0, CF_PLAYER | CF_MATCHLESS, CD_HOOKFAST }, { "hook_classic", hookclassic, 0, CF_PLAYER | CF_MATCHLESS, CD_HOOKCLASSIC }, { "hook_crhook", hookcrhook, 0, CF_PLAYER | CF_MATCHLESS, CD_HOOKCRHOOK }, { "norunes", norunes, 0, CF_PLAYER | CF_MATCHLESS, CD_NORUNES }, { "noga", noga, 0, CF_BOTH_ADMIN | CF_MATCHLESS, CD_NOGA }, { "mctf", mctf, 0, CF_BOTH_ADMIN | CF_MATCHLESS, CD_MCTF }, { "flagstatus", FlagStatus, 0, CF_BOTH | CF_MATCHLESS, CD_FLAGSTATUS }, { "swapall", SwapAll, 0, CF_PLAYER | CF_SPC_ADMIN, CD_SWAPALL }, { "ctfbasedspawn", CTFBasedSpawn, 0, CF_PLAYER | CF_SPC_ADMIN | CF_MATCHLESS, CD_CTFBASEDSPAWN }, // } { "motd", motd_show, 0, CF_BOTH | CF_MATCHLESS, CD_MOTD }, { "infolock", infolock, 0, CF_BOTH_ADMIN, CD_INFOLOCK }, { "infospec", infospec, 0, CF_PLAYER | CF_SPC_ADMIN, CD_INFOSPEC }, { "moreinfo", moreinfo, 0, CF_SPECTATOR | CF_MATCHLESS, CD_MOREINFO }, { "s-p", dummy, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_S_P }, { "s-l", dummy, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_S_L }, { "s-r", dummy, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_S_R }, { "s-t", dummy, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_S_T }, { "s-m", dummy, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_S_M }, { "mmode", mmode, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_MMODE }, { "multi", multi, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_MULTI }, { "kinfo", cmdinfo, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_KINFO }, { "kuinfo", cmduinfo, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_KUINFO }, // { saved for ktpro compatibility { "info", cmdinfo, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS | CF_NOALIAS, CD_NODESC }, { "uinfo", cmduinfo, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS | CF_NOALIAS, CD_NODESC }, // } { "wreg", cmd_wreg, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_WREG }, { "kill", ClientKill, 0, CF_PLAYER | CF_MATCHLESS, CD_KILL }, { "midair", ToggleMidair, 0, CF_PLAYER | CF_SPC_ADMIN, CD_MIDAIR }, { "midair_minheight", SetMidairMinHeight, 0, CF_PLAYER | CF_SPC_ADMIN, CD_MIDAIR_MINHEIGHT }, { "fresh", ToggleFreshTeams, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRESHTEAMS }, { "freshpacks", ToggleFreshPacks, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRESHPACKS }, { "freshguns", ToggleFreshGuns, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRESHGUNS }, { "freshtime", ToggleFreshTime, 0, CF_PLAYER | CF_SPC_ADMIN, CD_FRESHTIME }, { "nosweep", ToggleNoSweep, 0, CF_PLAYER | CF_SPC_ADMIN, CD_NOSWEEP }, { "instagib", ToggleInstagib, 0, CF_PLAYER | CF_SPC_ADMIN, CD_INSTAGIB }, { "berzerk", ToggleBerzerk, 0, CF_PLAYER | CF_SPC_ADMIN, CD_BERZERK }, { "lgcmode", ToggleLGC, 0, CF_PLAYER | CF_SPC_ADMIN, CD_LGC }, { "totmode", ToggleToT, 0, CF_PLAYER | CF_SPC_ADMIN, CD_TOT }, { "instagib_coilgun_kickback", ToggleCGKickback, 0, CF_PLAYER | CF_SPC_ADMIN, CD_CG_KB }, { "time", sv_time, 0, CF_BOTH | CF_MATCHLESS, CD_TIME }, { "gren_mode", GrenadeMode, 0, CF_PLAYER | CF_SPC_ADMIN, CD_GREN_MODE }, { "toggleready", ToggleReady, 0, CF_BOTH | CF_MATCHLESS, CD_TOGGLEREADY }, { "fp", DEF(fp_toggle), 1, CF_BOTH_ADMIN, CD_FP }, { "fp_spec", DEF(fp_toggle), 2, CF_BOTH_ADMIN, CD_FP_SPEC }, { "dlist", dlist, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_DLIST }, { "dinfo", dinfo, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_DINFO }, { "lock", sv_lock, 0, CF_BOTH_ADMIN, CD_LOCK }, // { RA { "ra_break", ra_break, 0, CF_PLAYER, CD_RA_BREAK }, { "ra_pos", ra_PrintPos, 0, CF_PLAYER, CD_RA_POS }, { "arena", ToggleArena, 0, CF_PLAYER | CF_SPC_ADMIN, CD_ARENA }, // } { "force_spec", force_spec, 0, CF_BOTH_ADMIN | CF_PARAMS, CD_FORCE_SPEC }, // { bans { "ban", redirect, 0, CF_BOTH_ADMIN | CF_MATCHLESS | CF_PARAMS | CF_REDIRECT, CD_BAN }, { "banip", redirect, 0, CF_BOTH_ADMIN | CF_MATCHLESS | CF_PARAMS | CF_REDIRECT, CD_BANIP }, { "banrem", redirect, 0, CF_BOTH_ADMIN | CF_MATCHLESS | CF_PARAMS | CF_REDIRECT, CD_BANREM }, // } { "teleteam", teleteam, 0, CF_PLAYER | CF_SPC_ADMIN, CD_TELETEAM }, { "upplayers", DEF(upplayers), 1, CF_PLAYER | CF_SPC_ADMIN, CD_UPPLAYERS }, { "downplayers", DEF(downplayers), 1, CF_PLAYER | CF_SPC_ADMIN, CD_DOWNPLAYERS }, { "upspecs", DEF(upplayers), 2, CF_PLAYER | CF_SPC_ADMIN, CD_UPSPECS }, { "downspecs", DEF(downplayers), 2, CF_PLAYER | CF_SPC_ADMIN, CD_DOWNSPECS }, { "iplist", iplist, 0, CF_BOTH, CD_IPLIST }, { "dmgfrags", dmgfrags, 0, CF_PLAYER | CF_SPC_ADMIN, CD_DMGFRAGS }, { "no_lg", no_lg, 0, CF_PLAYER | CF_SPC_ADMIN, CD_NO_LG }, { "no_gl", no_gl, 0, CF_PLAYER | CF_SPC_ADMIN, CD_NO_GL }, // { { "trx_rec", mv_cmd_record, 0, CF_PLAYER, CD_TRX_REC }, { "trx_play", mv_cmd_playback, 0, CF_PLAYER, CD_TRX_PLAY }, { "trx_stop", mv_cmd_stop, 0, CF_PLAYER, CD_TRX_STOP }, // } { "callalias", callalias, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_CALLALIAS }, { "check", fcheck, 0, CF_BOTH | CF_PARAMS, CD_CHECK }, { "next_map", PlayerBreak, 0, CF_PLAYER | CF_MATCHLESS_ONLY, CD_NEXT_MAP }, { "mapcycle", mapcycle, 0, CF_BOTH | CF_MATCHLESS, CD_MAPCYCLE }, { "yawnmode", ToggleYawnMode, 0, CF_PLAYER | CF_SPC_ADMIN, CD_YAWNMODE }, { "teleportcap", setTeleportCap, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_TELEPORTCAP }, { "airstep", airstep, 0, CF_PLAYER | CF_SPC_ADMIN, CD_AIRSTEP }, { "exclusive", ToggleExclusive, 0, CF_BOTH_ADMIN, CD_EXCLUSIVE }, { "vwep", ToggleVwep, 0, CF_PLAYER | CF_SPC_ADMIN, CD_VWEP }, { "pause", TogglePause, 0, CF_PLAYER | CF_MATCHLESS | CF_SPC_ADMIN, CD_PAUSE }, // { RACE { "race_ready", DEF(r_changestatus), 1, CF_PLAYER, CD_RREADY }, { "race_break", DEF(r_changestatus), 2, CF_PLAYER, CD_RBREAK }, { "race_break_all", r_all_break, 0, CF_BOTH_ADMIN, CD_RBREAKALL }, { "race_toggle", DEF(r_changestatus), 3, CF_PLAYER, CD_RTOGGLE }, { "race_cancel", DEF(r_changestatus), 4, CF_PLAYER, CD_RCANCEL }, { "race_show_lineup", race_display_line, 0, CF_BOTH, CD_RLINEUP }, { "race_show_toptimes", display_scores, 0, CF_BOTH, CD_RSCORES }, { "race_show_record_details", display_record_details, 0, CF_BOTH | CF_PARAMS, CD_RSCOREDETAIL }, { "race_show_route", r_print, 0, CF_BOTH, CD_R_PRINT }, { "race_set_start", DEF(r_Xset), 1, CF_PLAYER | CF_SPC_ADMIN, CD_R_SSET }, { "race_set_finish", DEF(r_Xset), 3, CF_PLAYER | CF_SPC_ADMIN, CD_R_ESET }, { "race_set_checkpoint", DEF(r_Xset), 2, CF_PLAYER | CF_SPC_ADMIN, CD_R_CSET }, { "race_del_checkpoint", r_cdel, 0, CF_PLAYER | CF_SPC_ADMIN, CD_R_CDEL }, { "race_set_timeout", r_timeout, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_RTIMEOUT }, { "race_set_falsestart", r_falsestart, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_RFALSESTART }, { "race_set_weapon_mode", r_mode, 0, CF_PLAYER | CF_SPC_ADMIN, CD_RMODE }, { "race_route_switch", r_route, 0, CF_PLAYER | CF_SPC_ADMIN, CD_R_ROUTE }, { "race_route_clear", r_clear_route, 0, CF_PLAYER | CF_SPC_ADMIN, CD_C_ROUTE }, { "race_chasecam", DEF(r_changefollowstatus), 3, CF_PLAYER, CD_RFTOGGLE }, { "race_chasecam_view", race_chasecam_change, 0, CF_PLAYER, CD_RCHASECAM }, { "race_chasecam_freelook", race_chasecam_freelook_change, 0, CF_PLAYER, CD_RCHASECAMFL }, { "race_dl_record_demo", race_download_record_demo, 0, CF_BOTH | CF_PARAMS, CD_RDLDEMO }, { "race_pacemaker", race_pacemaker, 0, CF_PLAYER | CF_PARAMS, CD_RPACEMAKER }, { "race_simultaneous", race_simultaneous_toggle, 0, CF_PLAYER, CD_RSIMULMODE }, { "race_match", race_match_toggle, 0, CF_PLAYER, CD_RMATCHMODE }, { "race_scoring", race_scoring_system_toggle, 0, CF_PLAYER, CD_RSCORINGMODE }, { "race_hide_players", race_hide_players_toggle, 0, CF_PLAYER, CD_RHIDEPLAYERS }, // } { "nospecs", nospecs, 0, CF_PLAYER | CF_SPC_ADMIN, CD_NOSPECS }, { "noitems", noitems, 0, CF_PLAYER | CF_SPC_ADMIN, CD_NOITEMS }, { "teamoverlay", teamoverlay, 0, CF_PLAYER | CF_SPC_ADMIN, CD_TEAMOVERLAY }, { "spawn666time", Spawn666Time, 0, CF_PLAYER | CF_SPC_ADMIN | CF_PARAMS, CD_SPAWN666TIME }, { "giveme", giveme, 0, CF_PLAYER | CF_MATCHLESS | CF_PARAMS, CD_GIVEME }, { "dropitem", dropitem, 0, CF_BOTH | CF_PARAMS, CD_DROPITEM }, { "removeitem", removeitem, 0, CF_BOTH | CF_PARAMS, CD_REMOVEITEM }, { "dumpent", dumpent, 0, CF_BOTH | CF_PARAMS, CD_DUMPENT }, { "votecoop", votecoop, 0, CF_PLAYER | CF_MATCHLESS, CD_VOTECOOP }, { "coop_nm_pu", ToggleNewCoopNm, 0, CF_PLAYER | CF_MATCHLESS, CD_COOPNMPU }, { "demomark", DemoMark, 0, CF_BOTH, CD_DEMOMARK }, #ifdef BOT_SUPPORT // { FROGBOTS { "botcmd", FrogbotsCommand, 0, CF_BOTH | CF_MATCHLESS | CF_PARAMS, CD_BOTCOMMAND }, // } #endif // { TEAMPLAY { "tpmsg", TeamplayMessage, 0, CF_PLAYER | CF_PARAMS | CF_MATCHLESS, CD_TEAMPLAYMESSAGE }, // { HOONYMODE { "pickspawn", HM_pick_spawn, 0, CF_PLAYER, CD_PICKSPAWN }, { "roundsup", HM_roundsup, 0, CF_PLAYER, CD_ROUNDSUP }, { "roundsdown", HM_roundsdown, 0, CF_PLAYER, CD_ROUNDSDOWN }, // } { "voteprivate", private_game_vote, 0, CF_PLAYER, CD_PRIVATEGAME }, { "gamemodes", ListGameModes, 0, CF_BOTH, CD_GAMEMODES }, }; #undef DEF int cmds_cnt = sizeof(cmds) / sizeof(cmds[0]); int DoCommand(int icmd) { int spc = self->ct == ctSpec; if (!((icmd >= 0) && (icmd < cmds_cnt))) { return DO_OUT_OF_RANGE_CMDS; } if (k_matchLess && !(cmds[icmd].cf_flags & CF_MATCHLESS)) { return DO_CMD_DISALLOWED_MATCHLESS; // cmd isn't allowed in matchLess mode } if (!k_matchLess && (cmds[icmd].cf_flags & CF_MATCHLESS_ONLY)) { return DO_CMD_MATCHLESS_ONLY; // cmd allowed in matchLess mode _only_ } if (spc) { // spec if (!(cmds[icmd].cf_flags & CF_SPECTATOR)) { return DO_WRONG_CLASS; // cmd not for spectator } if ((cmds[icmd].cf_flags & CF_SPC_ADMIN) && !is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return DO_ACCESS_DENIED; // admin rights required } } else { // player if (!(cmds[icmd].cf_flags & CF_PLAYER)) { return DO_WRONG_CLASS; // cmd not for player } if ((cmds[icmd].cf_flags & CF_PLR_ADMIN) && !is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return DO_ACCESS_DENIED; // admin rights required } } if (strnull(cmds[icmd].name) || !(cmds[icmd].f)) { return DO_FUNCTION_IS_WRONG; } if ((cmds[icmd].cf_flags & CF_CONNECTION_FLOOD) && ((self->connect_time + 30) > g_globalvars.time)) { ; // ignore flood check for first 30 seconds after connect, for commands marked with CF_CONNECTION_FLOOD flag } else if (isCmdFlood(self)) { return DO_FLOOD_PROTECT; } if (cmds[icmd].arg) { ((void (*)(float))(cmds[icmd].f))(cmds[icmd].arg); } else { (cmds[icmd].f)(); } return icmd; } // VVD: Need for executing commands by 'cmd ... ', // because ' ... ' work only with last ezQuake qw client. int DoCommand_Name(char *cmd_name) { int i; if (strnull(cmd_name)) { return DO_OUT_OF_RANGE_CMDS; } for (i = 0; i < cmds_cnt; ++i) { if (streq(cmds[i].name, cmd_name)) { if (cmds[i].cf_flags & CF_REDIRECT) { return DO_OUT_OF_RANGE_CMDS; // imitate we does't found command in redirect case } return DoCommand(i); } } return DO_OUT_OF_RANGE_CMDS; } qbool isCmdFlood(gedict_t *p) { int idx; float cmd_time; if (k_cmd_fp_disabled || ((p->connect_time + 5) > g_globalvars.time)) { return false; // cmd flood protect is disabled or skip near connect time due to tons of "cmd info" commands is done } if (cvar("sv_paused")) // FIXME: g_globalvars.time does not increase when paused, so if you { return false; // triggered floodprot you wouldn't be able to unpause } idx = bound(0, p->fp_c.last_cmd, MAX_FP_CMDS - 1); cmd_time = p->fp_c.cmd_time[idx]; if (g_globalvars.time < p->fp_c.locked) { G_sprint(p, 2, "command floodprot (%d sec)\n", (int)(p->fp_c.locked - g_globalvars.time + 1)); return true; // flooder } if (cmd_time && (g_globalvars.time - cmd_time < k_cmd_fp_per)) { G_sprint(p, 2, "You are a command flooder man!\n"); p->fp_c.locked = g_globalvars.time + k_cmd_fp_for; if (!k_cmd_fp_dontkick) { if ((k_cmd_fp_kick - p->fp_c.warnings) > 1) { G_sprint(p, 2, "%d warnings to kick\n", k_cmd_fp_kick - p->fp_c.warnings); } else if ((k_cmd_fp_kick - p->fp_c.warnings) == 1) { G_sprint(p, 2, "next time you will be kicked\n"); } else if ((k_cmd_fp_kick - p->fp_c.warnings) < 1) { if ((p->ct == ctPlayer) || ((p->ct == ctSpec) && !match_in_progress)) { G_bprint(2, "%s is a command flooooder!!!\nand will be kicked\n", getname(p)); } G_sprint(p, 2, "Go away!\n"); stuffcmd(p, "disconnect\n"); // FIXME: stupid way } } p->fp_c.warnings += 1; return true; // flooder } p->fp_c.cmd_time[idx] = g_globalvars.time; if (++idx >= k_cmd_fp_count) { idx = 0; } p->fp_c.last_cmd = idx; return false; } void redirect(void) { int i; char cmd_command[1024]; trap_CmdArgv(0, cmd_command, sizeof(cmd_command)); if (!only_digits(cmd_command) || !(((i = atoi(cmd_command)) >= 0) && (i < cmds_cnt))) { return; // sanity } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd %s %s\n", cmds[i].name, params_str(1, -1)); } // check if players client support params in aliases qbool isSupport_Params(gedict_t *p) { // seems only ezQuake support return (p->ezquake_version > 0 ? true : false); // have no idea at which point ezquake start support it } void StuffAliases(gedict_t *p) { int i; for (i = 1; i <= MAX_CLIENTS; i++) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "alias %d impulse %d\n", i, i); } if (p->ct == ctSpec) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "alias next_fav fav_next\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "alias notready break\n"); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "alias kfjump \"impulse 156;+jump;wait;-jump\"\n"); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "alias krjump \"impulse 164;+jump;wait;-jump\"\n"); } } // just check is this cmd valid for class of this player // admin rights skipped here qbool isValidCmdForClass(int icmd, qbool isSpec) { if ((icmd < 0) || (icmd >= cmds_cnt)) { return false; } if (k_matchLess && !(cmds[icmd].cf_flags & CF_MATCHLESS)) { return false; // cmd does't allowed in matchLess mode } if (!k_matchLess && (cmds[icmd].cf_flags & CF_MATCHLESS_ONLY)) { return false; // cmd allowed in matchLess mode _only_ } // split class if (isSpec) { // spec if (!(cmds[icmd].cf_flags & CF_SPECTATOR)) { return false; // cmd not for spec } } else { // player if (!(cmds[icmd].cf_flags & CF_PLAYER)) { return false; // cmd not for player } } return true; } // check if this cmd require admin rights qbool isCmdRequireAdmin(int icmd, qbool isSpec) { if ((icmd < 0) || (icmd >= cmds_cnt)) { return false; } // split class if (isSpec) { // spec if (cmds[icmd].cf_flags & CF_SPC_ADMIN) { return true; // cmd require admin rights } } else { // player if (cmds[icmd].cf_flags & CF_PLR_ADMIN) { return true; // cmd require admin rights } } return false; } void cmdslist_dl(void) { int i, from, to; char *name, *params, arg_2[32]; qbool spc = (self->ct == ctSpec); qbool support_params = isSupport_Params(self); // seems we alredy done that if (self->k_stuff & STUFF_COMMANDS) { G_sprint(self, 2, "cmdslist alredy stuffed\n"); return; } // no arguments if (trap_CmdArgc() == 1) { G_sprint(self, 2, "cmdslist without arguments\n"); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); from = bound(0, atoi(arg_2), cmds_cnt); to = bound(from, from + MAX_STUFFED_ALIASES_PER_FRAME, cmds_cnt); // stuff portion of aliases for (i = from; i < to; i++) { name = cmds[i].name; if (i == 0) { G_sprint(self, 2, "Loading commands list...\n"); } if (!isValidCmdForClass(i, spc) // cmd does't valid for this class of player or matchless mode does't have this command || (cmds[i].f == dummy) // cmd have't function, ie u must not stuff alias for this cmd || (cmds[i].cf_flags & CF_NOALIAS)) // no alias for such command, may be accessed only via /cmd commandname { to = min(to + 1, cmds_cnt); continue; } params = ((cmds[i].cf_flags & CF_PARAMS) && support_params) ? " %0" : ""; stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "alias %s cmd %03d%s\n", name, (int)i, params); } if (i < cmds_cnt) { // request next stuffing stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd cmdslist_dl %d\n", i); return; } // we done self->k_stuff = self->k_stuff | STUFF_COMMANDS; // add flag G_sprint(self, 2, "Commands loaded\n"); } void StuffModCommands(gedict_t *p) { // stuff impulses based aliases, or just aliases, not that much... StuffAliases(p); p->k_stuff = p->k_stuff & ~STUFF_COMMANDS; // remove flag stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "cmd cmdslist_dl %d\n", 0); } void Init_cmds(void) { int i = 0; for (; i < cmds_cnt; i++) { if (strnull(cmds[i].name) || !(cmds[i].f)) { G_Error("Init_cmds: null"); } if ((int)strlen(cmds[i].name) > max_cmd_len) { max_cmd_len = strlen(cmds[i].name); } if (cmds[i].cf_flags & CF_PLR_ADMIN) { cmds[i].cf_flags |= CF_PLAYER; // this let simplify cmds[] table } if (cmds[i].cf_flags & CF_SPC_ADMIN) { cmds[i].cf_flags |= CF_SPECTATOR; // this let simplify cmds[] table } if (cmds[i].cf_flags & CF_MATCHLESS_ONLY) { cmds[i].cf_flags |= CF_MATCHLESS; // this let simplify cmds[] table } } } void Do_ShowCmds(qbool adm_req) { qbool first = true; int i; char *name, dots[64]; char arg_1[1024]; trap_CmdArgv(1, arg_1, sizeof(arg_1)); for (i = 0; i >= 0 && i < cmds_cnt; i++) { name = cmds[i].name; if (strnull(cmds[i].description) || (cmds[i].description == CD_NODESC)) { continue; // command does't have description } if (!isValidCmdForClass(i, self->ct == ctSpec)) { continue; // cmd does't valid for this class of player or matchless mode does't have this command } if (adm_req != isCmdRequireAdmin(i, self->ct == ctSpec)) { continue; } if (arg_1[0] && !strstr(name, arg_1)) { continue; } if (first) { first = false; G_sprint(self, 2, "\n%s commands for %s:\n\n", (adm_req ? redtext("admin") : redtext("common")), (self->ct == ctSpec ? redtext("spectator") : redtext("player"))); } make_dots(dots, sizeof(dots), max_cmd_len, name); G_sprint(self, 2, "%s%s %s\n", redtext(name), dots, cmds[i].description); } } void ShowCmds(void) { Do_ShowCmds(false); // show common commands Do_ShowCmds(true); // show admin commands } qbool check_perm(gedict_t *p, int perm) { switch (perm) { case 0: G_sprint(p, 2, "%s can use this command\n", redtext("no one")); return false; case 1: if (!is_real_adm(p)) { G_sprint(p, 2, "you must be a %s\n", redtext("real admin")); return false; } break; case 2: if (!is_adm(p)) { G_sprint(p, 2, "you must be an %s\n", redtext("admin")); return false; } break; case 3: case 4: G_sprint(p, 2, "%s is not implemented in this mode\n", redtext("judges")); return false; case 5: break; default: G_sprint(p, 2, "server is misconfigured, command %s\n", redtext("skipped")); return false; } return true; } void ShowOpts(void) { G_sprint(self, 2, "%s... -1 mins match time\n" "%s..... +1 mins match time\n" "%s.... -5 mins match time\n" "%s...... +5 mins match time\n" "%s... -10 fraglimit\n" "%s..... +10 fraglimit\n" "%s.......... change deathmatch mode\n" "%s.......... change teamplay mode\n" "%s.... drop quad when killed\n" "%s.... drop ring when killed\n" "%s... drop pack when killed\n" "%s........ change locking mode\n" "%s....... change spawntype\n" "%s....... toggle sv_maxspeed\n" "%s.... quad, %s, ring & suit\n" "%s... best/last weapon dropped\n" "%s... underwater discharges\n" "%s..... toggle spectator talk\n" "%s...... toggle midair mode\n" "%s... toggle grenade mode\n" "%s.... toggle instagib mode\n" "%s..... toggle berzerk mode\n", redtext("timedown1"), redtext("timeup1"), redtext("timedown"), redtext("timeup"), redtext("fragsdown"), redtext("fragsup"), redtext("dm"), redtext("tp"), redtext("dropquad"), redtext("dropring"), redtext("droppacks"), redtext("lock"), redtext("spawn"), redtext("speed"), redtext("powerups"), redtext("666"), redtext("fairpacks"), redtext("discharge"), redtext("silence"), redtext("midair"), redtext("gren_mode"), redtext("instagib"), redtext("berzerk")); } void ShowQizmo(void) { G_sprint(self, 2, "%s....... lagsettings\n" "%s..... enemy vicinity reporting\n" "%s..... point function\n", redtext("qlag"), redtext("qenemy"), redtext("qpoint")); } /* // ShowMessages and SendMessage command implementations added void ShowMessages(void) { G_sprint(self, 2, "%s..... who killed you last\n" "%s..... who you last killed\n" "%s... last player joined\n, redtext("killer"), redtext("victim"), redtext("newcomer")"); } */ /* // Display all printable characters to console in octal table */ void ShowCharsetTableHexa(void) { int i; G_sprint(self, 2, "\n%s\n\n 0123456789ABCDEF\n ................\n", redtext("Hexadecimal charset table:")); for (i = 16; i < 256; i++) { if ((i % 16) == 0) { G_sprint(self, 2, "%1X..", i / 16); } G_sprint(self, 2, "%c", i); if (((i % 16) == 15) || (i == 255)) { G_sprint(self, 2, "\n"); } } G_sprint(self, 2, "\n"); } /* // Display all printable characters to console in hexadecimal table */ void ShowCharsetTableOctal(void) { int i; G_sprint(self, 2, "\n%s\n\n 01234567\n ........\n", redtext("Octal charset table:")); for (i = 16; i < 256; i++) { if ((i % 8) == 0) { G_sprint(self, 2, "%02o..", i / 8); } G_sprint(self, 2, "%c", i); if (((i % 8) == 7) || (i == 255)) { G_sprint(self, 2, "\n"); } } G_sprint(self, 2, "\n"); } void ShowVersion(void) { // limiting to 38 chars for VVD... G_sprint(self, 2, "\n\235\236\237 %s \235\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("ABOUT")); G_sprint(self, 2, "\n\213\212\212\212%s\212\212\212\212\213\n", "QUAKEWORLD SERVER INFORMATION"); if (strlen(cvar_string("qws_fullname"))) { G_sprint(self, 2, "%s....: %28s\n", redtext("Name"), cvar_string("qws_fullname")); } else { G_sprint(self, 2, "%s....: %28s\n", redtext("Name"), cvar_string("version")); } if (strlen(cvar_string("qws_version"))) { G_sprint(self, 2, "%s.: %28s\n", redtext("Version"), dig3s("%s", cvar_string("qws_version"))); } if (strlen(cvar_string("qws_buildnum"))) { G_sprint(self, 2, "%s...: %26s-%1.1s\n", redtext("Build"), cvar_string("qws_buildnum"), strlen(cvar_string("qws_platform")) ? cvar_string("qws_platform") : "u"); } if (strlen(cvar_string("qws_builddate"))) { G_sprint(self, 2, "%s....: %28s\n", redtext("Date"), dig3s("%s", cvar_string("qws_builddate"))); } if (strlen(cvar_string("qws_homepage"))) { G_sprint(self, 2, "%s.: %28s\n", redtext("Webpage"), cvar_string("qws_homepage")); } G_sprint(self, 2, "\n\213\212\212\212\212\212%s\212\212\212\212\212\213\n", "QUAKEWORLD MOD INFORMATION"); G_sprint(self, 2, "%s....: %28s\n", redtext("Name"), cvar_string("qwm_fullname")); G_sprint(self, 2, "%s.: %28s\n", redtext("Version"), dig3s("%s", cvar_string("qwm_version"))); if (strlen(cvar_string("qwm_buildnum"))) { G_sprint(self, 2, "%s...: %26s-%1.1s\n", redtext("Build"), cvar_string("qwm_buildnum"), strlen(cvar_string("qwm_platform")) ? cvar_string("qwm_platform") : "u"); } G_sprint(self, 2, "%s....: %28s\n", redtext("Date"), dig3s("%s", cvar_string("qwm_builddate"))); G_sprint(self, 2, "%s.: %28s\n", redtext("Webpage"), cvar_string("qwm_homepage")); // G_sprint(self, 2, "\n%s\n\n%s\n", MOD_RELEASE_QUOTE, redtext(MOD_RELEASE_HASHTAGS)); // G_sprint(self, 2, "\n%s\n", MOD_RELEASE_QUOTE); if ((int)cvar("sv_specprint") & SPECPRINT_SPRINT) { G_sprint( self, PRINT_CHAT, "\n\207\207\207 WARNING: Spectators may see team\nmessages (mm2) on this server!\n"); } G_sprint(self, 2, "\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n\n"); } void ChangeOvertime(void) { int f1, f2; if (match_in_progress) { return; } f1 = bound(0, cvar("k_overtime"), 3); f2 = bound(0, cvar("k_exttime"), 999); if (!f1) { cvar_fset("k_overtime", 1); if (!f2) { cvar_fset("k_exttime", (f2 = 1)); } G_bprint(2, "%s: time based\n", redtext("Overtime")); G_bprint(2, "%s: %d minute%s\n", redtext("Overtime length"), (int)f2, count_s(f2)); } else if (f1 == 1) { cvar_fset("k_overtime", 2); G_bprint(2, "%s: sudden death\n", redtext("Overtime")); } else if (f1 == 2) { cvar_fset("k_overtime", 3); G_bprint(2, "%s: tie-break\n", redtext("Overtime")); } else if (f1 == 3) { cvar_fset("k_overtime", 0); G_bprint(2, "%s: off\n", redtext("Overtime")); } } void ChangeOvertimeUp(void) { int k_exttime = cvar("k_exttime"); if (match_in_progress) { return; } k_exttime++; if ((k_exttime >= 11) || (k_exttime <= 0)) { k_exttime = 1; } cvar_fset("k_exttime", k_exttime); G_bprint(2, "%s %d %s%s\n", redtext("Overtime length set to"), k_exttime, redtext("minute"), redtext(count_s(k_exttime))); } void SendKillerMsg(void) { SendMessage(self->killer); } void SendVictimMsg(void) { SendMessage(self->victim); } void SendNewcomerMsg(void) { SendMessage(newcomer->netname); } void SendMessage(char *name) { char *s; gedict_t *p; for (p = world; (p = find_client(p));) { if (p == self) { continue; } if (!strnull(name) && streq(p->netname, name)) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "say "); if ((s = ezinfokey(self, "premsg"))) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, " %s ", s); } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "%s", name); if ((s = ezinfokey(self, "postmsg"))) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, " %s", s); } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "\n"); return; } } G_sprint(self, 2, "No name to display\n"); } static char* get_frp_str(void) { switch (get_fair_pack()) { case 0: return "off"; case 1: return "on"; case 2: return "lst"; default: return "unk"; } } void ModStatus1(void) { int votes; gedict_t *p; G_sprint(self, 2, "%-14.14s %-4d\n", redtext("Maxspeed"), (int)k_maxspeed); G_sprint(self, 2, "%-14.14s %-4d ", redtext("Deathmatch"), (int)deathmatch); G_sprint(self, 2, "%-14.14s %-3d\n", redtext("Teamplay"), (int)tp_num()); G_sprint(self, 2, "%-14.14s %-4d ", redtext("Timelimit"), (int)timelimit); G_sprint(self, 2, "%-14.14s %-3d\n", redtext("Fraglimit"), (int)fraglimit); G_sprint(self, 2, "%-14.14s %-4.4s ", redtext("Powerups"), Get_PowerupsStr()); G_sprint(self, 2, "%-14.14s %-3.3s\n", redtext("Discharge"), OnOff(cvar("k_dis"))); G_sprint(self, 2, "%-14.14s %-4.4s ", redtext("Drop Quad"), OnOff(cvar("dq"))); G_sprint(self, 2, "%-14.14s %-3.3s\n", redtext("Drop Ring"), OnOff(cvar("dr"))); G_sprint(self, 2, "%-14.14s %-4.4s ", redtext("Fair Backpacks"), get_frp_str()); G_sprint(self, 2, "%-14.14s %-3.3s\n", redtext("Drop Backpacks"), OnOff(cvar("dp"))); G_sprint(self, 2, "%-14.14s %-4.4s ", redtext("spec info perm"), mi_adm_only() ? "adm" : "all"); G_sprint(self, 2, "%-14.14s %-3.3s\n", redtext("more spec info"), OnOff(mi_on())); G_sprint(self, 2, "%-14.14s %-4.4s\n", redtext("teleteam"), OnOff(cvar("k_tp_tele_death"))); G_sprint(self, 2, "%-14.14s %-3.3s\n", redtext("Berzerk"), OnOff(cvar("k_bzk"))); if (match_in_progress == 1) { p = find(world, FOFCLSN, "timer"); if (p) { G_sprint(self, 2, "The match will start in %d second%s\n", (int)p->cnt2, count_s(p->cnt2)); } return; } if ((votes = get_votes( OV_ELECT))) G_sprint(self, 2, "%s election in progress:\220%d/%d\221 vote%s\n", redtext(get_elect_type_str()), votes, get_votes_req( OV_ELECT, false), count_s(votes)); if (k_captains == 2) { G_sprint(self, 2, "%s in progress\n", redtext("Team picking")); } if (floor(k_captains) == 1) { G_sprint(self, 2, "\2201\221 %s present\n", redtext("captain")); } if (floor(k_coaches) == 1) { G_sprint(self, 2, "\2201\221 %s present\n", redtext("coach")); } if (match_in_progress == 2) { if (k_sudden_death) { G_sprint(self, 2, "%s overtime in progress\n", redtext(SD_type_str())); } else { p = find(world, FOFCLSN, "timer"); if (p) { G_sprint(self, 2, "Match in progress\n" "\220%s\221 full minute%s left\n", dig3(p->cnt - 1), count_s(p->cnt)); } } } } void ModStatus2(void) { int i; char *ot = ""; G_sprint(self, 2, "%s\n", redtext(respawn_model_name(cvar("k_spw")))); if (isDuel()) { G_sprint(self, 2, "%s: duel\n", redtext("Server mode")); } else if (isFFA()) { G_sprint(self, 2, "%s: FFA\n", redtext("Server mode")); } else if (isCTF()) { G_sprint(self, 2, "%s: CTF\n", redtext("Server mode")); G_sprint( self, 2, "%s: %s\n", redtext("Server locking"), (!cvar("k_lockmode") ? "off" : (cvar("k_lockmode") == 2 ? "all" : (cvar("k_lockmode") == 1 ? "team" : "unknown")))); G_sprint(self, 2, "%s: hook %s, runes %s, ga %s\n", redtext("CTF settings"), OnOff(cvar("k_ctf_hook")), OnOff(cvar("k_ctf_runes")), OnOff(cvar("k_ctf_ga"))); } else if (isTeam()) { G_sprint(self, 2, "%s: team\n", redtext("Server mode")); G_sprint( self, 2, "%s: %s\n", redtext("Server locking"), (!cvar("k_lockmode") ? "off" : (cvar("k_lockmode") == 2 ? "all" : (cvar("k_lockmode") == 1 ? "team" : "unknown")))); } else G_sprint(self, 2, "%s: unknown\n", redtext("Server mode")); if (!match_in_progress) { G_sprint(self, 2, "%s (%s: %d %s: %d %s: %d)\n", redtext("Teaminfo"), redtext("cur"), (int)CountRTeams(), redtext("min"), (int)cvar("k_lockmin"), redtext("max"), (int)cvar("k_lockmax")); } G_sprint(self, 2, "%s: %s\n", redtext("Spectalk"), OnOff(cvar("k_spectalk"))); i = cvar("k_exttime"); switch ((int)cvar("k_overtime")) { case 0: ot = "off"; break; case 1: ot = va("%d minute%s", i, count_s(i)); break; case 2: ot = "sudden death"; break; case 3: ot = va("%d tie-break", tiecount()); break; default: ot = "unknown"; break; } G_sprint(self, 2, "%s: %s\n", redtext("Overtime"), ot); i = iKey(world, "fpd"); G_sprint(self, 2, "%s: %s\n", redtext("QiZmo lag"), OnOff(i & 8)); G_sprint(self, 2, "%s: %s\n", redtext("QiZmo timers"), OnOff(i & 2)); G_sprint(self, 2, "%s: %s\n", redtext("QiZmo enemy reporting"), OnOff(i & 32)); G_sprint(self, 2, "%s: %s\n", redtext("QiZmo pointing"), OnOff(i & 128)); /* new FDP bits https://www.quakeworld.nu/wiki/FPD G_sprint(self, 2, "%s: %s\n", redtext("Skin forcing"), OnOff(! (i & 256) )); G_sprint(self, 2, "%s: %s\n", redtext("Color forcing"), OnOff(! (i & 512) )); G_sprint(self, 2, "%s: %s\n", redtext("Pitch speed limiting"), OnOff( i & 16384 )); G_sprint(self, 2, "%s: %s\n", redtext("Yaw speed limiting"), OnOff( i & 32768 )); */ G_sprint(self, 2, "%s: %s\n", redtext("Admin election"), Allowed(cvar("k_allowvoteadmin"))); G_sprint(self, 2, "%s: %s\n", redtext("Check frametimes"), Enabled(framechecks)); switch ((int)cvar("k_prewar")) { case 1: ot = "players may fire before match"; break; case 2: ot = "players may fire and jump when ready"; break; case 0: default: ot = "players may not fire before match"; break; } G_sprint(self, 2, "%s: %s\n", redtext("Prewar"), ot); if (k_sv_locktime) { int seconds = k_sv_locktime - g_globalvars.time; G_sprint(self, 2, "%s: %d second%s\n", redtext("server is temporary locked"), seconds, count_s(seconds)); } if (k_cmd_fp_disabled) { G_sprint(self, 2, "%s: off\n", redtext("Command floodprot")); } else { G_sprint(self, 2, "%s: %d commands allowed per %d sec.," " skip commands for %d sec., ", redtext("Command floodprot"), k_cmd_fp_count, (int)k_cmd_fp_per, (int)k_cmd_fp_for); if (k_cmd_fp_dontkick) { G_sprint(self, 2, "cmdfp kick disabled\n"); } else { G_sprint(self, 2, "kick after %d warn.\n", k_cmd_fp_kick); } } } void ModStatusVote(void) { qbool voted = false; int votes, i; gedict_t *p; if (k_matchLess || !match_in_progress) if (vote_get_maps() >= 0) { voted = true; G_sprint(self, 2, "%s:\n", redtext("Map voting")); for (i = 0; i < MAX_CLIENTS; i++) { if (!maps_voted[i].map_id) { break; } G_sprint(self, 2, "\220%s\221 %2d vote%s\n", GetMapName(maps_voted[i].map_id), maps_voted[i].map_votes, count_s(maps_voted[i].map_votes)); for (p = world; (p = find_client(p));) { if (p->v.map == maps_voted[i].map_id) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!((get_elect_type() == etCaptain) && match_in_progress)) // doesn't show captain election in game { if ((votes = get_votes(OV_ELECT))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for %s election:\n", votes, get_votes_req(OV_ELECT, false), count_s(votes), redtext(get_elect_type_str())); for (p = world; (p = find_client(p));) { if (p->v.elect) { G_sprint(self, 2, "%s%s\n", (p->v.elect_type != etNone) ? "\207" : " ", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_PICKUP))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s game:\n", votes, get_votes_req(OV_PICKUP, false), count_s(votes), redtext("pickup")); for (p = world; (p = find_client(p));) { if (p->v.pickup) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_RPICKUP))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s game:\n", votes, get_votes_req(OV_RPICKUP, false), count_s(votes), redtext("rpickup")); for (p = world; (p = find_client(p));) { if (p->v.rpickup) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (k_matchLess || (match_in_progress == 2)) { if ((votes = get_votes(OV_BREAK))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for %s:\n", votes, get_votes_req(OV_BREAK, false), count_s(votes), (k_matchLess ? "next map" : "stopping")); for (p = world; (p = find_client(p));) { if (p->v.brk) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_ANTILAG))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s mode change:\n", votes, get_votes_req(OV_ANTILAG, false), count_s(votes), redtext("antilag")); for (p = world; (p = find_client(p));) { if (p->v.antilag) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_NOSPECS))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s mode change:\n", votes, get_votes_req(OV_NOSPECS, false), count_s(votes), redtext("no spec")); for (p = world; (p = find_client(p));) { if (p->v.nospecs) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_TEAMOVERLAY))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s change:\n", votes, get_votes_req(OV_TEAMOVERLAY, false), count_s(votes), redtext("teamoverlay")); for (p = world; (p = find_client(p));) { if (p->v.teamoverlay) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_PRIVATE))) { qbool enable = !cvar("sv_login"); voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s:\n", votes, get_votes_req(OV_PRIVATE, false), count_s(votes), enable ? redtext("private game") : redtext("public game")); for (p = world; (p = find_client(p));) { if (p->v.privategame) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_SWAPALL))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s for a %s game:\n", votes, get_votes_req(OV_SWAPALL, false), count_s(votes), redtext("swapall")); for (p = world; (p = find_client(p));) { if (p->v.swapall) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_HOOKSMOOTH))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s to change hookstyle to %s\n", votes, get_votes_req(OV_HOOKSMOOTH, false), count_s(votes), redtext("smooth")); for (p = world; (p = find_client(p));) { if (p->v.hooksmooth) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_HOOKFAST))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s to change hookstyle to %s\n", votes, get_votes_req(OV_HOOKFAST, false), count_s(votes), redtext("fast")); for (p = world; (p = find_client(p));) { if (p->v.hookfast) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (!match_in_progress) { if ((votes = get_votes(OV_HOOKCLASSIC))) { voted = true; G_sprint(self, 2, "\220%d/%d\221 vote%s to change hookstyle to %s\n", votes, get_votes_req(OV_HOOKCLASSIC, false), count_s(votes), redtext("classic")); for (p = world; (p = find_client(p));) { if (p->v.hookclassic) { G_sprint(self, 2, " %s\n", p->netname); } } } } if (voted) { G_sprint(self, 2, "%s\n", redtext("--------------")); } else { G_sprint(self, 2, "%s\n", redtext("No election going on")); } } char* OnePlayerStatus(gedict_t *p, gedict_t *e_self) { char *team_str = (isTeam() ? va(" \220%4.4s\221", getteam(p)) : ""); e_self = (e_self ? e_self : world); return va("%s%s%s %s%s", (p->ready ? "\206" : "\207"), (is_adm(p) ? "\xC1" : " "), team_str, getname(p), (p == e_self ? redtext(" \x8D you") : "")); } void PlayerStatus(void) { qbool found = false; gedict_t *p; if (match_in_progress) { G_sprint(self, 2, "Game in progress\n"); return; } for (p = world; (p = find_plr(p));) { if (!found) { G_sprint( self, 2, "Players list:\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } G_sprint(self, 2, "%s\n", OnePlayerStatus(p, self)); found = true; } G_sprint(self, 2, "%s\n", (found ? "" : "no players")); } void PlayerStatusS(void) { qbool found = false; gedict_t *p; for (p = world; (p = find_plr(p));) { if (!found) { G_sprint( self, 2, "Players skins list:\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } G_sprint(self, 2, "\220%10s\221 %s\n", ezinfokey(p, "skin"), p->netname); found = true; } G_sprint(self, 2, "%s\n", (found ? "" : "no players")); } void PlayerStatusN(void) { qbool found = false; gedict_t *p; if (match_in_progress) { G_sprint(self, 2, "Game in progress\n"); return; } if (CountRPlayers() == CountPlayers()) { G_sprint(self, 2, "All players ready\n"); return; } for (p = world; (p = find_plr(p));) { if (p->ready) { continue; } if (!found) { G_sprint( self, 2, "Players %s ready:\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("not")); } G_sprint(self, 2, "%s\n", OnePlayerStatus(p, self)); found = true; } G_sprint(self, 2, "%s\n", (found ? "" : "can't find not ready players")); } // broadcast not ready players void ListWhoNot(void) { qbool found = false; gedict_t *p, *p2; if (match_in_progress) { G_sprint(self, 2, "Game in progress\n"); return; } if (CountRPlayers() == CountPlayers()) { G_sprint(self, 2, "All players ready\n"); return; } if ((self->ct == ctPlayer) && !self->ready) { G_sprint(self, 2, "Ready yourself first\n"); return; } if (k_whonottime && (g_globalvars.time < (k_whonottime + 10))) { G_sprint(self, 2, "Only one %s in 10 seconds\n", redtext("list")); return; } k_whonottime = g_globalvars.time; for (p = world; (p = find_plr(p));) { if (p->ready) { continue; } if (!found) { G_bprint( 2, "Players %s ready:\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("not")); // broadcast } for (p2 = world; (p2 = find_client(p2));) { G_sprint(p2, 2, "%s\n", OnePlayerStatus(p, p2)); } found = true; } if (found) { G_bprint(2, "\n"); // broadcast } else { G_sprint(self, 2, "can't find not ready players\n"); // self } } void VotePickup(void) { int votes; if (match_in_progress) { return; } if (k_captains) { G_sprint(self, 2, "No pickup when captain stuffing\n"); return; } self->v.pickup = !self->v.pickup; G_bprint(2, "%s %s %s%s\n", self->netname, redtext("says"), (self->v.pickup ? "pickup!" : "no pickup"), ((votes = get_votes_req( OV_PICKUP, true)) ? va(" (%d)", votes) : "")); vote_check_pickup(); } void ReportMe(void) { gedict_t *p; char *t1, *t2, *wt, *pa1, *pa2; float f1, flag = 0; if (!strnull(ezinfokey(self, "k_nick")) || !strnull(ezinfokey(self, "k"))) { flag = 1; } pa1 = ""; pa2 = ": "; wt = "axe:"; f1 = 0; if ((int)self->s.v.items & 1) { wt = "sg:"; f1 = self->s.v.ammo_shells; } if ((int)self->s.v.items & 4) { wt = "ng:"; f1 = self->s.v.ammo_nails; } if ((int)self->s.v.items & 2) { wt = "ssg:"; f1 = self->s.v.ammo_shells; } if ((int)self->s.v.items & 8) { wt = "sng:"; f1 = self->s.v.ammo_nails; } if ((int)self->s.v.items & 16) { wt = "gl:"; f1 = self->s.v.ammo_rockets; } if ((int)self->s.v.items & 64) { wt = "lg:"; f1 = self->s.v.ammo_cells; } if ((int)self->s.v.items & 32) { wt = "rl:"; f1 = self->s.v.ammo_rockets; } t1 = getteam(self); for (p = world; (p = find_plr(p));) { if (strneq(t1, t2 = getteam(p))) { continue; } if (flag) { t1 = ezinfokey(self, "k_nick"); if (strnull(t1)) { t1 = ezinfokey(self, "k"); } G_sprint(p, 3, "%s: ", t1); } else { G_sprint(p, 3, "%s%s%s", pa1, self->netname, pa2); } if (self->s.v.armorvalue) { G_sprint(p, 3, "%s:%d", armor_type((int)self->s.v.items), (int)self->s.v.armorvalue); } else { G_sprint(p, 3, "a:0"); } G_sprint(p, 3, " h:%d %s%d", (int)self->s.v.health, wt, (int)f1); if ((int)self->s.v.items & 524288) { G_sprint(p, 3, " \220\212%s\212\221", redtext("eyes")); } if ((int)self->s.v.items & 1048576) { G_sprint(p, 3, " \220\212%s\212\221", redtext("666")); } if ((int)self->s.v.items & 4194304) { G_sprint(p, 3, " \220\212%s\212\221", redtext("quad")); } G_sprint(p, 3, "\n"); } } void ToggleRespawns(void) { int k_spw = bound(0, cvar("k_spw"), 4); if (match_in_progress) { return; } if (++k_spw > 4) { k_spw = 0; } cvar_fset("k_spw", k_spw); G_bprint(2, "%s\n", respawn_model_name(k_spw)); } void ToggleSpawnPoints(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_spm_show", redtext("visible spawn points")); if (cvar("k_spm_show")) { ShowSpawnPoints(); } else { HideSpawnPoints(); } } void TogglePowerups(void) { char arg[64]; int i; qbool changed = false; if (match_in_progress) { return; } if (cvar("k_instagib")) { G_bprint(2, "%s are disabled with Instagib\n", redtext("Powerups")); return; } if (cvar("k_midair")) { G_bprint(2, "%s are disabled with Midair\n", redtext("Powerups")); return; } if (trap_CmdArgc() <= 1) { // no arguments, just toggle on/off powerups cvar_toggle_msg(self, "k_pow", redtext("powerups")); cvar_fset("k_pow_q", cvar("k_pow")); cvar_fset("k_pow_p", cvar("k_pow")); cvar_fset("k_pow_r", cvar("k_pow")); cvar_fset("k_pow_s", cvar("k_pow")); return; } // at least one argument for (i = 1; i < min(1 + 4, trap_CmdArgc()); i++) { trap_CmdArgv(i, arg, sizeof(arg)); if (streq("q", arg)) { cvar_toggle_msg(self, "k_pow_q", redtext("quad")); changed = true; } else if (streq("p", arg)) { cvar_toggle_msg(self, "k_pow_p", redtext("pent")); changed = true; } else if (streq("r", arg)) { cvar_toggle_msg(self, "k_pow_r", redtext("ring")); changed = true; } else if (streq("s", arg)) { cvar_toggle_msg(self, "k_pow_s", redtext("suit")); changed = true; } } // enable k_pow if at least one powerup was turned on and vice versa turn off k_pow if all powerups was turned off if (changed) { cvar_fset("k_pow", (cvar("k_pow_q") || cvar("k_pow_p") || cvar("k_pow_r") || cvar("k_pow_s"))); } } void TogglePuPickup(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_pow_pickup", redtext("new powerups pickup (no multi pickup)")); } void ToggleDischarge(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_dis", redtext("discharges")); } void ShowDMM(void) { G_sprint(self, 2, "Deathmatch %s\n", dig3(deathmatch)); } void ChangeDM(float dmm) { if (!is_rules_change_allowed()) { return; } if (deathmatch == (int)dmm) { G_sprint(self, 2, "%s%s already set\n", redtext("dmm"), dig3(deathmatch)); return; } deathmatch = bound(1, (int)dmm, 5); cvar_set("deathmatch", va("%d", (int)deathmatch)); if (dmm != 4) // if leaving dmm4 { cvar_set("k_midair", "0"); // force midair off cvar_set("k_instagib", "0"); // force instagib off } else // if entering dmm4 { cvar_set("timelimit", "3"); // Set match length to 3 minutes } G_bprint(2, "Deathmatch %s\n", dig3(deathmatch)); } void ChangeTP(void) { if (match_in_progress) { return; } if (!isTeam() && !isCTF()) { G_sprint(self, 3, "console: non team mode disallows you to change teamplay setting\n"); return; } teamplay = bound(1, teamplay, 4); teamplay++; if (teamplay == 5) { teamplay = 1; } cvar_fset("teamplay", (int)teamplay); G_bprint(2, "Teamplay %s\n", dig3(teamplay)); } void TimeDown(float t) { int tl = timelimit; if (match_in_progress) { return; } if ((t == 5) && isHoonyModeAny()) { t = 2; } if ((t == 5) && (timelimit == 5)) { timelimit = 3; } else if ((t == 5) && (timelimit == 3)) { timelimit = 1; } else { timelimit -= t; } timelimit = bound(0, timelimit, cvar("k_timetop")); if ((timelimit <= 0) && (fraglimit <= 0)) { G_sprint(self, 2, "You need some timelimit or fraglimit at least\n"); timelimit = tl; } if (tl == timelimit) { G_sprint(self, 2, "%s still %s\n", redtext("timelimit"), dig3(timelimit)); return; } cvar_set("timelimit", va("%d", (int)timelimit)); G_bprint(2, "%s %s %s%s\n", redtext("Match length set to"), dig3(timelimit), redtext("minute"), redtext(count_s(timelimit))); } void TimeUp(float t) { int tl = timelimit; if (match_in_progress) { return; } if ((t == 5) && (timelimit == 0)) { timelimit = 1; } else if ((t == 5) && (timelimit == 1)) { timelimit = 3; } else if ((t == 5) && (timelimit == 3)) { timelimit = 5; } else { timelimit += t; } timelimit = bound(0, timelimit, cvar("k_timetop")); if (tl == timelimit) { G_sprint(self, 2, "%s still %s\n", redtext("timelimit"), dig3(timelimit)); return; } cvar_fset("timelimit", (int)timelimit); G_bprint(2, "%s %s %s%s\n", redtext("Match length set to"), dig3(timelimit), redtext("minute"), redtext(count_s(timelimit))); } void TimeSet(float t) { int tl = timelimit; if (match_in_progress) { return; } timelimit = bound(0, t, cvar("k_timetop")); if (tl == timelimit) { G_sprint(self, 2, "%s still %s\n", redtext("timelimit"), dig3(timelimit)); return; } cvar_fset("timelimit", (int)timelimit); G_bprint(2, "%s %s %s%s\n", redtext("Match length set to"), dig3(timelimit), redtext("minute"), redtext(count_s(timelimit))); } void AdjustFragLimit(int delta) { fraglimit += delta * (isHoonyModeAny() ? 2 : 10); fraglimit = bound(isHoonyModeAny() ? 0 : 1, fraglimit, isHoonyModeDuel() ? 20 : 100); } void FragsDown(void) { if (match_in_progress) { return; } else if (isHoonyModeAny()) { G_sprint(self, PRINT_HIGH, "No fraglimit in hoonymode\n"); return; } else { int fl = fraglimit; if (fraglimit == 1) { // allow fraglimit "1" (instead of going from 10 directly to 0) as a type of minimal hoonymode fraglimit = 0; } else if (fraglimit == 0) { // avoid cycling between 0 and 1 (this happens due to below shortcut using bound()) fraglimit = 0; } else { AdjustFragLimit(-1); } if ((timelimit <= 0) && (fraglimit <= 0)) { G_sprint(self, 2, "You need some timelimit or fraglimit at least\n"); fraglimit = fl; } if (fl == fraglimit) { G_sprint(self, 2, "%s still %s\n", redtext("fraglimit"), dig3(fraglimit)); return; } cvar_set("fraglimit", va("%d", (int)(fraglimit))); G_bprint(2, "%s %s\n", redtext("Fraglimit set to"), dig3(fraglimit)); } } void FragsUp(void) { if (match_in_progress) { return; } else if (isHoonyModeAny()) { G_sprint(self, PRINT_HIGH, "No fraglimit in hoonymode\n"); } else { int fl = fraglimit; AdjustFragLimit(1); if (fl == fraglimit) { G_sprint(self, 2, "%s still %s\n", redtext("fraglimit"), dig3(fraglimit)); return; } cvar_set("fraglimit", va("%d", (int)(fraglimit))); G_bprint(2, "%s %s\n", redtext("Fraglimit set to"), dig3(fraglimit)); } } void killquad(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_killquad", redtext("KillQuad")); k_killquad = cvar("k_killquad"); } void bloodfest(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_bloodfest", redtext("Blood Fest mode (for coop/single only)")); k_bloodfest = cvar("k_bloodfest"); } void ToggleDropQuad(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "dq", redtext("DropQuad")); } void ToggleDropRing(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "dr", redtext("DropRing")); } void ToggleDropPack(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "dp", redtext("DropPacks")); } void ToggleFairPacks(void) { int k_frp = bound(0, cvar("k_frp"), 2); if (match_in_progress) { return; } if (k_yawnmode) { k_frp = get_fair_pack(); // Yawnmode: hardcoded to 2 } else { if (++k_frp > 2) k_frp = 0; cvar_fset("k_frp", k_frp); } if (!k_frp) { G_bprint(2, "%s disabled\n", redtext("Fairpacks")); } else if (k_frp == 1) { G_bprint(2, "%s enabled - drop best weapon\n", redtext("Fairpacks")); } else if (k_frp == 2) { G_bprint(2, "%s enabled - drop last fired weapon\n", redtext("Fairpacks")); } else { G_bprint(2, "%s - unknown\n", redtext("Fairpacks")); } } void ToggleSpeed(void) { gedict_t *p; if (match_in_progress) { return; } if (k_maxspeed != 320) { k_maxspeed = 320; } else { k_maxspeed = bound(0, cvar("k_highspeed"), 9999); } G_bprint(2, "%s %d\n", redtext("Maxspeed set to"), (int)k_maxspeed); cvar_fset("sv_maxspeed", k_maxspeed); for (p = world; (p = find_plr(p));) { p->maxspeed = k_maxspeed; } } void ToggleBerzerk(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_bzk", redtext("Berzerk mode")); } void ToggleSpecTalk(void) { int k_spectalk = !cvar("k_spectalk"), fpd = iKey(world, "fpd"); if (match_in_progress && !is_adm(self)) { return; } k_spectalk = bound(0, k_spectalk, 1); if (match_in_progress == 2) { fpd = (k_spectalk) ? (fpd & ~64) : (fpd | 64); localcmd("serverinfo fpd %d\n", fpd); cvar_fset("sv_spectalk", k_spectalk); cvar_fset("k_spectalk", k_spectalk); if (k_spectalk) { G_bprint(2, "Spectalk on: %s\n", redtext("players can now hear spectators")); } else { G_bprint(2, "Spectalk off: %s\n", redtext("players can no longer hear spectators")); } return; } else { cvar_fset("k_spectalk", k_spectalk); if (k_spectalk) { G_bprint(2, "Spectalk on: %s\n", redtext("players can hear spectators during game")); } else { G_bprint(2, "Spectalk off: %s\n", redtext("players cannot hear spectators during game")); } } } void ShowRules(void) { if (isDuel()) { G_sprint(self, 2, "Server is in duel mode.\n"); } else if (isCTF()) { G_sprint(self, 2, "Server is in CTF mode.\n" "Additional commands/impulses:\n" "impulse 22 : Grappling Hook\n" "tossrune : Toss your current rune\n" "tossflag : Toss carried flag\n" "flagstatus : Displays flag information\n"); } else if (isFFA()) { G_sprint(self, 2, "Server is in FFA mode.\n"); } else if (isTeam()) { G_sprint(self, 2, "Server is in team mode.\n" "Typing %s during game\n" "will print time left and teamscores.\n" "Also available during game\n" "are %s and %s.\n", redtext("scores"), redtext("stats"), redtext("efficiency")); } else { G_sprint(self, 2, "Server is in unknown mode.\n"); } if (cvar("k_bzk")) { G_sprint(self, 2, "\nBERZERK mode is activated!\n" "This means that when only %d seconds\n" "remains of the game, all players\n" "gets QUAD/OCTA powered.\n", (int)cvar("k_btime")); } G_sprint(self, 2, "\n"); } void ChangeLock(void) { int lock = bound(0, cvar("k_lockmode"), 2); if (match_in_progress) { return; } lock++; if (lock > 2) { lock = 0; } if (lock == 0) { G_bprint(2, "%s off\n", redtext("Server locking")); } else if (lock == 2) { G_bprint(2, "%s - players cannot connect during game\n", redtext("Server locked")); } else if (lock == 1) { G_bprint(2, "%s - only players in existing teams can connect during game\n", redtext("Teamlock on")); } cvar_fset("k_lockmode", lock); } void TeamSay(float fsndname) { gedict_t *p; char *sndname = va("ktsound%d.wav", (int)fsndname); for (p = world; (p = find_plr(p));) { if ((p != self) && (isTeam() || isCTF()) && !strnull(p->netname) && (iKey(p, "kf") & KF_KTSOUNDS)) { if (streq(getteam(self), getteam(p))) { char *t1 = ezinfokey(p, "k_sdir"); stuffcmd(p, "play %s%s\n", (strnull(t1) ? "" : va("%s/", t1)), sndname); } } } } void PrintScores(void) { int minutes, seconds; gedict_t *p; if (intermission_running) { G_sprint(self, 2, "Intermission\n"); return; } if (!match_in_progress) { G_sprint(self, 2, "no game - no scores\n"); return; } if (match_in_progress == 1) { G_sprint(self, 2, "Countdown\n"); return; } if (k_sudden_death) { G_sprint(self, 2, "%s %s\n", SD_type_str(), redtext("overtime in progress")); } else { if (fraglimit && (p = get_ed_scores1())) { int diff = fraglimit - p->s.v.frags; if (diff >= 0) { G_sprint(self, 2, "Frags left: \220%s\221\n", dig3s("%2d", diff)); } } } if ((p = find(world, FOFCLSN, "timer"))) { minutes = p->cnt; seconds = p->cnt2; if (seconds == 60) { seconds = 0; } else { minutes--; } // we can't use dig3 here because of zero padding, so using dig3s G_sprint(self, 2, "\220%s:%s\221 remaining\n", dig3s("%02d", minutes), dig3s("%02d", seconds)); } if (k_showscores) { if (isCA()) { CA_PrintScores(); } else { int s1 = get_scores1(); int s2 = get_scores2(); int s3; char *t1 = cvar_string("_k_team1"); char *t2 = cvar_string("_k_team2"); char *t3; if ((current_umode < um2on2on2) || (current_umode > um4on4on4)) { G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s2 ? t1 : t2), dig3(s1 > s2 ? s1 : s2)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s2 ? t2 : t1), dig3(s1 > s2 ? s2 : s1)); } else { // if the current UserMode is 2on2on2, 3on3on3, 4on4on4, we have 3 teams s3 = get_scores3(); t3 = cvar_string("_k_team3"); if ((s1 > s2) && (s1 > s3)) { // Team 1 is leading G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t1, dig3(s1)); // Team 2 and 3 G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s2 > s3 ? t2 : t3), dig3(s2 > s3 ? s2 : s3)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s2 > s3 ? t3 : t2), dig3(s2 > s3 ? s3 : s2)); } else if ((s2 > s1) && (s2 > s3)) { // Team 2 is leading G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t2, dig3(s2)); // Team 1 and 3 G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s3 ? t1 : t3), dig3(s1 > s3 ? s1 : s3)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s3 ? t3 : t1), dig3(s1 > s3 ? s3 : s1)); } else if ((s3 > s1) && (s3 > s2)) { // Team 3 is leading G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t3, dig3(s3)); // Team 1 and 2 G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s2 ? t1 : t2), dig3(s1 > s2 ? s1 : s2)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), (s1 > s2 ? t2 : t1), dig3(s1 > s2 ? s2 : s1)); } else if (s1 == s3) { // Team 1 and Team 3 have equal scores G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t1, dig3(s1)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t3, dig3(s3)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t2, dig3(s2)); } else if (s2 == s3) { // Team 2 and Team 3 have equal scores G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t2, dig3(s2)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t3, dig3(s3)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t1, dig3(s1)); } else { // Team 1 and Team 2 have equal scores, but this is the 'catch all' case also G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t1, dig3(s1)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t2, dig3(s2)); G_sprint(self, 2, "%s \220%s\221 = %s\n", redtext("Team"), t3, dig3(s3)); } } } } } // This Endgame statistics is triggered by the ingame /laststats command. void LastStats(void) { if (match_in_progress) { G_sprint(self, 2, "Game in progress\n"); return; } MatchEndStatsTables(); } // This player statistics is triggered by the ingame /stats command. Nothing to do with the endgame stats. void PlayerStats(void) { gedict_t *p, *p2; char *tmp, *stats; int i, pL = 0, tL = 0; if (isRA()) { ra_PlayerStats(); return; } if (match_in_progress != 2) { G_sprint(self, 2, "no game - no statistics\n"); return; } for (p = world; (p = find_plr(p));) { p->k_flag = 0; } for (p = world; (p = find_plr(p));) { pL = max(pL, strlen(p->netname)); tL = max(tL, strlen(getteam(p))); } pL = bound(0, pL, 10); tL = bound(0, tL, 4); G_sprint(self, 2, "%s:\n" "%s %s %s \217 %s\n", redtext("Player statistics"), redtext("Frags"), redtext("rank"), isTeam() ? redtext("friendkills ") : " ", redtext("efficiency")); G_sprint(self, 2, "\235\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236%s\237\n", ((isTeam() || isCTF()) ? "\236\236\236\236\236\236\236\236\236\236" : "")); for (p = world; (p = find_plr(p));) { if (p->k_flag) { continue; // already served } tmp = getteam(p); for (p2 = world; (p2 = find_plr(p2));) { if (p2->k_flag || strneq(tmp, getteam(p2))) { continue; // already served or not on the same team } if (isTeam() || isCTF()) { G_sprint(self, 2, "\220%.4s\221 ", tmp); for (i = strlen(tmp); i < tL; i++) { G_sprint(self, 2, " "); } } G_sprint(self, 2, "%.10s ", p2->netname); // player name for (i = strlen(p2->netname); i < pL; i++) { G_sprint(self, 2, " "); } stats = va( "%d", (!isCTF() ? (int)p2->s.v.frags : (int)(p2->s.v.frags - p2->ps.ctf_points))); G_sprint(self, 2, "%3s", stats); // frags stats = va( "%d", (!isCTF() ? (int)(p2->s.v.frags - p2->deaths) : (int)(p2->s.v.frags - p2->ps.ctf_points - p2->deaths))); G_sprint(self, 2, "%4s ", stats); // rank if (isTeam()) { // friendkills stats = va("%d", (int)p2->friendly); G_sprint(self, 2, "%2s ", stats); } if (isCTF()) { if ((p2->s.v.frags - p2->ps.ctf_points) < 1) { p2->efficiency = 0; } else { p2->efficiency = (p2->s.v.frags - p2->ps.ctf_points) / (p2->s.v.frags - p2->ps.ctf_points + p2->deaths) * 100; } } else { if (p2->s.v.frags < 1) { p2->efficiency = 0; } else { p2->efficiency = p2->s.v.frags / (p2->s.v.frags + p2->deaths) * 100; } } stats = va("%3.1f", p2->efficiency); G_sprint(self, 2, "\217 %5s%%\n", stats); // effi p2->k_flag = 1; // mark as served } } for (p = world; (p = find_plr(p));) { p->k_flag = 0; } } void ToggleQLag(void) { int fpd = iKey(world, "fpd"); if (match_in_progress) { return; } fpd ^= 8; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("QiZmo lag settings"), ((fpd & 8) ? "in effect" : "not in effect")); } void ToggleQEnemy(void) { int fpd = iKey(world, "fpd"); if (match_in_progress) { return; } fpd ^= 32; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("QiZmo enemy reporting"), Allowed(fpd & 32)); } void ToggleQPoint(void) { int fpd = iKey(world, "fpd"); if (match_in_progress) { return; } fpd ^= 128; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("QiZmo pointing"), Enabled(fpd & 128)); } /* new FDP bits https://www.quakeworld.nu/wiki/FPD void ToggleSkinForcing(void) { int fpd = iKey( world, "fpd" ); if ( match_in_progress ) return; fpd ^= 256; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("Skin forcing"), Enabled( !(fpd & 256) )); } void ToggleColorForcing(void) { int fpd = iKey( world, "fpd" ); if ( match_in_progress ) return; fpd ^= 512; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("Color forcing"), Enabled( !(fpd & 512) )); } void TogglePitchSpeedLimit(void) { int fpd = iKey( world, "fpd" ); if ( match_in_progress ) return; fpd ^= 16384; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("Pitch speed limit"), Enabled( fpd & 16384 )); } void ToggleYawSpeedLimit(void) { int fpd = iKey( world, "fpd" ); if ( match_in_progress ) return; fpd ^= 32768; localcmd("serverinfo fpd %d\n", fpd); G_bprint(2, "%s %s\n", redtext("Yaw speed limit"), Enabled( fpd & 32768 )); } */ void ToggleFreeze(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_freeze", redtext("map freeze")); } // qqshka: pointing code stolen from Zquake void ShowNick(void) { gedict_t *p, *bp = NULL; char *s1, *s2, *pups, *kn, buf[256] = { 0 }; char arg_1[32]; float best; vec3_t ang; vec3_t vieworg, entorg; int itms, i, ln, version; if (!match_in_progress) { ; // allow shownick in prewar anyway } else if (!isTeam() && !isCTF()) { return; } trap_CmdArgv(1, arg_1, sizeof(arg_1)); ang[0] = self->s.v.v_angle[0]; ang[1] = self->s.v.v_angle[1]; ang[2] = 0; trap_makevectors(ang); VectorCopy(self->s.v.origin, vieworg); vieworg[2] += 16 /* was 22 */; // adjust for view height best = -1; s1 = getteam(self); for (p = world; (p = find_plr(p));) { vec3_t v, v2, v3; float dist, miss, rank; if (ISDEAD(p)) { continue; // ignore dead } if (p == self) { continue; // ignore self } if (strnull(p->netname)) { continue; // ignore not really players } if (p->s.v.modelindex != modelindex_player) { continue; // ignore non player mdl index (EYES) } s2 = getteam(p); if (!match_in_progress) { ; // allow shownick in prewar anyway } else if (strneq(s1, s2)) { continue; // ignore non teammaters } VectorCopy(p->s.v.origin, entorg); entorg[2] += 30; VectorSubtract(entorg, vieworg, v); dist = DotProduct(v, g_globalvars.v_forward); if (dist < 10) { continue; } VectorScale(g_globalvars.v_forward, dist, v2); VectorSubtract(v2, v, v3); miss = VectorLength(v3); if (miss > 300) { continue; } if (miss > (dist * 1.7)) { continue; // over 60 degrees off } if (dist < (3000.0 / 8.0)) { rank = miss * (dist * 8.0 * 0.0002f + 0.3f); } else { rank = miss; } if ((rank < best) || (best < 0)) { // check if we can actually see the object vec3_t end; float radius; radius = 27; if ((int)p->s.v.effects & (EF_DIMLIGHT | EF_BRIGHTLIGHT | EF_BLUE | EF_RED | EF_GREEN)) { radius = 200; } if (dist <= radius) { goto ok; } VectorSubtract(vieworg, entorg, v); VectorNormalize(v); VectorMA(entorg, radius, v, end); traceline(PASSVEC3(vieworg), PASSVEC3(end), true, self); if (g_globalvars.trace_fraction == 1) { goto ok; } VectorMA(entorg, radius, g_globalvars.v_right, end); VectorSubtract(vieworg, end, v); VectorNormalize(v); VectorMA(end, radius, v, end); traceline(PASSVEC3(vieworg), PASSVEC3(end), true, self); if (g_globalvars.trace_fraction == 1) { goto ok; } VectorMA(entorg, -radius, g_globalvars.v_right, end); VectorSubtract(vieworg, end, v); VectorNormalize(v); VectorMA(end, radius, v, end); traceline(PASSVEC3(vieworg), PASSVEC3(end), true, self); if (g_globalvars.trace_fraction == 1) { goto ok; } VectorMA(entorg, radius, g_globalvars.v_up, end); VectorSubtract(vieworg, end, v); VectorNormalize(v); VectorMA(end, radius, v, end); traceline(PASSVEC3(vieworg), PASSVEC3(end), true, self); if (g_globalvars.trace_fraction == 1) { goto ok; } // use half the radius, otherwise it's possible to see // through floor in some places VectorMA(entorg, -radius / 2, g_globalvars.v_up, end); VectorSubtract(vieworg, end, v); VectorNormalize(v); VectorMA(end, radius, v, end); traceline(PASSVEC3(vieworg), PASSVEC3(end), true, self); if (g_globalvars.trace_fraction == 1) { goto ok; } continue; // not visible ok: best = rank; bp = p; } } if ((best < 0) || !bp) { return; } version = atoi(arg_1); version = bound(0, version, 1); switch (version) { case 1: { int h, a, shells, nails, rockets, cells; if (strnull(kn = ezinfokey(bp, "k_nick"))) // get nick, if any, do not send name, client can guess it too { kn = ezinfokey(bp, "k"); } if (kn[0] && kn[1] && kn[2] && kn[3]) { kn[4] = 0; // truncate nick to 4 symbols } i = NUM_FOR_EDICT(bp) - 1; h = bound(0, (int)bp->s.v.health, 999); a = bound(0, (int)bp->s.v.armorvalue, 999); shells = bound(0, (int)bp->s.v.ammo_shells, 999); nails = bound(0, (int)bp->s.v.ammo_nails, 999); rockets = bound(0, (int)bp->s.v.ammo_rockets, 999); cells = bound(0, (int)bp->s.v.ammo_cells, 999); stuffcmd(self, "//sn %d %d %d %d %d %d %d %d \"%s\" %d %d %d %d\n", version, i, (int)bp->s.v.origin[0], (int)bp->s.v.origin[1], (int)bp->s.v.origin[2], h, a, (int)bp->s.v.items, kn, shells, nails, rockets, cells); return; } } itms = (int)bp->s.v.items; pups = ""; if (bp->invincible_finished >= g_globalvars.time) { pups = va("%s\220%s\221", (*pups ? va("%s ", pups) : ""), redtext("Pent")); } if (bp->super_damage_finished > g_globalvars.time) { pups = va("%s\220%s\221", (*pups ? va("%s ", pups) : ""), redtext("Quad")); } if (bp->radsuit_finished > g_globalvars.time) { pups = va("%s\220%s\221", (*pups ? va("%s ", pups) : ""), redtext("Suit")); } if (*pups) { pups = va("%s\n", pups); } if ((int)bp->s.v.armorvalue) { s1 = va("%s:%d ", redtext(armor_type(itms)), (int)bp->s.v.armorvalue); } else { s1 = ""; } s2 = ""; if ((itms & IT_RL_AND_LG) == IT_RL_AND_LG) { s2 = va(" %s:%d %s:%d", redtext("rl"), (int)bp->s.v.ammo_rockets, redtext("lg"), (int)bp->s.v.ammo_cells); } else if (itms & IT_ROCKET_LAUNCHER) { s2 = va(" %s:%d", redtext("rl"), (int)bp->s.v.ammo_rockets); } else if (itms & IT_LIGHTNING) { s2 = va(" %s:%d", redtext("lg"), (int)bp->s.v.ammo_cells); } else if (itms & IT_GRENADE_LAUNCHER) { s2 = va(" %s:%d", redtext("gl"), (int)bp->s.v.ammo_rockets); } else if (itms & IT_SUPER_NAILGUN) { s2 = va(" %s:%d", redtext("sng"), (int)bp->s.v.ammo_nails); } else if (itms & IT_SUPER_SHOTGUN) { s2 = va(" %s:%d", redtext("ssg"), (int)bp->s.v.ammo_shells); } else if (itms & IT_NAILGUN) { s2 = va(" %s:%d", redtext("ng"), (int)bp->s.v.ammo_nails); } else if (itms & IT_SHOTGUN) { s2 = va(" %s:%d", redtext("sg"), (int)bp->s.v.ammo_shells); } else if (itms & IT_AXE) { s2 = redtext(" axe!"); // just in case :] } kn = ezinfokey(bp, "k_nick"); if (strnull(kn)) { kn = ezinfokey(bp, "k"); } if (strnull(kn)) { kn = bp->netname; } ln = iKey(self, "ln"); ln = (iKey(self, "ktpl") ? abs(ln + 2) : ln); // NOTE: ktpro does't allow negative "ln", muhaha if ((i = ln) > 0) { i = bound(0, i, sizeof(buf) - 1); memset((void*) buf, (int)'\n', i); buf[i] = 0; } if (match_in_progress != 2) // simple shownick in prewar { strlcat(buf, va("%s\n", kn), sizeof(buf)); } else { strlcat(buf, va("%s" // if powerups present \n is too "%s%s:%d%s\n" "%s", pups, s1, redtext("h"), (int)bp->s.v.health, s2, kn), sizeof(buf)); } if ((i = ln) < 0) { int offset = strlen(buf); i = bound(0, -i, (int)sizeof(buf) - offset - 1); memset((void*)(buf + offset), (int)'\n', i); buf[i + offset] = 0; } G_centerprint(self, "%s", buf); self->need_clearCP = 1; self->shownick_time = g_globalvars.time + 0.8; // clear centerprint at this time } // qqshka // below predefined settings for usermodes // this settings used when server desire general rules reset: last player disconnects / race toggled / etc. const char _reset_settings[] = "serverinfo matchtag \"\"\n" // Hint for QTV what type of event it is. Like: "EQL semifinal" etc. "k_teamoverlay 0\n" // Teamoverlay off ; // common settings for all user modes const char common_um_init[] = "k_pow_pickup 0\n" "sv_loadentfiles_dir \"\"\n" "sv_antilag 2\n" // antilag on "k_bloodfest 0\n" "k_killquad 0\n" "pm_airstep \"\"\n" // airstep off by default "samelevel 1\n" // change levels off "maxclients 8\n" // maxclients "k_yawnmode 0\n" // disable SHITMODE by default (c)Renzo "k_instagib 0\n" // instagib off "k_cg_kb 1\n" // coilgun kickback in instagib "k_disallow_weapons 16\n" // disallow gl in dmm4 by default "floodprot 10 1 1\n" // 10 messages in 1 seconds, 1 second silence "k_fp 1\n" // floodprot for players "k_fp_spec 1\n" // floodprot for specs "dmm4_invinc_time \"\"\n" // reset to default "k_noitems \"\"\n" // reset to default "k_clan_arena 0\n" // disable Clan Arena by default "k_rocketarena 0\n" // disable Rocket Arena by default "k_race 0\n" // disable Race by default "k_hoonymode 0\n" // disable HoonyMode by default "k_freshteams 0\n" // disable FreshTeams by default "k_nosweep 0\n" // disable nosweep by default "k_spec_info 1\n" // allow spectators receive took info during game "k_midair 0\n" // midair off LGCMODE_VARIABLE " 0\n" // LGC mode off TOT_MODE_VARIABLE " 0\n" // ToT mode off "fraglimit 0\n" // fraglimit %) "dp 1\n" // drop pack "dq 0\n" // drop quad "dr 0\n" // drop ring "k_frp 0\n" // fairpacks "k_spectalk 0\n" // silence "k_dis 1\n" // discharge on "k_spw 4\n" // affect spawn type "k_dmgfrags 0\n" // damage frags off "k_dmm4_gren_mode 0\n" // dmm4 grenade mode off "k_tp_tele_death 1\n" // affect frags on team telefrags or not "k_allowcountchange 1\n" // permissions for upplayers, only real admins "k_maxspectators 4\n" // some default value "k_ip_list 1\n" // permissions for iplist, only real admins "k_idletime 0\n" // idlebot "k_membercount 0\n" // some unlimited values "k_lockmin 0\n" // some unlimited values "k_lockmax 64\n" // some unlimited values "k_lockmode 1\n" // server lockmode "k_pow_q 1\n" // powerups - quad "k_pow_p 1\n" // powerups - pent "k_pow_r 1\n" // powerups - ring "k_pow_s 1\n" // powerups - suit "qtv_sayenabled 0\n" // default blocking of qtv chat "k_bzk 0\n" // berzerk mode off ; const char _1on1_um_init[] = "coop 0\n" // no coop "maxclients 2\n" // duel = two players "k_maxclients 2\n" // duel = two players "timelimit 10\n" // 10 minute rounds "teamplay 0\n" // hurt yourself, no teammates here "deathmatch 3\n" // weapons stay "k_overtime 1\n" // overtime type = time based "k_exttime 3\n" // overtime 3mins "k_pow 0\n" // powerups "k_membercount 0\n" // no efect in duel "k_lockmin 0\n" // no efect in duel "k_lockmax 0\n" // no efect in duel "k_mode 1\n" ; const char _1on1hm_um_init[] = "coop 0\n" // no coop "maxclients 2\n" // duel = two players "k_maxclients 2\n" // duel = two players "fraglimit 1\n" // hoonymode - every 1 frag we toggle spawns "timelimit 0\n" // hoonymode - timelimit 0 "k_hoonymode 1\n" // "k_hoonyrounds 12\n" // first to seven "teamplay 0\n" // hurt yourself, no teammates here "deathmatch 3\n" // weapons stay "k_overtime 1\n" // overtime type = time based "k_exttime 3\n" // overtime 3mins "k_pow 0\n" // powerups "k_membercount 0\n" // no efect in duel "k_lockmin 0\n" // no efect in duel "k_lockmax 0\n" // no efect in duel "k_mode 1\n" ; // 'blitz' now const char _2on2hm_um_init[] = "coop 0\n" // no coop "maxclients 4\n" // 2on2 = 4 players "k_maxclients 4\n" // 2on2 = 4 players "timelimit 3\n" // 3 minute rounds "k_hoonyrounds 4\n" // 4 rounds (2 sets of spawns) "fraglimit 0\n" // hoonymode - no fraglimit, time-based "k_hoonymode 1\n" // "teamplay 2\n" // hurt teammates and yourself "deathmatch 3\n" // weapons stay "k_overtime 0\n" // time based "k_exttime 3\n" // overtime 3mins "k_pow 1\n" // use powerups "k_membercount 1\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_mode 2\n" ; const char _2on2_um_init[] = "coop 0\n" // no coop "maxclients 4\n" // 2on2 = 4 players "k_maxclients 4\n" // 2on2 = 4 players "timelimit 10\n" // 10 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 3\n" // weapons stay "k_overtime 1\n" // time based "k_exttime 3\n" // overtime 3mins "k_pow 1\n" // use powerups "k_membercount 1\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_mode 2\n" ; const char _2on2on2_um_init[] = "coop 0\n" // no coop "maxclients 6\n" // 2on2on2 = 6 players "k_maxclients 6\n" // 2on2on2 = 6 players "timelimit 10\n" // 10 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 3\n" // weapons stay "k_overtime 1\n" // time based "k_exttime 3\n" // overtime 3mins "k_pow 1\n" // use powerups "k_membercount 1\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 3\n" // maximum number of teams "k_mode 2\n" ; const char _3on3_um_init[] = "coop 0\n" // no coop "maxclients 6\n" // 3on3 = 6 players "k_maxclients 6\n" // 3on3 = 6 players "timelimit 15\n" // 15 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_pow 1\n" // use powerups "k_membercount 2\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char _3on3on3_um_init[] = "coop 0\n" // no coop "maxclients 9\n" // 3on3on3 = 9 players "k_maxclients 9\n" // 3on3on3 = 9 players "timelimit 15\n" // 15 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_pow 1\n" // use powerups "k_membercount 2\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 3\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; // 'blitz' now const char _4on4hm_um_init[] = "coop 0\n" // no coop "maxclients 8\n" // 4on4 = 8 players "k_maxclients 8\n" // 4on4 = 8 players "timelimit 5\n" // 5 minute rounds "k_hoonyrounds 4\n" // 4 rounds (2 sets of spawns) "fraglimit 0\n" // no fraglimit, time-based "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_hoonymode 1\n" "k_pow 1\n" // use powerups "k_membercount 3\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char _4on4_um_init[] = "coop 0\n" // no coop "maxclients 8\n" // 4on4 = 8 players "k_maxclients 8\n" // 4on4 = 8 players "timelimit 20\n" // 20 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_pow 1\n" // use powerups "k_membercount 3\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char _4on4on4_um_init[] = "coop 0\n" // no coop "maxclients 12\n" // 4on4on4 = 12 players "k_maxclients 12\n" // 4on4on4 = 12 players "timelimit 20\n" // 20 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_pow 1\n" // use powerups "k_membercount 3\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 3\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char _10on10_um_init[] = "coop 0\n" // no coop "maxclients 20\n" // 10on10 = 20 players "k_maxclients 20\n" // 10on10 = 20 players "timelimit 20\n" // 20 minute rounds "teamplay 2\n" // hurt yourself and teammates "deathmatch 1\n" // wpons dowont stay on pickup "k_pow 1\n" // user powerups "k_membercount 5\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char _XonX_um_init[] = "coop 0\n" // no coop "maxclients 32\n" // allow up to 32 players "k_maxclients 32\n" // allow up to 32 players "timelimit 20\n" // 20 minute rounds "teamplay 2\n" // hurt teammates and yourself "deathmatch 1\n" // weapons wont stay on pickup "k_pow 1\n" // use powerups "k_membercount 1\n" // minimum number of players in each team "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 2\n" ; const char ffa_um_init[] = // "coop 0\n" // NO WE CAN'T DO IT SO, FFA MATCHLESS USED IN COOP MODE "maxclients 26\n" // some limit "k_maxclients 26\n" // some limit "timelimit 20\n" // some limit "teamplay 0\n" // hurt yourself, no teammates "deathmatch 3\n" // weapons stay "dq 1\n" // drop quad "dr 1\n" // drop ring "k_pow 1\n" // use powerups "k_membercount 0\n" // no effect in ffa "k_lockmin 0\n" // no effect in ffa "k_lockmax 0\n" // no effect in ffa "k_overtime 1\n" // time based "k_exttime 5\n" // overtime 5mins "k_mode 3\n" "k_bzk 0\n" // berzerk mode on ;) ; const char ctf_um_init[] = "sv_loadentfiles_dir ctf\n" "pm_airstep 1\n" "coop 0\n" "maxclients 16\n" "k_maxclients 16\n" "timelimit 10\n" "teamplay 4\n" "deathmatch 3\n" "k_dis 2\n" // no out of water discharges in ctf "k_pow 1\n" "k_spw 1\n" "k_membercount 0\n" "k_lockmin 1\n" "k_lockmax 2\n" "k_overtime 1\n" "k_exttime 5\n" "k_mode 4\n" "k_ctf_based_spawn 1\n" // team based spawn "k_ctf_hook 0\n" // hook off "k_ctf_runes 0\n" // runes off "k_ctf_ga 1\n" // green armor on ; const char wipeout_um_init[] = "k_clan_arena 2\n" // enable wipeout "k_clan_arena_rounds 9\n" // number of rounds in a series "k_clan_arena_max_respawns 4\n" // number of respawns per round "coop 0\n" // no coop "dp 0\n" // don't drop packs "teamplay 4\n" "deathmatch 5\n" "timelimit 0\n" // no time limit "maxclients 8\n" // no more than 8 players in ca/wipeout "k_maxclients 8\n" // no more than 8 players in ca/wipeout "k_pow 0\n" "k_overtime 0\n" "k_spectalk 1\n" // enable spec talk by default "k_exttime 0\n" // zero overtime length "k_spw 1\n" // KT Safety spawns (important for CA) "k_dmgfrags 1\n" // 1 "frag" for every 100 damage dealt "k_teamoverlay 1\n" // enable teamoverlay by default "k_membercount 1\n" // no minimum team size "k_noitems 1\n" // no items on the map "k_lockmin 1\n" // minimum number of teams "k_lockmax 2\n" // maximum number of teams "k_mode 2\n" ; const char carena_um_init[] = "k_clan_arena 1\n" // enable clan arena "k_clan_arena_rounds 9\n" // number of rounds in a series "k_clan_arena_max_respawns 0\n" // number of respawns per round "dp 0\n" // don't drop packs "teamplay 4\n" "deathmatch 5\n" "timelimit 0\n" // no time limit "maxclients 8\n" // no more than 8 players in ca/wipeout "k_maxclients 8\n" // no more than 8 players in ca/wipeout "k_pow 0\n" "k_overtime 0\n" "k_spectalk 1\n" // enable spec talk by default "k_exttime 0\n" // zero overtime length "k_spw 1\n" // KT Safety spawns (important for CA) "k_dmgfrags 1\n" // 1 "frag" for every 100 damage dealt "k_teamoverlay 1\n" // enable teamoverlay by default "k_membercount 1\n" // no minimum team size "k_noitems 1\n" // no items on the map "coop 0\n" // no coop "k_lockmax 2\n" // maximum number of teams "k_mode 2\n" ; const char tot_um_init[] = "deathmatch 4\n" "dmm4_invinc_time -1\n" "dq 0\n" "dr 0\n" "k_bzk 0\n" "k_disallow_weapons 80\n" "k_exttime 0\n" "k_fb_enabled 1\n" "k_fb_quad_multiplier 8\n" "k_lockmax 0\n" "k_lockmin 0\n" "k_maxclients 9\n" "k_membercount 0\n" "k_mode 3\n" "k_overtime 0\n" "k_pow 1\n" "k_spw 1\n" "k_tot_mode 1\n" "maxclients 9\n" "teamplay 0\n" "timelimit 5\n" ; usermode um_list[] = { { "1on1", "\223 on \223", _1on1_um_init, UM_1ON1, 1 }, { "2on2", "\224 on \224", _2on2_um_init, UM_2ON2, 2 }, { "3on3", "\225 on \225", _3on3_um_init, UM_3ON3, 3 }, { "4on4", "\226 on \226", _4on4_um_init, UM_4ON4, 4 }, { "10on10", "\223\222 on \223\222", _10on10_um_init, UM_10ON10, 10 }, { "ffa", "ffa", ffa_um_init, UM_FFA, -1 }, { "ctf", "ctf", ctf_um_init, UM_CTF, 0 }, { "hoonymode", "HoonyMode", _1on1hm_um_init, UM_1ON1HM, 0 }, { "blitz2v2", "Blitz (2v2)", _2on2hm_um_init, UM_1ON1HM, 0 }, { "blitz4v4", "Blitz (4v4)", _4on4hm_um_init, UM_1ON1HM, 0 }, { "2on2on2", "\224 on \224 on \224", _2on2on2_um_init, UM_2ON2ON2, 0 }, { "3on3on3", "\225 on \225 on \225", _3on3on3_um_init, UM_3ON3ON3, 0 }, { "4on4on4", "\226 on \226 on \226", _4on4on4_um_init, UM_4ON4ON4, 0 }, { "XonX", "X on X", _XonX_um_init, UM_XONX, 0 }, { "wipeout", "Wipeout", wipeout_um_init, UM_4ON4, 0 }, { "ca", "Clan Arena", carena_um_init, UM_4ON4, 0 }, { "tot", "Tribe of Tjernobyl", tot_um_init, UM_FFA, 0 }, }; int um_cnt = sizeof(um_list) / sizeof(um_list[0]); UserModes_t current_umode; // return -1 if not found int um_idx_byname(char *name) { int i; if (strnull(name)) { return -1; // not found } for (i = 0; i < um_cnt; i++) { if (streq(name, um_list[i].name)) { return i; } } return -1; // not found } // Returns the name of a UserMode const char *um_name_byidx(UserModes_t umode) { if ((umode >= 0) && (umode < um_cnt)) { return um_list[umode].name; } else { return NULL; } } extern int skip_fixrules; void UserMode_SetMatchTag(char *matchtag) { char matchtag_old[20] = { 0 }, matchtag_new[20] = { 0 }; // get current serverinfo matchtag. infokey(world, "matchtag", matchtag_old, sizeof(matchtag_old)); // set new matchtag. localcmd("serverinfo matchtag \"%s\"\n", clean_string(matchtag)); trap_executecmd(); // <- this really needed // check what we get in serverinfo after all. infokey(world, "matchtag", matchtag_new, sizeof(matchtag_new)); if (matchtag_new[0]) { G_bprint(2, "\n" "%s is %s\n", redtext("matchtag"), matchtag_new); } else if (matchtag_old[0]) { G_bprint(2, "\n" "%s %s\n", redtext("matchtag"), redtext("disabled")); } else { G_bprint(2, "\n" "%s not set\n", redtext("matchtag")); } } // for user call this like UserMode( 1 ) // for server call like UserMode( -1 ) void UserMode(float umode) { char matchtag[20] = { 0 }; const char *um; char buf[1024 * 4]; char *cfg_name; qbool sv_invoked = false; int k_free_mode = (k_matchLess ? 5 : cvar("k_free_mode")); current_umode = umUnknown; if (umode < 0) { sv_invoked = true; umode *= -1; } else { if (world->hoony_timelimit || !strnull(world->hoony_defaultwinner)) { G_sprint(self, 2, "This map is designed for hoonymode only\n"); return; } if (cvar("k_auto_xonx")) { G_sprint(self, 2, "Command blocked due to k_auto_xonx\n"); return; } } umode = (int)umode - 1; if ((umode < 0) || (umode >= um_cnt)) { G_bprint(2, "UserMode: unknown mode\n"); return; } // get user supplied matchtag if any. trap_CmdArgs(matchtag, sizeof(matchtag)); um = um_list[(int)umode].name; if (isRACE()) { if (!sv_invoked) { race_switch_usermode(um, um_list[(int)umode].race_plrs_per_team); } return; } if (!k_matchLess) // allow for matchless mode { if (!is_rules_change_allowed()) { return; } } if (streq(um, "ffa") && k_matchLess && cvar("k_use_matchless_dir")) { um = "matchless"; // use configs/usermodes/matchless instead of configs/usermodes/ffa in matchless mode } if (streq(um, "ctf") && bots_enabled() && !sv_invoked) { if (bots_enabled()) { G_sprint(self, PRINT_HIGH, "Disable bots first with %s\n", redtext("/botcmd disable")); return; } } //for 1on1 / 2on2 / 4on4 and ffa commands manipulation //0 - no one, 1 - admins, 2 elected admins too //3 - only real real judges, 4 - elected judges too //5 - all players // hmm, I didn't understand how k_free_mode affect this command, // so implement how i think this must be, it is like some sort of access control if (sv_invoked) { if (k_free_mode != 5) { G_bprint(2, "UserMode: sv %s discarded due to k_free_mode\n", um); return; } } else if (!check_perm(self, k_free_mode)) { return; } // ok u have access, but is this command really allowed at all? if (!(um_list[(int)umode].um_flags & k_allowed_free_modes)) { if (sv_invoked) { G_bprint(2, "UserMode: sv %s discarded due to k_allowed_free_modes\n", um); } else { G_sprint(self, 2, "Server %s this command\n", redtext("disallows")); } return; } #ifdef CTF_RELOADMAP if ((!isCTF() && (um_list[(int)umode].um_flags & UM_CTF)) || (isCTF() && !(um_list[(int)umode].um_flags & UM_CTF))) { skip_fixrules = 2; // skip FixRules for 2 frames, or we get some teamplay warning } #else // We invoke ctf command. // So we need check ready players, and if they have wrong teams, discard ctf command // untill they type break or fix team names. // After ctf mode activated no one can have wrong team and be ready at the same time. if (!isCTF() && (um_list[(int)umode].um_flags & UM_CTF)) { gedict_t *p; for (p = world; (p = find_plr(p));) { if (p->ready && (!streq(getteam(p), "blue") && !streq(getteam(p), "red"))) { if (sv_invoked) { G_bprint(2, "UserMode: sv %s discarded due to ready players have not red or blue team\n", um); } else { G_sprint(self, 2, "command discarded due to ready players have not red or blue team\n" "either force they fix team or be not ready\n" ); } return; } } } #endif if (!k_matchLess) { // do not show for matchless mode if (sv_invoked) { G_bprint(2, "%s %s\n", redtext(va("%s", um_list[(int)umode].displayname)), redtext("settings enabled")); } else { G_bprint(2, "%s %s %s\n", redtext(va("%s", um_list[(int)umode].displayname)), redtext("settings enabled by"), self->netname); } } trap_readcmd(common_um_init, buf, sizeof(buf)); G_cprint("%s", buf); trap_readcmd(um_list[(int)umode].initstring, buf, sizeof(buf)); G_cprint("%s", buf); cfg_name = "configs/usermodes/default.cfg"; if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/%s/default.cfg", um); // If CTF matchless mode, load config from /matchless/ctf.cfg instead of /matchless/default.cfg // isCTF() and k_mode aren't reliable to use here, so define "k_use_matchless_dir 2" for this purpose if (streq(um, "matchless") && (cvar("k_use_matchless_dir") == 2)) { cfg_name = va("configs/usermodes/%s/ctf.cfg", um); } if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/%s.cfg", mapname); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/%s/%s.cfg", um, mapname); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } HM_unpick_all_spawns(); G_cprint("\n"); // apply matchtag if not executed by server. if (!sv_invoked) { UserMode_SetMatchTag(matchtag); } cvar_fset("_k_last_xonx", umode + 1); // save last XonX command current_umode = umode+1; } void execute_rules_reset(void) { char *cfg_name = "configs/reset.cfg"; char buf[1024 * 4]; int um_idx; cvar_fset("_k_last_xonx", 0); // forget last XonX command // execute hardcoded reset settings. trap_readcmd(_reset_settings, buf, sizeof(buf)); G_cprint("%s", buf); if ((is_private_game() != private_game_by_default()) && private_game_voteable()) { private_game_toggle(private_game_by_default()); } // execute configs/reset.cfg. if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } G_cprint("\n"); // execute usermode. if ((um_idx = um_idx_byname(k_matchLess ? "ffa" : cvar_string("k_defmode"))) >= 0) { UserMode(-(um_idx + 1)); // force exec configs for default user mode } } // This routine change map if srv_practice_mode == 0 and 'map' is not NULL, // empty string mean realod to the current map. void SetPractice(int srv_practice_mode, const char *map) { if (match_in_progress) { G_Error("SetPractice: match_in_progress"); } k_practice = srv_practice_mode; cvar_fset("srv_practice_mode", srv_practice_mode); if (k_practice) { G_bprint(2, "%s\n", redtext("Server in practice mode")); } else { G_bprint(2, "%s\n", redtext("Server in normal mode")); if (map) { // If map equal to "" then reload current map in this case. changelevel((strnull(map) ? mapname : map)); } } } void TogglePractice(void) { int lock_practice = cvar("lock_practice"); int allow_toggle_practice = cvar("allow_toggle_practice"); if (match_in_progress) { return; } if ((lock_practice == 2) /* server locked in current practice mode */ || ((lock_practice != 0) && (lock_practice != 1))) /* unknown lock type, ignore command */ { G_sprint(self, 3, "console: command is locked\n"); return; } if (k_force || find(world, FOFCLSN, "idlebot")) { return; // cmon, no practice if forcestart or idlebot active } //0 - no one, 1 - admins, 2 elected admins too //3 - only real real judges, 4 - elected judges too //5 - all players // implement how i think this must be, it is like some sort of access control switch (allow_toggle_practice) { case 0: G_sprint(self, 2, "%s can use this command\n", redtext("no one")); return; case 1: case 2: if (!is_adm(self)) { G_sprint(self, 2, "you must be an %s\n", redtext("admin")); return; } break; case 3: case 4: if (!is_adm(self)) { G_sprint(self, 2, "%s is not implemented in this mode\n", redtext("judges")); G_sprint(self, 2, "you must be an %s\n", redtext("admin")); return; } break; case 5: break; default: G_sprint(self, 2, "server is misconfigured, command %s\n", redtext("skipped")); return; } // ok u have access SetPractice(!k_practice, ""); // reload current map if needed } // allow reset weapon stats in prewar void Wp_Reset(void) { if (match_in_progress) { return; } memset(self->ps.wpn, 0, sizeof(self->ps.wpn)); } void Wp_Stats(float on) { on--; self->wp_stats = (int)on; self->wp_stats_time = g_globalvars.time; // force show/hide } void Sc_Stats(float on) { on--; self->sc_stats = (int)on; self->sc_stats_time = g_globalvars.time; // force show/hide } void W_WeaponFrame(void); void kfjump(void) { int button0 = self->s.v.button0; if (cvar("k_disallow_kfjump")) { G_sprint(self, 2, "%s is disabled\n", redtext("kfjump")); return; } if (g_globalvars.time < self->attack_finished) { return; // sanity } self->s.v.impulse = 7; // select switch to rl self->s.v.button0 = 1; // force attack button self->s.v.v_angle[1] += 180; // turn 180 W_WeaponFrame(); // switch to rl and fire self->s.v.v_angle[1] -= 180; // turn back self->s.v.button0 = button0; // restore button state } void krjump(void) { int button0 = self->s.v.button0; float va_x = self->s.v.v_angle[0]; if (cvar("k_disallow_krjump")) { G_sprint(self, 2, "%s is disabled\n", redtext("krjump")); return; } if (g_globalvars.time < self->attack_finished) { return; // sanity } self->s.v.impulse = 7; // select switch to rl self->s.v.button0 = 1; // force attack button self->s.v.v_angle[0] = 80; // look down much as possible, qw block this at 80 W_WeaponFrame(); // switch to rl and fire self->s.v.v_angle[0] = va_x; // restore self->s.v.button0 = button0; // restore button state } void t_jump(float j_type) { char *jt, *cv_jt, cjt = j_type == 1 ? 'f' : 'r'; if (match_in_progress) { return; } jt = va("k%cjump", cjt); cv_jt = va("k_disallow_k%cjump", cjt); trap_cvar_set_float(cv_jt, !cvar(cv_jt)); G_bprint(2, "%s %s %s\n", self->netname, redtext(Enables(!cvar(cv_jt))), redtext(jt)); } void klist(void) { int i, hdc; gedict_t *p = world; char *track; if (!cvar("k_allowklist") && match_in_progress && self->ct == ctPlayer) { G_sprint(self, 2, "klist is disabled\n"); return; } for (i = 0, p = world; (p = find_plr(p)); i++) { if (!i) { G_sprint(self, 2, "Clients list: %s\n", redtext("players")); G_sprint(self, 2, "%s %s %s %s %s %s\n", redtext("id"), redtext("ad"), redtext("vip"), redtext("hdp"), redtext("team"), redtext("name")); } hdc = GetHandicap(p); G_sprint(self, 2, "%2d|%2s|%3d|%3s|%4.4s|%s\n", GetUserID(p), (is_real_adm(p) ? redtext("A") : is_adm(p) ? redtext("a") : ""), VIP(p), (hdc == 100 ? "off" : va("%d", hdc)), getteam(p), getname(p)); } if (i) { G_sprint(self, 2, "%s %2d found %s\n", redtext("--"), i, redtext("-------------")); } for (i = 0, p = world; (p = find_spc(p)); i++) { if (!i) { G_sprint(self, 2, "Clients list: %s\n", redtext("spectators")); G_sprint(self, 2, "%s %s %s %s %s\n", redtext("id"), redtext("ad"), redtext("vip"), redtext("co"), redtext("name")); } track = TrackWhom(p); G_sprint(self, 2, "%2d|%2s|%3d|%2s|%s%s\n", GetUserID(p), (is_real_adm(p) ? redtext("A") : is_adm(p) ? redtext("a") : ""), VIP(p), (is_coach(p) ? redtext("c") : ""), getname(p), (strnull(track) ? "" : va(" \x8D %s", track))); } if (i) { G_sprint(self, 2, "%s %2d found %s\n", redtext("--"), i, redtext("-------------")); } for (i = 0, p = world; (p = find(p, FOFCLSN, "ghost")); i++) { if (!i) { G_sprint(self, 2, "Clients list: %s\n", redtext("ghosts")); G_sprint(self, 2, "%s %s %s\n", redtext("frags"), redtext("team"), redtext("name")); } G_sprint(self, 2, "%5d|%4.4s|%s\n", (int)p->s.v.frags, getteam(p), getname(p)); } if (i) { G_sprint(self, 2, "%s %2d found %s\n", redtext("--"), i, redtext("-------------")); } for (i = 0, p = world + 1; p <= world + MAX_CLIENTS; p++) { if (streq(track = ezinfokey(p, "*state"), "zombie")) { ; } else if (streq(track, "preconnected") || streq(track, "connected")) { track = "connecting"; } else { continue; // continue due to player spawned(connected) or free or in unknown state } if (!i) { G_sprint(self, 2, "Clients list: %s\n", redtext("unconnected")); G_sprint(self, 2, "%s %s %-10s %s\n", redtext("id"), redtext("vip"), redtext("state"), redtext("name")); } G_sprint(self, 2, "%2d|%3d|%-10.10s|%s\n", iKey(p, "*userid"), // can't use GetUserID here VIP(p), track, (strnull(p->netname) ? "!noname!" : p->netname)); i++; } if (i) { G_sprint(self, 2, "%s %2d found %s\n", redtext("--"), i, redtext("-------------")); } } void toggleklist(void) { int k_allowklist = !cvar("k_allowklist"); if (match_in_progress) { return; } cvar_fset("k_allowklist", k_allowklist); if (k_allowklist) { G_bprint(2, "klist: %s - remember to also toggle tracklist\n", redtext("on")); } else { G_bprint(2, "klist: %s - remember to also toggle tracklist\n", redtext("off")); } } void hdptoggle(void) { if (match_in_progress) { return; } trap_cvar_set_float("k_lock_hdp", !cvar("k_lock_hdp")); G_bprint(2, "%s %s %s\n", self->netname, redtext(Allows(!cvar("k_lock_hdp"))), redtext("handicap")); } void handicap(void) { char arg_2[1024]; qbool k_lgc = cvar(LGCMODE_VARIABLE) != 0; if (k_lgc) { G_sprint(self, 2, "Handicap is not allowed in LGC mode\n"); return; } if (trap_CmdArgc() != 2) { G_sprint(self, 2, "use: /handicap value, value from 50 to 150\n"); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); SetHandicap(self, atoi(arg_2)); } void show_disallowed_weapons(int k_disallow_weapons) { char *dwp = str_noweapon(k_disallow_weapons); G_sprint(self, 2, "weapons disallowed:%s\n", (strnull(dwp) ? redtext(" none") : redtext(dwp))); } void noweapon(void) { char arg_2[1024]; int k_disallow_weapons = (int)cvar("k_disallow_weapons") & DA_WPNS; if (match_in_progress) { if (deathmatch == 4) // match started, show info and return { show_disallowed_weapons(k_disallow_weapons); } return; } if (deathmatch != 4) { G_sprint(self, 2, "command allowed in %s only\n", redtext("dmm4")); return; } if (trap_CmdArgc() == 1) { // no arguments, show info and return show_disallowed_weapons(k_disallow_weapons); return; } // one argument if (trap_CmdArgc() == 2) { char *nwp = NULL; int bit = 0; trap_CmdArgv(1, arg_2, sizeof(arg_2)); if (streq(nwp = "axe", arg_2) || streq("1", arg_2)) { k_disallow_weapons ^= bit = IT_AXE; } else if (streq(nwp = "sg", arg_2) || streq("2", arg_2)) { k_disallow_weapons ^= bit = IT_SHOTGUN; } else if (streq(nwp = "ssg", arg_2) || streq("3", arg_2)) { k_disallow_weapons ^= bit = IT_SUPER_SHOTGUN; } else if (streq(nwp = "ng", arg_2) || streq("4", arg_2)) { k_disallow_weapons ^= bit = IT_NAILGUN; } else if (streq(nwp = "sng", arg_2) || streq("5", arg_2)) { k_disallow_weapons ^= bit = IT_SUPER_NAILGUN; } else if (streq(nwp = "gl", arg_2) || streq("6", arg_2)) { k_disallow_weapons ^= bit = IT_GRENADE_LAUNCHER; } else if (streq(nwp = "rl", arg_2) || streq("7", arg_2)) { k_disallow_weapons ^= bit = IT_ROCKET_LAUNCHER; } else if (streq(nwp = "lg", arg_2) || streq("8", arg_2)) { k_disallow_weapons ^= bit = IT_LIGHTNING; } if (bit) { G_bprint(2, "%s %s %s\n", self->netname, redtext(Allows(!(k_disallow_weapons & bit))), redtext(nwp)); trap_cvar_set_float("k_disallow_weapons", k_disallow_weapons); } else { G_sprint(self, 2, "unknown weapon name %s\n", redtext(arg_2)); } return; } } void no_lg(void) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd noweapon lg\n"); } void no_gl(void) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd noweapon gl\n"); } void tracklist(void) { int i; gedict_t *p; char *track; char *nt = redtext(" not tracking"); if (!cvar("k_allowtracklist") && match_in_progress && self->ct == ctPlayer) { G_sprint(self, 2, "tracklist is disabled\n"); return; } for (i = 0, p = world; (p = find_spc(p)); i++) { if (!i) { G_sprint(self, 2, "%s:\n", redtext("Trackers list")); } track = TrackWhom(p); G_sprint(self, 2, "%15s%s\n", getname(p), (strnull(track) ? nt : va(" \x8D %s", track))); } if (!i) { G_sprint(self, 2, "No spectators present\n"); } } void toggletracklist(void) { int k_allowtracklist = !cvar("k_allowtracklist"); if (match_in_progress) { return; } cvar_fset("k_allowtracklist", k_allowtracklist); if (k_allowtracklist) { G_bprint(2, "tracklist: %s - remember to also toggle klist\n", redtext("on")); } else { G_bprint(2, "tracklist: %s - remember to also toggle klist\n", redtext("off")); } } void fpslist(void) { int i; gedict_t *p; float cur, max, min, avg; for (i = 0, p = world; (p = find_plr(p)); i++) { if (!i) { G_sprint(self, 2, "Players %s list:\n", redtext("FPS")); G_sprint(self, 2, " name:(cur \217 max \217 min \217 avg)\n"); G_sprint(self, 2, "\235\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\237\n"); } cur = p->fCurrentFrameTime ? (1.0f / p->fCurrentFrameTime) : 0; max = p->fLowestFrameTime ? (1.0f / p->fLowestFrameTime) : 0; min = p->fHighestFrameTime ? (1.0f / p->fHighestFrameTime) : 0; avg = p->fFrameCount ? (p->fAverageFrameTime / p->fFrameCount) : 0; avg = avg ? (1.0f / avg) : 0; G_sprint(self, 2, "%13s: %3d \217 %3d \217 %3d \217%5.1f\n", getname(p), Q_rint(cur), Q_rint(max), Q_rint(min), avg); } if (!i) { G_sprint(self, 2, "No players present\n"); } } // This is designed for pickup games and creates totally random teams(ish) void RandomPickup(void) { int votes; if (match_in_progress) { return; } if (k_captains) { G_sprint(self, 2, "No random pickup when captain stuffing\n"); return; } if (k_coaches) { G_sprint(self, 2, "No random pickup when coach stuffing\n"); return; } // Dont need to bother if less than 4 players if (CountPlayers() < 4) { G_sprint(self, 2, "You need at least 4 players to do this.\n"); return; } self->v.rpickup = !self->v.rpickup; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.rpickup ? redtext("votes for rpickup") : redtext(va("withdraws %s rpickup vote", g_his(self)))), ((votes = get_votes_req(OV_RPICKUP, true)) ? va(" (%d)", votes) : "")); vote_check_rpickup(MAX_RPICKUP_RECUSION); } // { spec tracking stuff qbool fav_del_do(gedict_t *s, gedict_t *p, char *prefix); qbool favx_del_do(gedict_t *s, gedict_t *p, char *prefix); // this is called from ClientDisconnect - so disconnected players // removed from spectators favourites void del_from_specs_favourites(gedict_t *rm) { gedict_t *p; for (p = world; (p = find_spc(p));) { fav_del_do(p, rm, "auto: "); favx_del_do(p, rm, "auto: "); } } void fav_add(void) { int fav_num, free_num; gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); int diff = (int)(goal - world); if ((goal->ct != ctPlayer) || (diff < 1) || (diff > MAX_CLIENTS)) { G_sprint(self, 2, "fav_add: you are %s player!\n", redtext("not tracking")); return; } for (free_num = -1, fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) if (self->fav[fav_num] == diff) { G_sprint(self, 2, "fav_add: %s %s added to favourites\n", goal->netname, redtext("already")); return; } else if (free_num < 0 && !self->fav[fav_num]) { // ok - found free slot free_num = fav_num; } fav_num = free_num + 1; if ((fav_num < 1) || (fav_num > MAX_CLIENTS)) { // must not happen G_sprint(self, 2, "fav_add: oops, all slots busy? Can't add.\n"); return; } G_sprint(self, 2, "fav_add: %s added to favourites\n", goal->netname); self->fav[(int)fav_num - 1] = diff; } // s - for whom remove // p - who removed qbool fav_del_do(gedict_t *s, gedict_t *p, char *prefix) { qbool removed = false; int fav_num; if (!s || !p) { return false; } for (fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if (s->fav[fav_num] && ((world + s->fav[fav_num]) == p)) { if (removed == false) // show info one time { G_sprint(s, 2, "%s%s removed from favourites\n", prefix, (strnull(p->netname) ? "-someone-" : p->netname)); } s->fav[fav_num] = 0; removed = true; // does't break, so if this player multiple times in favourites // he will removed anyway, must not happend really } } return removed; } // s - for whom remove // p - who removed qbool favx_del_do(gedict_t *s, gedict_t *p, char *prefix) { qbool removed = false; int fav_num; if (!s || !p) { return false; } for (fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if (s->favx[fav_num] && ((world + s->favx[fav_num]) == p)) { G_sprint(s, 2, "%s%s removed from \220slot %2d\221\n", prefix, (strnull(p->netname) ? "-someone-" : p->netname), fav_num + 1); s->favx[fav_num] = 0; removed = true; // does't break, so if this player multiple times in favourites // he will removed anyway } } return removed; } void fav_del(void) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); int diff = (int)(goal - world); if ((goal->ct != ctPlayer) || (diff < 1) || (diff > MAX_CLIENTS)) { G_sprint(self, 2, "fav_del: you are %s player!\n", redtext("not tracking")); return; } if (fav_del_do(self, goal, "fav_del: ")) { return; } G_sprint(self, 2, "fav_del: %s is %s favourites\n", goal->netname, redtext("not in")); } void fav_all_del(void) { qbool deleted = false; int fav_num; for (fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if (self->fav[fav_num]) { self->fav[fav_num] = 0; deleted = true; } } G_sprint(self, 2, "Favourites list %sdeleted\n", (deleted ? "" : redtext("already "))); } void favx_add(float fav_num) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); int diff = (int)(goal - world); if ((fav_num < 1) || (fav_num > MAX_CLIENTS)) { return; } if ((goal->ct != ctPlayer) || (diff < 1) || (diff > MAX_CLIENTS)) { G_sprint(self, 2, "fav add: you are %s player!\n", redtext("not tracking")); return; } G_sprint(self, 2, "fav add: %s added to \220slot %d\221\n", goal->netname, (int)fav_num); self->favx[(int)fav_num - 1] = diff; } void fav_next(void) { int pl_num, fav_num, first_fav, desired_fav; gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity), *p; int diff = (int)(goal - world); for (fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if (self->fav[fav_num]) { break; } } if (fav_num >= MAX_CLIENTS) { G_sprint(self, 2, "fav_next: favourites list is %s\n", redtext("empty")); return; } desired_fav = -2; first_fav = fav_num; // remember if (!((goal->ct != ctPlayer) || (diff < 1) || (diff > MAX_CLIENTS))) { // ok - tracking player, so if goal in favourites switch to the next favourite, // if goal not in favourites switch to the first favourite for (fav_num = first_fav; fav_num < MAX_CLIENTS; fav_num++) { if ((desired_fav == -2) && (self->fav[fav_num] == diff)) { desired_fav = -1; // found goal in favourites, search now next fav } else if ((desired_fav == -1) && self->fav[fav_num]) { desired_fav = fav_num; // found next fav in favourites break; } } } if (desired_fav >= 0) { fav_num = desired_fav + 1; } else { fav_num = first_fav + 1; } if ((fav_num < 1) || (fav_num > MAX_CLIENTS)) { G_sprint(self, 2, "fav_next: internal error, fav_num %d\n", fav_num); return; // sanity - must not happen } pl_num = self->fav[fav_num - 1]; if ((pl_num < 1) || (pl_num > MAX_CLIENTS)) { G_sprint(self, 2, "fav_next: internal error, slot %d\n", pl_num); return; } p = world + pl_num; if (p->ct != ctPlayer) { G_sprint(self, 2, "fav_next: can't find player\n"); return; } if (PROG_TO_EDICT(self->s.v.goalentity) == p) { G_sprint(self, 2, "fav_next: already observing...\n"); return; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "track %d\n", GetUserID(p)); } void xfav_go(float fav_num) { gedict_t *p; int pl_num; if ((fav_num < 1) || (fav_num > MAX_CLIENTS)) { return; } pl_num = self->favx[(int)fav_num - 1]; if ((pl_num < 1) || (pl_num > MAX_CLIENTS)) { G_sprint(self, 2, "fav go: \220slot %d\221 is not defined\n", (int)fav_num); return; } p = world + pl_num; if (p->ct != ctPlayer) { G_sprint(self, 2, "fav go: \220slot %d\221 can't find player\n", (int)fav_num); return; } if (PROG_TO_EDICT(self->s.v.goalentity) == p) { G_sprint(self, 2, "fav go: already observing...\n"); return; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "track %d\n", GetUserID(p)); } void fav_show(void) { gedict_t *p; qbool first, showed = false; int fav_num, diff; for (first = true, fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if ((diff = self->favx[fav_num])) { p = world + diff; if ((p->ct != ctPlayer) || strnull(p->netname)) { continue; } if (first) { G_sprint(self, 2, "%s \220%s\221 %s:\n", redtext("Favourites"), redtext("slots based"), redtext("list")); first = false; } G_sprint(self, 2, " \220slot %2d\221 \x8D %s\n", fav_num + 1, p->netname); showed = true; } } if (showed) { G_sprint(self, 2, "\n"); } for (first = true, fav_num = 0; fav_num < MAX_CLIENTS; fav_num++) { if ((diff = self->fav[fav_num])) { p = world + diff; if ((p->ct != ctPlayer) || strnull(p->netname)) { continue; } if (first) { G_sprint(self, 2, "%s:\n", redtext("Favourites list")); first = false; } G_sprint(self, 2, " %s\n", p->netname); showed = true; } } if (!showed) { G_sprint(self, 2, "Favourites list %s or nothing to show\n", redtext("empty")); } } // { // this is used for autotrack which saved in demo static gedict_t *autotrack_last = NULL; static gedict_t *autotrack_hint = NULL; static qbool autotrack_update = false; static char *autotrack_reason = ""; // } // relax autotrack attempts static void ResetMVDAutoTrack(gedict_t *p) { autotrack_update = false; autotrack_last = (p && p->ct == ctPlayer) ? p : NULL; autotrack_hint = NULL; autotrack_reason = ""; } void DoMVDAutoTrack(void) { gedict_t *p = NULL; int id; if (!autotrack_update) { return; // autotrack was not requested } if ((autotrack_hint && autotrack_hint->ct == ctPlayer) && ISLIVE(autotrack_hint)) { p = autotrack_hint; // we have hint to whom we should switch } #if 0 // no we don't need it if (!match_in_progress) { ResetMVDAutoTrack(p); return; // we don't need much in prewar } #endif // search best only in case when we do not have hint above "autotrack_hint" if (!p && !(p = get_ed_best1())) { // MEAG: We can fall in here if everyone is dead (e.g. frag-trade in duel)... if we can, // keep tracking current player for now and evaluate again after respawns if (!autotrack_last || (autotrack_last->ct != ctPlayer)) { ResetMVDAutoTrack(NULL); } return; // can't find best } // do not switch instantly autotrack pov after tracked player die, wait a few seconds or untill them respawn if (autotrack_last && (autotrack_last->ct == ctPlayer) && ISDEAD(autotrack_last) && ((g_globalvars.time - autotrack_last->dead_time) < 2)) { // no, we do not reset it, we need repeat autotrack apply after some time... //ResetMVDAutoTrack( p ); return; } if (autotrack_last == p) { ResetMVDAutoTrack(p); return; // already track this player } if ((id = GetUserID(p)) > 0) { // with "properly" haxed server this does't go to player but goes to mvd demo only stuffcmd_flags(p, STUFFCMD_DEMOONLY, "//at_dbg %s\n", autotrack_reason); stuffcmd_flags(p, STUFFCMD_DEMOONLY, "//at %d\n", id); } ResetMVDAutoTrack(p); } // relax ktpro's autotrack static void ResetNormalAutoTrack(gedict_t *cl) { cl->apply_ktpro_autotrack = false; cl->autotrack_hint = NULL; } void DoAutoTrack(void) { gedict_t *p = NULL, *goal; int id; switch (self->autotrack) { case atBest: p = get_ed_best1(); break; // ktx's autotrack case atPow: p = get_ed_bestPow(); break; // powerups autotrack case atKTPRO: { // "ktpro's" autotrack if (self->apply_ktpro_autotrack) { // do not try switch pov to dead player even we have it as hint if (self->autotrack_hint && (self->autotrack_hint->ct == ctPlayer) && ISLIVE(self->autotrack_hint)) { p = self->autotrack_hint; } else { p = get_ed_best1(); } } break; } case atNone: default: { ResetNormalAutoTrack(self); return; // unknow or off so ignore } } if (!p) { ResetNormalAutoTrack(self); return; } goal = PROG_TO_EDICT(self->s.v.goalentity); // do not switch instantly autotrack pov after tracked player die, wait a few seconds or untill them respawn if ((goal->ct == ctPlayer) && ISDEAD(goal) && ((g_globalvars.time - goal->dead_time) < 2)) { // no, we do not reset it here since we need repeat autotrack apply later //ResetNormalAutoTrack( self ); return; } if (goal == p) { ResetNormalAutoTrack(self); return; // already track this player } if ((id = GetUserID(p)) > 0) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "track %d\n", id); } ResetNormalAutoTrack(self); } void AutoTrack(float autoTrackType) { autoTrackType_t at = self->autotrack; // save auto track type before turn off or switch to other type char *at_txt; if ((autoTrackType == self->autotrack) || (autoTrackType == atNone)) { self->autotrack = atNone; // turn off } else { self->autotrack = at = autoTrackType; // switch auto track type } self->apply_ktpro_autotrack = (self->autotrack == atKTPRO); // select some first best pov if we use ktpro's autotrack too SetUserInfo(self, "*at", va("%d", self->autotrack), SETUSERINFO_STAR); // so we can restore it on level change switch (at) { case atBest: at_txt = "Autotrack_ktx"; break; // ktx's autotrack case atPow: at_txt = "Auto_pow"; break; // powerups autotrack case atKTPRO: at_txt = "Autotrack"; break; // "ktpro's" autotrack case atNone: default: at_txt = "AutoUNKNOWN"; } G_sprint(self, 2, "%s %s\n", redtext(at_txt), OnOff(self->autotrack)); } void AutoTrackRestore(void) { autoTrackType_t at = iKey(self, "*at"); if (self->ct == ctPlayer) { return; } if ((at != atNone) && (at != self->autotrack)) { AutoTrack(at); } } // >> start ktpro compatible autotrack // When issueing this command, KTeams Pro will switch the view to the next_best // player. The view will then automtically switch to the next_best player when // one of the following events occurs: // 1. the first rl in the game is taken // 2. the player currently being observed dies // 3. any player takes a powerup // 4. when the currently observed player has a powerup which runs out and he has // neither the rocket launcher nor the lightning gun // will force spec who used ktpro autotrack switch track static void ktpro_autotrack_mark_spec(gedict_t *spec, gedict_t *dude) { if (spec->autotrack == atKTPRO) { spec->apply_ktpro_autotrack = true; // this will be used in DoAutoTrack( ) spec->autotrack_hint = dude; // in some cases dude == NULL, its OK } } // will force specs who used ktpro autotrack switch track static void ktpro_autotrack_mark_all(char *reason, gedict_t *dude) { gedict_t *p; autotrack_update = true; // this is for mvd autotrack autotrack_hint = dude; // in some cases dude == NULL, its OK autotrack_reason = reason; for (p = world; (p = find_spc(p));) { ktpro_autotrack_mark_spec(p, dude); } } // first rl was taken, mark specs to switch pov to best player, that may be not even this rl dude :P void ktpro_autotrack_on_first_rl(gedict_t *dude) { ktpro_autotrack_mark_all("first_rl", /*dude*/NULL); // can't use dued, this may overwrite pent or quad } // player just died, switch pov to other if spec track this player and used ktpro's autotrack void ktpro_autotrack_on_death(gedict_t *dude) { gedict_t *p; int goal = EDICT_TO_PROG(dude); // so we can compare with ->s.v.goal if (dude == autotrack_last) { autotrack_update = true; // this is for mvd autotrack autotrack_hint = NULL; // yeah, we have no idea whom will be tracked autotrack_reason = "death"; } for (p = world; (p = find_spc(p));) { if (p->s.v.goalentity == goal) { ktpro_autotrack_mark_spec(p, NULL); } } } // change pov to someone who most close to powerup, right before powerup spawned, atm it 2 seconds. // players which too far to powerup not counted. void ktpro_autotrack_on_powerup_predict(gedict_t *dude) { gedict_t *p = get_ed_bestPow(); // do not allow powerup predict if there still some powruped player running around, // we apply it to quad and pent only, ring and suit are ignored if (p) { if (p->invincible_finished || p->super_damage_finished) { return; } } ktpro_autotrack_mark_all("powerup_predict", dude); } // some powerup taken, mark specs to switch pov to best player, that may be not even this poweruped dude :P void ktpro_autotrack_on_powerup_take(gedict_t *dude) { ktpro_autotrack_mark_all("powerup_take", /*dude*/NULL); // we can't use "dude", since quad may overwrite pent } // some powerup out, and he has neither the rocket launcher nor the lightning gun, mark specs to switch pov to best player void ktpro_autotrack_on_powerup_out(gedict_t *dude) { /* qqshka: I turned this out, because sassa think its correct, lets test it... gedict_t *p; int goal = EDICT_TO_PROG( dude ); // so we can compare with ->s.v.goal if ( ((int)dude->s.v.items & IT_ROCKET_LAUNCHER) || ((int)dude->s.v.items & IT_LIGHTNING) ) return; // dude have weapon, continue track him, may be add check for ammo? if (dude == autotrack_last) { autotrack_update = true; // this is for mvd autotrack autotrack_hint = NULL; // yeah, we have no idea whom will be tracked autotrack_reason = "powerup_out"; } for ( p = world; (p = find_spc( p )); ) if ( p->s.v.goalentity == goal ) ktpro_autotrack_mark_spec( p, NULL ); */ } // change pov to racer void ktpro_autotrack_on_race_status_changed(void) { ktpro_autotrack_mark_all("race_status_changed", NULL); } void ktpro_autotrack_predict_powerup(void) { extern float visible(gedict_t *targ); gedict_t *p, *best; float len, best_len; vec3_t org; if ((self->s.v.items != IT_QUAD) && (self->s.v.items != IT_INVULNERABILITY)) { return; // we use this function for quad and pent only, ring and suit is not interesting for us } best = NULL; best_len = 10e+32; for (p = world; (p = find_plr(p));) { if (ISDEAD(p)) { continue; // we are not interested in dead players } VectorSubtract(p->s.v.origin, self->s.v.origin, org); len = vlen(org); if (len > 500) { // G_bprint(2, "too far %f\n", len); continue;// player too far from this powerup } if (len >= best_len) { continue; // not interesting, we alredy have someone with similar closeness to powerup } if (!visible(p)) { // G_bprint(2, "not visible\n"); continue;// powerup not visible for this player } best = p; } if (!best) { return; // noone was found } ktpro_autotrack_on_powerup_predict(best); } // << end ktpro compatible autotrack void next_best(void) { gedict_t *b1 = get_ed_best1(), *b2 = get_ed_best2(); gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity), *to; int id; if (!b1) { G_sprint(self, 2, "%s: can't do this now\n", redtext("next_best")); return; } b2 = b2 ? b2 : b1; to = b1; if (goal == b1) { to = b2; } else if (goal == b2) { to = b1; } if ((id = GetUserID(to)) > 0) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "track %d\n", id); } } void next_pow(void) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity), *to, *first, *p; qbool nextBreak = false; int id; to = first = NULL; for (p = world; (p = find_plr(p));) { if (ISDEAD(p)) { continue; } if (!((p->invincible_finished >= g_globalvars.time) || (p->super_damage_finished >= g_globalvars.time) || (p->invisible_finished >= g_globalvars.time) || (p->radsuit_finished >= g_globalvars.time))) { continue; } if (nextBreak) { to = p; break; } if (!first) { first = p; } if (goal == p) { nextBreak = true; continue; } } to = to ? to : first; if (!to) { G_sprint(self, 2, "%s: can't find poweruped player\n", redtext("next_pow")); return; } if ((id = GetUserID(to)) > 0) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "track %d\n", id); } } // } spec tracking stuff //================================================ // pos_show/pos_save/pos_move/pos_set_* commands { //================================================ // common functions #define Pos_Disallowed() (match_in_progress || intermission_running || cvar( "sv_paused" ) || (isRACE() && race.status)) // parse pos_show/pos_save/pos_move int Pos_Get_idx(void) { char arg_2[1024]; if (trap_CmdArgc() == 2) { trap_CmdArgv(1, arg_2, sizeof(arg_2)); return bound(0, atoi(arg_2) - 1, MAX_POSITIONS - 1); } return 0; } // Show functions void Pos_Show(void) { int idx; pos_t *pos; pos = &(self->pos[idx = Pos_Get_idx()]); G_sprint(self, 2, "Position: %d\n", idx + 1); G_sprint(self, 2, "velocity: %9.2f %9.2f %9.2f\n", PASSVEC3(pos->velocity)); G_sprint(self, 2, " origin: %9.2f %9.2f %9.2f\n", PASSVEC3(pos->origin)); G_sprint(self, 2, " v_angle: %9.2f %9.2f %9.2f\n", PASSVEC3(pos->v_angle)); G_sprint(self, 2, " Self:\n"); G_sprint(self, 2, "velocity: %9.2f %9.2f %9.2f\n", PASSVEC3(self->s.v.velocity)); G_sprint(self, 2, " origin: %9.2f %9.2f %9.2f\n", PASSVEC3(self->s.v.origin)); G_sprint(self, 2, " v_angle: %9.2f %9.2f %9.2f\n", PASSVEC3(self->s.v.v_angle)); } // Save #define Pos_Save_origin(pos) VectorCopy(self->s.v.origin, (pos)->origin) #define Pos_Save_angles(pos) VectorCopy(self->s.v.v_angle, (pos)->v_angle) #define Pos_Save_velocity(pos) VectorCopy(self->s.v.velocity, (pos)->velocity) // pos_save void Pos_Save(void) { int idx; pos_t *pos; if (Pos_Disallowed()) { return; } pos = &(self->pos[idx = Pos_Get_idx()]); Pos_Save_origin(pos); Pos_Save_angles(pos); Pos_Save_velocity(pos); G_sprint(self, 2, "Position %d was saved\n", idx + 1); } // Move & Set functions qbool Pos_Set_origin(pos_t *pos) { gedict_t *p; if (VectorCompare(pos->origin, VEC_ORIGIN)) { G_sprint(self, 2, "Save your position first\n"); return true; } if (VectorCompare(pos->origin, self->s.v.origin)) { return true; } if (self->ct == ctPlayer) { TraceCapsule(PASSVEC3(pos->origin), PASSVEC3(pos->origin), false, self, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); p = PROG_TO_EDICT(g_globalvars.trace_ent); if (g_globalvars.trace_startsolid || ((p != self) && (p != world) && ((p->s.v.solid == SOLID_BSP) || (p->s.v.solid == SOLID_SLIDEBOX)))) { G_sprint(self, 2, "Can't move, location occupied\n"); return true; } } setorigin(self, PASSVEC3(pos->origin)); // u can't just copy, use setorigin return false; } #define Pos_Set_angles(pos) { \ VectorCopy((pos)->v_angle, self->s.v.angles); \ VectorCopy((pos)->v_angle, self->s.v.v_angle); \ self->s.v.fixangle = true; \ } #define Pos_Set_velocity(pos) VectorCopy((pos)->velocity, self->s.v.velocity) // pos_move void Pos_Move(void) { int idx; pos_t *pos; if (Pos_Disallowed()) { return; } if (self->pos_move_time && ((self->pos_move_time + 1) > g_globalvars.time)) { G_sprint(self, 2, "Only one move per second allowed\n"); return; } self->pos_move_time = g_globalvars.time; pos = &(self->pos[idx = Pos_Get_idx()]); if (Pos_Set_origin(pos)) { return; } Pos_Set_angles(pos); Pos_Set_velocity(pos); G_sprint(self, 2, "Position %d was restored\n", idx + 1); } // parse arguments for pos_set_* void Pos_Parse_Set(vec3_t *x) { char arg[1024]; int i; for (i = 0; i < 3; ++i) { trap_CmdArgv(i + 1, arg, sizeof(arg)); if (strneq(arg, "*")) { (*x)[i] = atof(arg); } } } // pos_set_origin/pos_set_angles/pos_set_velocity void Pos_Set(float set_type) { // VVD: For trick chiters! :-) // Need to think out how to limit using Pos_Set for tricking. // May be to ban pos_set_velocity? pos_t pos; if (Pos_Disallowed()) { return; } if (trap_CmdArgc() != 4) { G_sprint(self, 2, "Usage: pos_{origin|angles"/*|velocity*/"} x1 x2 x3\n" "use '*' for no changes\n"); return; } if (self->pos_move_time && ((self->pos_move_time + 1) > g_globalvars.time)) { G_sprint(self, 2, "Only one move per second allowed\n"); return; } self->pos_move_time = g_globalvars.time; switch ((int)set_type) { case 1: Pos_Save_origin(&pos) ; Pos_Parse_Set(&(pos.origin)); Pos_Set_origin(&pos); break; case 2: Pos_Save_angles(&pos) ; Pos_Parse_Set(&(pos.v_angle)); Pos_Set_angles(&pos) ; break; case 3: Pos_Save_velocity(&pos) ; Pos_Parse_Set(&(pos.velocity)); Pos_Set_velocity(&pos) ; break; default: return; } G_sprint(self, 2, "Position set\n"); } //================================================ // pos_show/pos_save/pos_move/pos_set_* commands } //================================================ void Sh_Speed(void) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd info kf %d\n", (iKey(self, "kf") ^ KF_SPEED)); } // /motd command void PMOTDThink(void); void SMOTDThink(void); // often times you play a game on non-symmetrical map as one color then swap teams and play again to be fair void SwapAll(void) { int votes; if (match_in_progress) { return; } if (!isCTF()) { return; } if (k_captains) { G_sprint(self, 2, "No swapall when captain stuffing\n"); return; } if (k_coaches) { G_sprint(self, 2, "No swapall when coach stuffing\n"); return; } self->v.swapall = !self->v.swapall; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.swapall ? redtext(va("votes for swapall")) : redtext(va("withdraws %s swapall vote", g_his(self)))), ((votes = get_votes_req(OV_SWAPALL, true)) ? va(" (%d)", votes) : "")); vote_check_swapall(); } void motd_show(void) { gedict_t *motd; int owner = EDICT_TO_PROG(self); if (!k_matchLess) // show motd in matchLess mode even match in progress { if (match_in_progress) { return; } } for (motd = world; (motd = find(motd, FOFCLSN, "motd"));) { if (owner == motd->s.v.owner) { G_sprint(self, 2, "Already showing motd\n"); return; } } motd = spawn(); motd->classname = "motd"; motd->s.v.owner = EDICT_TO_PROG(self); // select MOTD for spectator or player motd->think = (func_t)(self->ct == ctSpec ? SMOTDThink : PMOTDThink); motd->s.v.nextthink = g_globalvars.time + 0.1; motd->attack_finished = g_globalvars.time + 10; } void krnd(void) { int argc, i; char arg_x[1024], buf[2048] = { 0 }; if (match_in_progress) { return; } if ((argc = trap_CmdArgc()) < 2) { G_sprint(self, 2, "usage: rnd <1st 2nd ...>\n"); return; } for (buf[0] = 0, i = 1; i < argc; i++) { trap_CmdArgv(i, arg_x, sizeof(arg_x)); strlcat(buf, arg_x, sizeof(buf)); strlcat(buf, (i + 1 < argc ? ", " : ""), sizeof(buf)); } G_bprint(2, "%s %s %s:\n" "\220%s\221\n", redtext("Random select by"), getname(self), redtext("from"), buf); trap_CmdArgv(i_rnd(1, argc - 1), arg_x, sizeof(arg_x)); G_bprint(2, "selected: \220%s\221\n", arg_x); } void agree_on_map(void) { if (!k_lastvotedmap) { return; // no map voted } // emulate as we select last voted map DoSelectMap(k_lastvotedmap); // <- there will be all checks about match_in_progress and etc } // { lastscores stuff char* lastscores2str(lsType_t lst) { switch (lst) { case lsDuel: return "duel"; // I was going to change this to "Duel" but maybe some stuff case lsTeam: return "team"; // is case sensitive out there already, to process it..? --phil case lsFFA: return "FFA"; case lsCTF: return "CTF"; case lsRA: return "RA"; case lsCA: return "Clan Arena"; case lsWO: return "Wipeout"; case lsHM: return "HoonyMode"; case lsRACE: return "race"; default: return "unknown"; } } void lastscore_add(void) { gedict_t *p; gedict_t *ed1 = get_ed_scores1(); gedict_t *ed2 = get_ed_scores2(); int from; int i; int s1 = 0; int s2 = 0; int s3 = 0; int k_ls = bound(0, cvar("__k_ls"), MAX_LASTSCORES - 1); char *e1; char *e2; char *e3; char t1[128] = { 0 }; char t2[128] = { 0 }; char t3[128] = { 0 }; char *name; char date[64]; char *extra; lsType_t lst = lsUnknown; e1 = e2 = e3 = extra = ""; if ((isRA() || isFFA()) && ed1 && ed2) { // not the best way since get_ed_scores do not serve ghosts, so... lst = (isRA() ? lsRA : lsFFA); e1 = getname(ed1); s1 = ed1->s.v.frags; e2 = getname(ed2); s2 = ed2->s.v.frags; } else if (isHoonyModeAny()) { if (HM_current_point_type() != HM_PT_FINAL) { return; } lst = lsHM; for (i = from = 0, p = world; (p = find_plrghst(p, &from)) && i < 2; i++) { if (!i) { // info about first dueler e1 = getname(p); s1 = p->s.v.frags; } else { // about second e2 = getname(p); s2 = p->s.v.frags; } } } else if (isDuel()) { lst = lsDuel; for (i = from = 0, p = world; (p = find_plrghst(p, &from)) && i < 2; i++) { if (!i) { // info about first dueler e1 = getname(p); s1 = p->s.v.frags; } else { // about second e2 = getname(p); s2 = p->s.v.frags; } } } else if ((isTeam() || isCTF() || isCA()) && k_showscores) { qbool isCa = isCA(); if (isCa) { lst = cvar("k_clan_arena") == 2 ? lsWO : lsCA; } else if (isTeam()) { lst = lsTeam; } else { lst = lsCTF; } e1 = cvar_string("_k_team1"); s1 = isCa ? CA_get_score_1() : get_scores1(); e2 = cvar_string("_k_team2"); s2 = isCa ? CA_get_score_2() : get_scores2(); // players from first team for (t1[0] = from = 0, p = world; (p = find_plrghst(p, &from));) { if (streq(getteam(p), e1) && !strnull(name = getname(p))) { strlcat(t1, va(" %s", name), sizeof(t1)); } } // players from second team for (t2[0] = from = 0, p = world; (p = find_plrghst(p, &from));) { if (streq(getteam(p), e2) && !strnull(name = getname(p))) { strlcat(t2, va(" %s", name), sizeof(t2)); } } if ((current_umode >= um2on2on2) && (current_umode <= um4on4on4)) { e3 = cvar_string("_k_team3"); s3 = get_scores3(); // players from third team for (t3[0] = from = 0, p = world; (p = find_plrghst(p, &from));) { if (streq(getteam(p), e3) && !strnull(name = getname(p))) { strlcat(t3, va(" %s", name), sizeof(t3)); } } } } if (strnull(e1) || strnull(e2)) { lst = lsUnknown; } if (lst == lsUnknown) // sorry but something wrong { return; } if (isRACE()) { lst = lsRACE; } if (!QVMstrftime(date, sizeof(date), "%b %d, %H:%M:%S %Y", 0)) { date[0] = 0; } cvar_fset(va("__k_ls_m_%d", k_ls), lst); cvar_set(va("__k_ls_e1_%d", k_ls), e1); cvar_set(va("__k_ls_e2_%d", k_ls), e2); cvar_set(va("__k_ls_t1_%d", k_ls), t1); cvar_set(va("__k_ls_t2_%d", k_ls), t2); if ((current_umode < umBlitz4v4) || (current_umode > um4on4on4)) { cvar_set(va("__k_ls_s_%d", k_ls), va("%3d:%-3d %s \x8D %-8.8s %13.13s%s", s1, s2, (k_overtime ? "OT" : " "), mapname, date, extra)); } else { cvar_set(va("__k_ls_e3_%d", k_ls), e3); cvar_set(va("__k_ls_t3_%d", k_ls), t3); cvar_set(va("__k_ls_s_%d", k_ls), va("%3d:%-3d:%-3d \x8D %-8.8s %13.13s%s", s1, s2, s3, mapname, date, extra)); } cvar_fset("__k_ls", ++k_ls % MAX_LASTSCORES); // this is a HACK for QTV, ok EZTV { char qtvdate[64]; gedict_t *cl = find_client(world); if (!QVMstrftime(qtvdate, sizeof(qtvdate), "%b %d, %H:%M", 0)) { qtvdate[0] = 0; } if (cl && !strnull(qtvdate)) { stuffcmd(cl, "//finalscores \"%s\" \"%s\" \"%s\" \"%s\" %d \"%s\" %d\n", qtvdate, lastscores2str(lst), mapname, e1, s1, e2, s2); } } } void lastscores(void) { int i; int j; int cnt; int k_ls = bound(0, cvar("__k_ls"), MAX_LASTSCORES - 1); char *e1; char *e2; char *le1; char *le2; char *t1; char *t2; char *lt1; char *lt2; char *sc; qbool extended = (trap_CmdArgc() > 1); // if they specified some params, then use extended version lsType_t last = lsUnknown; lsType_t cur = lsUnknown; e1 = e2 = le1 = le2 = t1 = t2 = lt1 = lt2 = ""; for (j = k_ls, cnt = i = 0; i < MAX_LASTSCORES; i++, j = (j + 1 >= MAX_LASTSCORES) ? 0 : j + 1) { cur = cvar(va("__k_ls_m_%d", j)); e1 = cvar_string(va("__k_ls_e1_%d", j)); e2 = cvar_string(va("__k_ls_e2_%d", j)); t1 = cvar_string(va("__k_ls_t1_%d", j)); t2 = cvar_string(va("__k_ls_t2_%d", j)); sc = cvar_string(va("__k_ls_s_%d", j)); if (cur == lsUnknown || strnull(e1) || strnull(e2)) { continue; } if (cur != last // changed game mode || (strneq(le1, e1) || strneq(le2, e2))) // changed teams, duelers { lt1 = lt2 = ""; // force show teams members again G_sprint(self, 2, "\220%s %s %s\221 %s\n", e1, redtext("vs"), e2, redtext(lastscores2str(cur))); } // if team mode show members. // generally show members one time while show scores for each played map, // but if squad changed from previuos map, show members again, // so we know which squad played each map. if (extended && ((cur == lsTeam) || (cur == lsCTF) || (cur == lsCA))) { if (strneq(lt1, t1)) // first team { G_sprint(self, 2, " %4.4s:%s\n", e1, t1); } if (strneq(lt2, t2)) // second team { G_sprint(self, 2, " %4.4s:%s\n", e2, t2); } } G_sprint(self, 2, " %s\n", sc); last = cur; le1 = e1; le2 = e2; lt1 = t1; lt2 = t2; cnt++; } if (cnt) { G_sprint(self, 2, "\n" "Lastscores: %d entr%s found\n", cnt, cnt ? "y" : "ies"); } else { G_sprint(self, 2, "Lastscores data empty\n"); } } // } lastscores stuff // { spec moreinfo qbool mi_on(void) { return ((int)cvar("k_spec_info") & MI_ON); } qbool mi_adm_only(void) { return ((int)cvar("k_spec_info") & MI_ADM_ONLY); } #define MI_POW (IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) #define MI_ARM (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3) #define MI_WPN (IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN \ | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING ) #define MI_WPN3 (IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING) typedef struct mi_levels_s { int items; const char *desc; } mi_levels_t; mi_levels_t mi_levels[] = { { 0, "Receiving extra infos: \xcf\xe6\xe6" }, { MI_POW | MI_ARM | IT_SUPERHEALTH | IT_ROCKET_LAUNCHER, "Receiving powerups\217armors\217mh\217rl" }, { MI_POW | MI_ARM | IT_SUPERHEALTH | MI_WPN3, "Receiving powerups\217armors\217mh\217rl\217gl\217lg" }, { MI_POW | MI_ARM | IT_SUPERHEALTH | MI_WPN, "Receiving powerups\217armors\217mh\217weapons" }, { MI_POW, "Receiving only powerups" } }; int mi_levels_cnt = sizeof(mi_levels) / sizeof(mi_levels[0]); void mi_print(gedict_t *tooker, int it, char *msg) { char *t_team; gedict_t *p; int level; qbool adm = mi_adm_only(); if (!mi_on()) { return; // spec info is turned off } t_team = getteam(tooker); for (p = world; (p = find_spc(p));) { if (adm && !is_adm(p)) { continue; // configured send only for admins } level = iKey(p, "mi"); // get spec setup if (level < 0) { level = 0; } if (level > (mi_levels_cnt - 1)) { level = 0; } if (!(it & mi_levels[level].items)) { continue; } if (isTeam() || isCTF()) { G_sprint(p, 2, "\204\220%4.4s\221 %s\n", t_team, msg); } else { G_sprint(p, 2, "%s\n", msg); } } } void moreinfo(void) { int level; if (!mi_on()) { G_sprint(self, 2, "Spec info is turned off by server\n"); return; } level = iKey(self, "mi") + 1; if (level > (mi_levels_cnt - 1)) { level = 0; } if (level < 0) { level = 0; } SetUserInfo(self, "mi", va("%d", level), 0); } void info_mi_update(gedict_t *p, char *from, char *to) { int level = atoi(to); int olevel = atoi(from); if (!mi_on()) { return; } if (level == olevel) { return; } if (level > (mi_levels_cnt - 1)) { level = 0; } if (level < 0) { level = 0; } G_sprint(p, 2, "%s\n", mi_levels[level].desc); } void infolock(void) { int k_spec_info = cvar("k_spec_info"); if (match_in_progress) { return; } if (!is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return; } k_spec_info ^= MI_ADM_ONLY; cvar_fset("k_spec_info", k_spec_info); if (mi_adm_only()) { G_bprint(2, "Only %s can receive specinfos\n", redtext("admins")); } else { G_bprint(2, "All %s can receive specinfos\n", redtext("spectators")); } } void infospec(void) { int k_spec_info = cvar("k_spec_info"); if (match_in_progress) { return; } k_spec_info ^= MI_ON; cvar_fset("k_spec_info", k_spec_info); G_bprint(2, "Extra info for spectators %s\n", redtext(OnOff(mi_on()))); } // } // { wreg void wreg_usage(void) { G_sprint(self, 2, "usage: cmd wreg [[char] [[+/-]weapon order]]\n"); } void wreg_showslot(wreg_t *w, int slot) { int i; char *sign, order[MAX_WREG_IMP + 1]; if (!w->init) { G_sprint(self, 2, "slot \"%c\" - unregistered\n", (char) slot); return; } sign = ""; if (w->attack > 0) { sign = "+"; } else if (w->attack < 0) { sign = "-"; } for (order[0] = i = 0; i < MAX_WREG_IMP && w->impulse[i]; i++) { order[i] = '0' + w->impulse[i]; } order[i] = 0; G_sprint(self, 2, "slot \"%c\" - \"%s%s\"\n", (char) slot, sign, order); } void cmd_wreg(void) { int argc = trap_CmdArgc(), attack = 0, imp[MAX_WREG_IMP], i, cnt; char arg_1[64], arg_2[64], *tmp = arg_2; byte c; wreg_t *w; if (!self->wreg) { return; } if (argc == 1) { qbool found = false; G_sprint(self, 2, "list of registered weapons:\n"); for (i = 0; i < MAX_WREGS; i++) { w = &(self->wreg[i]); if (!w->init) { continue; } found = true; wreg_showslot(w, i); } if (!found) { G_sprint(self, 2, "none\n"); } return; } trap_CmdArgv(1, arg_1, sizeof(arg_1)); if (strnull(arg_1)) { wreg_usage(); G_sprint(self, 2, "empty char\n"); return; } if (strlen(arg_1) > 1) { wreg_usage(); G_sprint(self, 2, "char can be only one byte\n"); return; } c = arg_1[0]; if (c == 0 || c > 175 || c > MAX_WREGS - 2) { // zzz, MAX_WREGS-2 so gcc is silent even that wrong wreg_usage(); G_sprint(self, 2, "\"%c\" - illegal char!\n", (char) c); return; } w = &(self->wreg[c]); if (argc == 2) { wreg_showslot(w, c); return; } if (argc != 3) { wreg_usage(); return; // something wrong } trap_CmdArgv(2, arg_2, sizeof(arg_2)); if (strnull(arg_2)) { if (w->init) { memset(w, 0, sizeof(wreg_t)); // clear w->init = false; G_sprint(self, 2, "slot \"%c\" - unregistered\n", (char) c); } else { wreg_usage(); G_sprint(self, 2, "empty weapon order\n"); } return; } for (cnt = i = 0; i < MAX_WREGS; i++) { if (!(self->wreg[i].init)) { continue; } if (++cnt >= 20) { G_sprint(self, 2, "too many wregs, discard registration\n"); return; } } if (strlen(arg_2) > 10) { // 10 == strlen("+987654321") wreg_usage(); G_sprint(self, 2, "too long weapon order\n"); return; } if (tmp[0] == '+') { tmp++; attack = 1; } else if (tmp[0] == '-') { tmp++; attack = -1; } if (!strnull(tmp) && !only_digits(tmp)) { wreg_usage(); G_sprint(self, 2, "illegal character in weapon order\n"); return; } for (i = 0; i < MAX_WREG_IMP && !strnull(tmp); tmp++) { if (tmp[0] == '0') // do not confuse with '\0' { continue; } imp[i] = tmp[0] - '0'; i++; } // ok we parse wreg command, and all ok, init it memset(w, 0, sizeof(wreg_t)); // clear w->init = true; w->attack = attack; for (i--; i >= 0 && i < MAX_WREG_IMP; i--) { w->impulse[i] = imp[i]; } G_sprint(self, 2, "slot \"%c\" - registered\n", (char) c); } void cmd_wreg_do(byte c) { qbool warn; int j; wreg_t *w; if (!self->wreg || (c > (MAX_WREGS - 2))) // zzz MAX_WREGS-2 so gcc happy, even that wrong { return; } w = &(self->wreg[c]); if (!w->init) { G_sprint(self, 2, "unregistered wreg char - \"%c\"\n", (char) c); return; } // G_sprint(self, 2, "wreg char - %c, i - %d %d %d\n", (char)c, w->impulse[0], w->impulse[1], w->impulse[2]); if (w->attack > 0) { self->wreg_attack = 1; if (self->ct == ctSpec) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "+attack\n"); } } else if (w->attack < 0) { self->wreg_attack = 0; if (self->ct == ctSpec) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "-attack\n"); } } if (self->ct == ctSpec) { return; } for (j = 0; j < MAX_WREG_IMP && w->impulse[j]; j++) { if (((j + 1) >= MAX_WREG_IMP) || !w->impulse[j + 1]) { warn = true; // warn about no weapon or ammo if this last impulse in array } else { warn = false; } if (W_CanSwitch(w->impulse[j], warn)) { self->s.v.impulse = w->impulse[j]; return; } } } // } void ToggleMidair(void) { if (!is_rules_change_allowed()) { return; } // Can't enable midair unless dmm4 is set first if (!cvar("k_midair") && deathmatch != 4) { G_sprint(self, 2, "Midair requires dmm4\n"); return; } // If midair is enabled, disable instagib if (cvar("k_instagib")) { cvar_set("k_instagib", "0"); } if (cvar(LGCMODE_VARIABLE)) { cvar_set(LGCMODE_VARIABLE, "0"); } if (cvar(TOT_MODE_VARIABLE)) { cvar_set(TOT_MODE_VARIABLE, "0"); } if (cvar("k_dmm4_gren_mode")) { cvar_set("k_dmm4_gren_mode", "0"); // If midair is enabled, disable gren_mode } cvar_toggle_msg(self, "k_midair", redtext("Midair")); } void SetMidairMinHeight(void) { int k_midair_minheight = bound(0, cvar("k_midair_minheight"), 4); if (!is_rules_change_allowed()) { return; } // Can't set minheight if midair is not turned on if (!cvar("k_midair")) { G_sprint(self, 2, "Midair must be turned on to set minimal frag height\n"); return; } if (++k_midair_minheight > 4) { k_midair_minheight = 0; } cvar_fset("k_midair_minheight", k_midair_minheight); if (k_midair_minheight == 1) { G_bprint(2, "Midair minimum height set to %s enabled level\n", redtext("bronze")); } else if (k_midair_minheight == 2) { G_bprint(2, "Midair minimum height set to %s enabled level\n", redtext("silver")); } else if (k_midair_minheight == 3) { G_bprint(2, "Midair minimum height set to %s enabled level\n", redtext("gold")); } else if (k_midair_minheight == 4) { G_bprint(2, "Midair minimum height set to %s enabled level\n", redtext("platinum")); } else { G_bprint(2, "Midair minimum height set to %s enabled level\n", redtext("ground")); } } void W_SetCurrentAmmo(void); void ToggleFreshTeams(void) { if (!is_rules_change_allowed()) { return; } // Can't enable freshteams unless dmm1 is set first if (deathmatch != 1) { G_sprint(self, 2, "FreshTeams requires dmm1\n"); return; } cvar_toggle_msg(self, "k_freshteams", "&c08fFreshTeams&r"); } void ToggleFreshPacks(void) // FreshPacks is enabled by default when playing freshteams { int k_freshteams = cvar("k_freshteams"); if (!is_rules_change_allowed()) { return; } // Can't enable nosweep unless dmm1 is set first if (!k_freshteams) { G_sprint(self, 2, "FreshPacks requires FreshTeams (/fresh)\n"); return; } cvar_toggle_msg(self, "k_freshteams_limit_packs", "&c08fFreshPacks&r (limited backpack ammo)"); } void ToggleFreshGuns(void) // FreshGuns is enabled by default when playing freshteams { int k_freshteams = cvar("k_freshteams"); if (!is_rules_change_allowed()) { return; } // Can't enable nosweep unless dmm1 is set first if (!k_freshteams) { G_sprint(self, 2, "FreshGuns requires FreshTeams (/fresh)\n"); return; } cvar_toggle_msg(self, "k_freshteams_limit_sweep_ammo", "&c08fFreshGuns&r (limited weapon ammo on sweep)"); } void ToggleFreshTime(void) { int k_freshteams = cvar("k_freshteams"); int k_freshtime = bound(0, cvar("k_freshteams_weapon_time"), 60); if (!is_rules_change_allowed()) { return; } // Can't enable nosweep unless dmm1 is set first if (!k_freshteams) { G_sprint(self, 2, "FreshTime requires FreshTeams (/fresh)\n"); return; } if (k_freshtime == 20) { cvar_set("k_freshteams_weapon_time", "15"); G_bprint(2, "%s 15 second weapons\n", "&c08fFreshTeams&r"); } else if (k_freshtime == 15) { cvar_set("k_freshteams_weapon_time", "10"); G_bprint(2, "%s 10 second weapons\n", "&c08fFreshTeams&r"); } else { cvar_set("k_freshteams_weapon_time", "20"); G_bprint(2, "%s 20 second weapons (default)\n", "&c08fFreshTeams&r"); } } void ToggleNoSweep(void) { if (!is_rules_change_allowed()) { return; } // Can't enable nosweep unless dmm1 is set first if (deathmatch != 1) { G_sprint(self, 2, "nosweep requires dmm1\n"); return; } cvar_toggle_msg(self, "k_nosweep", redtext("NoSweep")); } void ToggleInstagib(void) { int k_instagib = bound(0, cvar("k_instagib"), 3); char buf[1024 * 4]; char *cfg_name; if (!is_rules_change_allowed()) { return; } // Can't enable instagib unless dmm4 is set first if (!cvar("k_midair") && deathmatch != 4) { G_sprint(self, 2, "Instagib requires dmm4\n"); return; } cfg_name = va("configs/usermodes/instagib/default.cfg"); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/instagib/%s.cfg", mapname); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } G_cprint("\n"); if (cvar("k_midair")) { cvar_set("k_midair", "0"); // If instagib is enabled, disable midair } if (cvar(LGCMODE_VARIABLE)) { cvar_set(LGCMODE_VARIABLE, "0"); } if (cvar(TOT_MODE_VARIABLE)) { cvar_set(TOT_MODE_VARIABLE, "0"); } if (cvar("k_dmm4_gren_mode")) { cvar_set("k_dmm4_gren_mode", "0"); // If instagib is enabled, disable gren_mode } if (k_instagib == 0) { cvar_fset("dmm4_invinc_time", 1.0f); // default invic respawn time is 1s in instagib } if (++k_instagib > 3) { k_instagib = 0; } cvar_fset("k_instagib", k_instagib); if (!k_instagib) { G_bprint(2, "%s disabled\n", redtext("Instagib")); } else if (k_instagib == 1) { if (cvar("k_instagib_custom_models")) { G_bprint(2, "%s enabled (slow coilgun mode)\n", redtext("Instagib")); } else { G_bprint(2, "%s enabled (slow mode)\n", redtext("Instagib")); } } else if (k_instagib == 2) { if (cvar("k_instagib_custom_models")) { G_bprint(2, "%s enabled (fast coilgun mode)\n", redtext("Instagib")); } else { G_bprint(2, "%s enabled (fast mode)\n", redtext("Instagib")); } } else if (k_instagib == 3) { if (cvar("k_instagib_custom_models")) { G_bprint(2, "%s enabled (extreme coilgun mode)\n", redtext("Instagib")); } else { G_bprint(2, "%s enabled (extreme mode)\n", redtext("Instagib")); } } else { G_bprint(2, "%s unknown\n", redtext("Instagib")); } if (k_instagib) { cvar_set("k_cg_kb", "1"); } W_SetCurrentAmmo(); } void ToggleLGC(void) { qbool k_lgc = cvar(LGCMODE_VARIABLE) != 0; if (!is_rules_change_allowed()) { return; } // Can't enable instagib unless dmm4 is set first if (!k_lgc && (deathmatch != 4)) { G_sprint(self, 2, "LGC mode requires dmm4\n"); return; } // Disable incompatible modes if (cvar("k_midair")) { cvar_set("k_midair", "0"); } if (cvar("k_instagib")) { cvar_set("k_instagib", "0"); } // disable dmgfrags if (cvar("k_dmgfrags")) { cvar_set("k_dmgfrags", "0"); } // turn off handicap SetHandicap(self, 100); cvar_set(LGCMODE_VARIABLE, k_lgc ? "1" : "0"); cvar_toggle_msg(self, LGCMODE_VARIABLE, redtext("LGC mode")); W_SetCurrentAmmo(); } void ToggleCGKickback(void) { if (match_in_progress) { return; } if (!cvar("k_instagib")) { G_sprint(self, 2, "cg_kb requires Instagib\n"); return; } cvar_toggle_msg(self, "k_cg_kb", redtext("Coilgun kickback")); } void sv_time(void) { char date[64]; if (QVMstrftime(date, sizeof(date), "%a %b %d, %H:%M:%S %Y", 0)) { G_sprint(self, 2, "%s\n", date); } } void ToggleToT(void) { qbool k_tot = cvar(TOT_MODE_VARIABLE) != 0; if (!is_rules_change_allowed()) { return; } if (!k_tot && (deathmatch != 4)) { G_sprint(self, 2, "ToT mode requires dmm4\n"); return; } if (cvar("k_midair")) { cvar_set("k_midair", "0"); } if (cvar("k_instagib")) { cvar_set("k_instagib", "0"); } cvar_set(TOT_MODE_VARIABLE, k_tot ? "1" : "0"); cvar_toggle_msg(self, TOT_MODE_VARIABLE, redtext("Tribe of Tjernobyl mode")); W_SetCurrentAmmo(); } void GrenadeMode(void) { if (!is_rules_change_allowed()) { return; } // Can't toggle unless dmm4 is set first if (deathmatch != 4) { G_sprint(self, 2, "gren_mode requires dmm4\n"); return; } cvar_toggle_msg(self, "k_dmm4_gren_mode", redtext("grenade mode")); if (cvar("k_dmm4_gren_mode")) { // disallow any weapon except gl trap_cvar_set_float("k_disallow_weapons", DA_WPNS & ~IT_GRENADE_LAUNCHER); } } void ToggleReady(void) { if (isRACE()) { r_changestatus(3); // race_toggle return; } if (self->ready) { PlayerBreak(); } else { PlayerFastReady(); } } void dlist(void) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd demolist %s\n", params_str(1, -1)); } void dinfo(void) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd demoinfo %s\n", params_str(1, -1)); } // ktpro (c) void teleteam(void) { int k_tp_tele_death = bound(0, cvar("k_tp_tele_death"), 1); if (match_in_progress) { return; } if ((k_tp_tele_death = (k_tp_tele_death ? 0 : 1))) { G_bprint(2, "%s turn teamtelefrag %s\n", self->netname, redtext("affects frags")); } else { G_bprint(2, "%s turn teamtelefrag does %s\n", self->netname, redtext("not affect frags")); } cvar_fset("k_tp_tele_death", k_tp_tele_death); } // ktpro (c) void ChangeClientsCount(int type, int value) { char *sv_max = "maxclients", *k_max = "k_maxclients"; int cl_count = 0; if (match_in_progress) { return; } if (!check_perm(self, cvar("k_allowcountchange"))) { return; } type = bound(1, type, 2); // 1 - players, 2 - specs if (type == 2) { sv_max = "maxspectators"; k_max = "k_maxspectators"; } if ((cvar(sv_max) >= cvar(k_max)) && (value > 0)) { G_sprint(self, 2, "%s reached\n", redtext(sv_max)); return; } cl_count = bound(1, cvar(sv_max) + value, max(1, cvar(k_max))); if (cvar(sv_max) == cl_count) // does't change { return; } cvar_fset(sv_max, cl_count); G_bprint(2, "%s set %s to %d\n", self->netname, redtext(sv_max), cl_count); } void upplayers(float type) { ChangeClientsCount(type, 1); } void downplayers(float type) { ChangeClientsCount(type, -1); } void iplist_one(gedict_t *s, gedict_t *p) { G_sprint(s, 2, "%15.15s %s %-18.18s\n", cl_ip(p), is_adm(p) ? "A" : " ", p->netname); } // ktpro (c) void iplist(void) { int i; gedict_t *p; if (!check_perm(self, cvar("k_ip_list"))) { G_sprint(self, 2, "%s %s\n", redtext("Your IP is:"), cl_ip(self)); return; } for (i = 0, p = world; (p = find_plr(p));) { if (!i) { G_sprint(self, 2, "\x9xIPs list\x9x %s\n", redtext("players:")); } iplist_one(self, p); i++; } for (i = 0, p = world; (p = find_spc(p));) { if (!i) { G_sprint(self, 2, "\x9xIPs list\x9x %s\n", redtext("spectators:")); } iplist_one(self, p); i++; } } void dmgfrags(void) { qbool k_lgc = cvar(LGCMODE_VARIABLE) != 0; if (!is_rules_change_allowed()) { return; } if (k_lgc) { G_sprint(self, 2, "Dmgfrags is not allowed in LGC mode\n"); return; } cvar_toggle_msg(self, "k_dmgfrags", redtext("damage frags")); } // { movie, for trix record in memory // code is partially wroten by Tonik void mv_stop_record(void); qbool mv_is_recording(void); qbool mv_is_playback(void) { return self->is_playback; } void mv_stop_playback(void) { if (!mv_is_playback()) { return; } if (self->pb_ent) { ent_remove(self->pb_ent); self->pb_ent = NULL; } G_sprint(self, 2, "playback finished\n"); self->pb_frame = 0; self->is_playback = false; } qbool mv_can_playback(void) { if (match_in_progress || intermission_running) { return false; } if (mv_is_recording()) { return false; // sanity } if ((self->pb_frame >= self->rec_count) || (self->pb_frame < 0)) { return false; } return true; } void mv_playback(void) { gedict_t *pb_ent = self->pb_ent; float scale; int s, i; plrfrm_t *ftmp, *fp; if (!mv_is_playback()) { return; } if (!pb_ent || !mv_can_playback() || (self->pb_frame == (self->rec_count - 1))) { mv_stop_playback(); return; } scale = ((s = bound(0, iKey(self, "pbspeed"), 200)) ? s / 100.0f : 1.0f); self->pb_time += (g_globalvars.time - self->pb_old_time) * scale; self->pb_old_time = g_globalvars.time; fp = ftmp = &(self->plrfrms[self->pb_frame]); for (i = self->pb_frame + 1; i < self->rec_count; i++) { ftmp = &(self->plrfrms[i]); if (ftmp->time > self->pb_time) { break; } fp = ftmp; } i = fp - self->plrfrms; if ((i == self->pb_frame) || (fp->time > self->pb_time)) { return; } self->pb_frame = i; setorigin(pb_ent, PASSVEC3(fp->origin)); VectorCopy(fp->angles, pb_ent->s.v.angles); pb_ent->s.v.frame = fp->frame; pb_ent->s.v.effects = fp->effects; pb_ent->s.v.colormap = fp->colormap; } void mv_cmd_playback(void) { mv_stop_record(); // stop record first mv_stop_playback(); // stop playback first self->pb_frame = 0; if (!mv_can_playback()) { G_sprint(self, 2, "can't playback now\n"); return; } G_sprint(self, 2, "playback\n"); self->pb_ent = spawn(); self->pb_ent->classname = "pb_ent"; setmodel(self->pb_ent, "progs/player.mdl"); self->pb_time = 0; self->pb_old_time = g_globalvars.time; self->is_playback = true; } qbool mv_is_recording(void) { return self->is_recording; } void mv_stop_record(void) { if (!mv_is_recording()) { return; } G_sprint(self, 2, "recording finished (%d) frames\n", self->rec_count); self->is_recording = false; } qbool mv_can_record(void) { if (match_in_progress || intermission_running) { return false; } if (mv_is_playback()) { return false; // sanity } if ((self->rec_count >= MAX_PLRFRMS) || (self->rec_count < 0)) { return false; } return true; } void mv_record(void) { plrfrm_t *f; if (!mv_is_recording()) { return; } if (!mv_can_record()) { mv_stop_record(); return; } f = &(self->plrfrms[self->rec_count]); f->time = g_globalvars.time - self->rec_start_time; VectorCopy(self->s.v.origin, f->origin); VectorCopy(self->s.v.angles, f->angles); // VectorCopy(self->s.v.v_angle, f->v_angle); // FIXME: usefull ? f->frame = self->s.v.frame; f->effects = self->s.v.effects; f->colormap = self->s.v.colormap; // f->s.v.modelindex = self.modelindex; self->rec_count++; } void mv_cmd_record(void) { mv_stop_record(); // stop record first mv_stop_playback(); // stop playback first self->rec_count = 0; if (!mv_can_record()) { G_sprint(self, 2, "can't record now\n"); return; } G_sprint(self, 2, "recording\n"); self->rec_start_time = g_globalvars.time; self->is_recording = true; } void mv_cmd_stop(void) { mv_stop_record(); // stop record mv_stop_playback(); // stop playback } // } // ktpro (c) // /cmd callalias void callalias(void) { const int ca_limit = 15, ca_limit2 = 30; char arg_x[1024]; float tm; if (trap_CmdArgc() != 3) { G_sprint(self, 2, "usage: cmd callalias \n"); return; } if (self->connect_time + ca_limit < g_globalvars.time) { G_sprint(self, 2, "you can use \"callalias\" only during %d sec after connect\n", ca_limit); return; } trap_CmdArgv(2, arg_x, sizeof(arg_x)); tm = fabs(atof(arg_x)); if ((tm <= 0) || (tm > ca_limit2)) { G_sprint(self, 2, "calling time can't be longer than %d seconds\n", ca_limit2); return; } if (self->callalias_time) { G_sprint(self, 2, "you can't install more than 1 alias before previous will execute\n"); return; } trap_CmdArgv(1, arg_x, sizeof(arg_x)); if (strnull(arg_x)) { G_sprint(self, 2, "you can't install an alias with an empty name\n"); return; } G_sprint(self, 2, "installing %s alias (%.1f)\n", arg_x, tm); strlcpy(self->callalias, arg_x, CALLALIAS_SIZE); self->callalias_time = g_globalvars.time + tm; } void check_callalias(void) { if (!self->callalias_time || (self->callalias_time > g_globalvars.time)) { return; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "%s\n", self->callalias); self->callalias_time = 0; } // ktpro (c) // /cmd check char fcheck_name[128]; void fcheck(void) { char arg_x[1024]; int i; if (match_in_progress) { return; } if (trap_CmdArgc() != 2) { G_sprint(self, 2, "usage: cmd check \n" "for example: cmd check f_version\n"); return; } if (f_check) { G_sprint(self, 2, "Waiting from previous reply\n"); return; } trap_CmdArgv(1, arg_x, sizeof(arg_x)); if (!is_real_adm(self)) { if (strneq(arg_x, "f_version") && strneq(arg_x, "f_modified") && strneq(arg_x, "f_server")) { G_sprint(self, 2, "You are not allowed to check \020%s\021\n" "available checks are: f_version, f_modified and f_server\n", arg_x); return; } } for (i = 1; i <= MAX_CLIENTS; i++) { if (g_edicts[i].f_checkbuf) { g_edicts[i].f_checkbuf[0] = 0; // clear bufs } } f_check = g_globalvars.time + 3; strlcpy(fcheck_name, arg_x, sizeof(fcheck_name)); // remember check name G_bprint(2, "%s is checking \020%s\021\n", self->netname, arg_x); if (streq(arg_x, "f_version") || streq(arg_x, "f_modified")) { G_bprint(3, "%s: %s %d%d\n", self->netname, arg_x, i_rnd(1, 9999), i_rnd(0, 9999)); } else { G_bprint(3, "%s: %s\n", self->netname, arg_x); } } void check_fcheck(void) { gedict_t *p; char *nl, *tmp; if (!f_check || (f_check > g_globalvars.time)) { return; } G_bprint(2, "player's \020%s\021 replies:\n", fcheck_name); for (p = world; (p = find_plr(p));) { if (strnull(tmp = p->f_checkbuf)) { G_bprint(3, "%s did not reply!\n", p->netname); continue; } while (!strnull(tmp)) { if ((nl = strchr(tmp, '\n'))) { nl[0] = 0; } G_bprint(3, "%s: %s\n", p->netname, tmp); tmp = (nl ? nl + 1 : NULL); } } G_bprint(2, "end of player's \020%s\021 replies\n", fcheck_name); f_check = 0; } void mapcycle(void) { char var[128], *newmap = ""; int i; for (i = 0; i < 999; i++) { snprintf(var, sizeof(var), "k_ml_%d", i); if (strnull(newmap = cvar_string(var))) { break; } if (!i) { G_sprint(self, 2, "%s:\n" "%3.3s | %s\n", redtext("Map cycle"), redtext("id"), redtext("name")); } G_sprint(self, 2, "%3.3d | %s%s\n", i + 1, newmap, streq(newmap, mapname) ? " \x8D current" : ""); } if (!i) { G_sprint(self, 2, "\n%s: %s\n", redtext("Map cycle"), redtext("empty")); return; } if (trap_cvar("samelevel")) { G_sprint(self, 2, "\n%s: %s\n", redtext("Map cycle"), redtext("not active")); } } void airstep(void) { if (match_in_progress || isRACE()) { return; } cvar_toggle_msg(self, "pm_airstep", redtext("pm_airstep")); } void ToggleVwep(void) { gedict_t *p, *oself; if (match_in_progress) { return; } if (!vw_available || !cvar("k_allow_vwep")) { return; } cvar_toggle_msg(self, "k_vwep", redtext("vwep")); vw_enabled = vw_available && cvar("k_allow_vwep") && cvar("k_vwep"); oself = self; for (p = world; (p = find_client(p));) { if (p->ct == ctPlayer) { self = p; W_SetCurrentAmmo(); } } self = oself; } void ToggleExclusive(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_exclusive", redtext("exclusive mode")); } void ToggleNewCoopNm(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_nightmare_pu", redtext("New Nightmare mode (drops powerups)")); } // { yawn mode related // { yawn mode related void FixYawnMode(void) { k_yawnmode = cvar("k_yawnmode"); k_teleport_cap = bound(0, cvar("k_teleport_cap"), 100); } // Toggle yawnmode, implemented by Molgrum void ToggleYawnMode(void) { if (!is_rules_change_allowed()) { return; } cvar_toggle_msg(self, "k_yawnmode", redtext("yawnmode")); FixYawnMode(); // apply changes ASAP } void setTeleportCap(void) { char arg[256]; if (!k_yawnmode) { G_sprint(self, 2, "%s required to be on\n", redtext("Yawn mode")); return; } if (match_in_progress || trap_CmdArgc() < 1) { G_sprint(self, 2, "%s is %d%%\n", redtext("Teleport cap"), k_teleport_cap); return; } trap_CmdArgv(1, arg, sizeof(arg)); k_teleport_cap = atoi(arg); // get user input k_teleport_cap = bound(0, k_teleport_cap, 100); // bound cvar_fset("k_teleport_cap", k_teleport_cap); // set FixYawnMode(); // apply changes ASAP G_bprint(2, "%s set %s to %d%%\n", self->netname, redtext("Teleport cap"), k_teleport_cap); // and print } // } float when_to_pause; int when_to_unpause; int pauseduration; int pauses_remaining; char pause_name[50]; void PausedTic(int duration) { gedict_t *p; int time = 0; static int prevtime = 0; pauseduration = duration; if (when_to_unpause && when_to_unpause > duration) { time = max(0, (when_to_unpause - duration) / 1000) + 1; G_cp2all("%s\n\n%d", "unpausing", time); if (time != prevtime) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play buttons/switch04.wav\n"); } prevtime = time; } } // Unpause on schedule, or if the game has ended for some reason if ((!k_matchLess && match_in_progress != 2) || (when_to_unpause && duration >= when_to_unpause)) { when_to_unpause = pauseduration = 0; // reset our globals G_cp2all(" "); // clear centerprint G_bprint(2, "game unpaused\n"); trap_setpause(0); } } void TogglePause(void) { int minutes, seconds; gedict_t *p; if (!k_matchLess) { // NON matchless if (match_in_progress != 2) { return; // apply TogglePause only during actual game } } if ((int)cvar("sv_paused") & 1) { // UNPAUSE // pause release is not applied immediately, but after a countdown if (when_to_unpause) { // unpause is pending alredy int sec = max(0, (when_to_unpause - pauseduration) / 1000); G_sprint(self, 2, "Unpause is pending, %d second%s\n", sec, count_s(sec)); return; } when_to_unpause = pauseduration + 3000; // schedule unpause in 3000 ms G_bprint(2, "%s unpaused the game (will resume in 3 seconds)\n", self->netname); } else { // PAUSE if (when_to_pause) { G_sprint(self, 2, "Pause already in progress.\n"); return; } if ((p = find(world, FOFCLSN, "timer"))) { minutes = p->cnt; seconds = p->cnt2; if (seconds == 60) { seconds = 0; } else { minutes--; } //can't pause if less than 3 seconds left in match if (!minutes && seconds <= 3) { G_sprint(self, 2, "Too late to pause. Please wait for match to finish.\n"); return; } } // admins may ignore not allowed pause if (!cvar("pausable") && !is_adm(self) && !PlayerCanPause(self)) { G_sprint(self, 2, "Pause is not allowed\n"); return; } when_to_pause = g_globalvars.time + 3; strlcpy(pause_name, self->netname, sizeof(pause_name)); pauses_remaining = self->k_pauseRequests; } } void WillPause(void) { gedict_t *p; int time = when_to_pause - g_globalvars.time+1; static int prevtime = 0; if (!when_to_pause) { return; } if (time > 0) { if (time != prevtime) { for (p = world; (p = find_client(p));) { stuffcmd(p, "play buttons/switch04.wav\n"); } prevtime = time; } G_cp2all("%s\n\n%d", "pausing", time); return; } G_cp2all(" "); // clear centerprint when_to_pause = 0; pauseduration = when_to_unpause = 0; // reset our globals G_bprint(2, "%s paused the game. He has %d remaining request(s).\n", pause_name, pauses_remaining); trap_setpause(1); } void ToggleArena(void) { if (!is_rules_change_allowed()) { return; } if (!isRA()) { // seems we trying turn RA on. if (!isDuel()) { G_sprint(self, 2, "Set %s mode first\n", redtext("\223 on \223")); return; } } cvar_toggle_msg(self, "k_rocketarena", redtext("Rocket Arena")); if (isRA()) { char buf[1024 * 4]; char *cfg_name; char *um = "1on1"; cfg_name = va("configs/usermodes/%s/ra/default.cfg", um); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/%s/ra/%s.cfg", um, mapname); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } G_cprint("\n"); // avoid spawn bug with safe spawn mode cvar_fset("k_spw", 1); } } void Spawn666Time(void) { char arg_2[1024]; float dmm4_invinc_time; if (deathmatch != 4) { G_sprint(self, 2, "command allowed in %s only\n", redtext("dmm4")); return; } // no arguments, show info and return if (match_in_progress || (trap_CmdArgc() == 1)) { dmm4_invinc_time = cvar("dmm4_invinc_time"); dmm4_invinc_time = dmm4_invinc_time ? bound(0, dmm4_invinc_time, DMM4_INVINCIBLE_MAX) : DMM4_INVINCIBLE_DEFAULT; G_sprint(self, 2, "%s is %.1fs\n", redtext("spawn invincibility time"), dmm4_invinc_time); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); dmm4_invinc_time = bound(0, atof(arg_2), DMM4_INVINCIBLE_DEFAULT); G_bprint(2, "%s set %s to %.1fs\n", self->netname, redtext("spawn invincibility time"), dmm4_invinc_time); // to actualy disable dmm4_invinc_time we need set it to negative value trap_cvar_set_float("dmm4_invinc_time", dmm4_invinc_time ? dmm4_invinc_time : -1); } void noitems(void) { if (match_in_progress) { return; } cvar_toggle_msg(self, "k_noitems", redtext("noitems mode")); } void giveme_usage(void) { G_sprint(self, 2, "giveme [seconds]\n" "giveme rune [1|2|3|4]\n" "giveme runes\n" "giveme norunes\n"); } void giveme(void) { char arg_2[128]; char arg_3[128]; char *got = "BUG"; float seconds; if (strnull(ezinfokey(world, "*cheats"))) { G_sprint(self, 2, "Cheats are disabled on this server, so use the force, Luke... err %s\n", self->netname); return; // FU! } // no arguments, show info and return if (trap_CmdArgc() == 1) { giveme_usage(); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); trap_CmdArgv(2, arg_3, sizeof(arg_3)); seconds = max(0, atof(arg_3)); if (!seconds) { seconds = 30; } if (streq(arg_2, "q")) { self->super_time = 1; self->super_damage_finished = g_globalvars.time + seconds; self->s.v.items = (int)self->s.v.items | IT_QUAD; got = "quad"; } else if (streq(arg_2, "p")) { self->invincible_time = 1; self->invincible_finished = g_globalvars.time + seconds; self->s.v.items = (int)self->s.v.items | IT_INVULNERABILITY; got = "pent"; } else if (streq(arg_2, "r")) { self->invisible_time = 1; self->invisible_finished = g_globalvars.time + seconds; self->s.v.items = (int)self->s.v.items | IT_INVISIBILITY; got = "ring"; } else if (streq(arg_2, "s")) { self->rad_time = 1; self->radsuit_finished = g_globalvars.time + seconds; self->s.v.items = (int)self->s.v.items | IT_SUIT; got = "suit"; } else if (streq(arg_2, "rune")) { int rune = bound(0, seconds - 1, 3); g_globalvars.serverflags = (int)g_globalvars.serverflags | (1 << rune); return; } else if (streq(arg_2, "runes")) { g_globalvars.serverflags = (int)g_globalvars.serverflags | 15; return; } else if (streq(arg_2, "norunes")) { g_globalvars.serverflags = (int)g_globalvars.serverflags & ~15; return; } else { giveme_usage(); return; } G_sprint(self, 2, "You got %s for %.1fs\n", got, seconds); } qbool is_rules_change_allowed(void) { if (match_in_progress) { G_sprint(self, 2, "Command is locked while %s is in progress\n", redtext("match")); return false; } if (isRACE()) { G_sprint(self, 2, "%s is on, please toggle it off by using %s command first\n", redtext("race mode"), redtext("race")); return false; } return true; } typedef struct { char *name; char *classname; int spawnflags; int angle; // should we set angles or not. void (*spawn)(void); // custom spawn function, called after actual spawn. } dropitem_spawn_t; #define WEAPON_BIG2 1 static void dropitem_spawn_spawnpoint(void) { int effects = EF_GREEN | EF_RED; // default effects. self->s.v.flags = (int)self->s.v.flags | FL_ITEM; setmodel(self, "progs/w_g_key.mdl"); if (streq(self->classname, "info_player_team1")) { effects = EF_RED; } else if (streq(self->classname, "info_player_team2")) { effects = EF_BLUE; } self->s.v.effects = (int)self->s.v.effects | effects; setorigin(self, PASSVEC3(self->s.v.origin)); } static dropitem_spawn_t dropitems[] = { { "h15", "item_health", H_ROTTEN }, { "h25", "item_health", 0 }, { "h100", "item_health", H_MEGA }, { "ga", "item_armor1", 0 }, { "ya", "item_armor2", 0 }, { "ra", "item_armorInv", 0 }, { "ssg", "weapon_supershotgun", 0 }, { "ng", "weapon_nailgun", 0 }, { "sng", "weapon_supernailgun", 0 }, { "gl", "weapon_grenadelauncher", 0 }, { "rl", "weapon_rocketlauncher", 0 }, { "lg", "weapon_lightning", 0 }, { "sh20", "item_shells", 0 }, { "sh40", "item_shells", WEAPON_BIG2 }, { "sp25", "item_spikes", 0 }, { "sp50", "item_spikes", WEAPON_BIG2 }, { "ro5", "item_rockets", 0 }, { "ro10", "item_rockets", WEAPON_BIG2 }, { "ce6", "item_cells", 0 }, { "ce12", "item_cells", WEAPON_BIG2 }, { "p", "item_artifact_invulnerability", 0 }, { "s", "item_artifact_envirosuit", 0 }, { "r", "item_artifact_invisibility", 0 }, { "q", "item_artifact_super_damage", 0 }, { "fl_r", "item_flag_team1", 0, 1 }, { "fl_b", "item_flag_team2", 0, 1 }, { "sp_r", "info_player_team1", 0, 1, dropitem_spawn_spawnpoint }, { "sp_b", "info_player_team2", 0, 1, dropitem_spawn_spawnpoint }, { "sp_dm", "info_player_deathmatch", 0, 1, dropitem_spawn_spawnpoint }, { "sp_cp", "info_player_coop", 0, 1, dropitem_spawn_spawnpoint }, { "sp_sp", "info_player_start", 0, 1, dropitem_spawn_spawnpoint }, }; static const int dropitems_count = sizeof(dropitems) / sizeof(dropitems[0]); static dropitem_spawn_t* dropitem_find_by_name(const char *name) { int i; for (i = 0; i < dropitems_count; i++) { if (streq(dropitems[i].name, name)) { return &dropitems[i]; } } return NULL; } // spawn item. static gedict_t* dropitem_spawn_item(gedict_t *spot, dropitem_spawn_t *di) { extern qbool G_CallSpawn(gedict_t *ent); gedict_t *oself; gedict_t *p = spawn(); p->dropitem = true; p->classname = di->classname; p->s.v.spawnflags = di->spawnflags; VectorCopy(spot->s.v.origin, p->s.v.origin); // VectorCopy(spot->s.v.angles, p->s.v.angles); if (di->angle) { p->s.v.angles[1] = spot->s.v.angles[1]; // seems we should set angles for this entity. } setorigin(p, PASSVEC3(p->s.v.origin)); // G_CallSpawn will change 'self', so we have to do trick about it. oself = self; // save!!! if (!G_CallSpawn(p) || strnull(p->classname)) { // failed to call spawn function, so remove it ASAP. ent_remove(p); p = NULL; } else if (di->spawn) { di->spawn(); // call custom spawn function if we succeed with main spawn function. } self = oself; // restore!!! return p; } static void dropitem_usage(void) { int i; char tmp[1024] = { 0 }; // dropitem < x | y > for (i = 0; i < dropitems_count; i++) { if (!(i % 3) && *tmp) { G_sprint(self, 2, "dropitem < %s >\n", tmp); *tmp = 0; } if (*tmp) { strlcat(tmp, " | ", sizeof(tmp)); } strlcat(tmp, dropitems[i].name, sizeof(tmp)); } if (*tmp) { G_sprint(self, 2, "dropitem < %s >\n", tmp); } } static void dropitem(void) { dropitem_spawn_t *di; char arg_1[128]; if (match_in_progress) { return; } if (strnull(ezinfokey(world, "*cheats"))) { G_sprint(self, 2, "Cheats are disabled on this server, so use the force, Luke... err %s\n", self->netname); return; // FU! } // no arguments, show info and return if (trap_CmdArgc() < 2) { dropitem_usage(); return; } trap_CmdArgv(1, arg_1, sizeof(arg_1)); if ((di = dropitem_find_by_name(arg_1))) { if (dropitem_spawn_item(self, di)) { G_sprint(self, 2, "Spawned %s\n", di->classname); } else { G_sprint(self, 2, "Can't spawn %s\n", di->classname); } } else { dropitem_usage(); return; } } static void removeitem(void) { gedict_t *ent; gedict_t *p = NULL; float best_distance = 10e+32; //should be FLT_MAX but it is absent of some systems. if (match_in_progress) { return; } if (strnull(ezinfokey(world, "*cheats"))) { G_sprint(self, 2, "Cheats are disabled on this server, so use the force, Luke... err %s\n", self->netname); return; // FU! } for (ent = world; (ent = nextent(ent));) { float distance = 0; int j; if (!ent->dropitem) { continue; // not our item. } for (j = 0; j < 3; j++) { float c = self->s.v.origin[j] - (ent->s.v.origin[j] + (ent->s.v.mins[j] + ent->s.v.maxs[j]) * 0.5); distance += c * c; } // check if that item closer to us. if (distance > best_distance) { continue; } p = ent; best_distance = distance; } if (p) { G_sprint(self, 2, "Removed %s\n", p->classname); ent_remove(p); } else { G_sprint(self, 2, "Nothing found around\n"); } } static void dump_print(fileHandle_t file_handle, const char *fmt, ...) { va_list argptr; char text[1024] = { 0 }; if (file_handle < 0) { return; } va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_FS_WriteFile(text, strlen(text), file_handle); } static void dumpent(void) { int cnt = 0; gedict_t *p; fileHandle_t file_handle = -1; if (match_in_progress) { return; } if (strnull(ezinfokey(world, "*cheats"))) { G_sprint(self, 2, "Cheats are disabled on this server, so use the force, Luke... err %s\n", self->netname); return; } if (trap_FS_OpenFile("dump.ent", &file_handle, FS_WRITE_BIN) < 0) { G_sprint(self, 2, "Can't open file for write\n"); return; } for (p = world; (p = nextent(p));) { if (!p->dropitem) { continue; // not our item. } if (strnull(p->classname)) { continue; // null class name. } dump_print(file_handle, "{\n"); dump_print(file_handle, "\t" "\"classname\" \"%s\"" "\n", p->classname); dump_print(file_handle, "\t" "\"origin\" \"%d %d %d\"" "\n", (int)p->s.v.origin[0], (int)p->s.v.origin[1], (int)p->s.v.origin[2]); if (p->s.v.angles[0] || p->s.v.angles[2]) { dump_print(file_handle, "\t" "\"angles\" \"%d %d %d\"" "\n", (int)p->s.v.angles[0], (int)p->s.v.angles[1], (int)p->s.v.angles[2]); } else if (p->s.v.angles[1]) { dump_print(file_handle, "\t" "\"angle\" \"%d\"" "\n", (int)p->s.v.angles[1]); } if (p->s.v.spawnflags) { dump_print(file_handle, "\t" "\"spawnflags\" \"%d\"" "\n", (int)p->s.v.spawnflags); } dump_print(file_handle, "}\n"); cnt++; } trap_FS_CloseFile(file_handle); G_sprint(self, 2, "Dumped %d entities\n", cnt); } qbool lgc_enabled(void) { return cvar(LGCMODE_VARIABLE) != 0; } void lgc_register_hit(vec3_t start, gedict_t *player, gedict_t *victim) { if (victim && (victim->ct == ctPlayer)) { player->lgc_state = lgcNormal; if (isDuel()) { float distance = bound(0, VectorDistance(start, victim->s.v.origin), LGCMODE_MAX_DISTANCE - 1); int bucket = bound(0, (int)(distance / LGCMODE_BUCKET_DISTANCE), LGCMODE_DISTANCE_BUCKETS - 1); player->lgc_distance_hits[bucket]++; } } else { lgc_register_miss(start, player); } } void lgc_register_miss(vec3_t start, gedict_t *player) { if (player->lgc_state == lgcUndershaft) { ++player->ps.lgc_undershaft; } else if (player->lgc_state == lgcOvershaft) { ++player->ps.lgc_overshaft; } if (isDuel()) { // Find opponent and register miss according to distance gedict_t *p; for (p = world; (p = find_plr(p));) { if (p != player) { float distance = bound(0, VectorDistance(start, p->s.v.origin), LGCMODE_MAX_DISTANCE - 1); int bucket = bound(0, (int)(distance / LGCMODE_BUCKET_DISTANCE), LGCMODE_DISTANCE_BUCKETS - 1); player->lgc_distance_misses[bucket]++; break; } } } } void lgc_register_kill(gedict_t *player) { player->lgc_state = lgcOvershaft; player->ps.wpn[wpLG].enemyjustkilled = 1; } void lgc_register_fire_stop(gedict_t *player) { player->lgc_state = lgcUndershaft; if (player->ps.wpn[wpLG].enemyjustkilled == 1) { player->ps.wpn[wpLG].enemyjustkilled = 0; // last frag lg statistics player->ps.wpn[wpLG].lastfragdisplayattacks = player->ps.wpn[wpLG].lastfragattacks; player->ps.wpn[wpLG].lastfragdisplayhits = player->ps.wpn[wpLG].lastfraghits; player->ps.wpn[wpLG].lastfragattacks = 0; player->ps.wpn[wpLG].lastfraghits = 0; } } void ListGameModes(void) { const char *known[] = { "race", "1on1", "2on2", "3on3", "4on4", "2on2on2", "3on3on3", "4on4on4", "10on10", "XonX", "ffa", "ctf", "hoonymode", "blitz2v2", "blitz4v4", "practice", "midair", "instagib", "berzerk", "lgcmode", "arena", "carena", "wipeout", "yawnmode", "totmode", }; int i, j; for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { for (j = 0; j < sizeof(known) / sizeof(known[0]); j++) { if (streq(cmds[i].name, known[j])) { G_sprint(self, 2, "%s\n", known[j]); break; } } } } qbool tot_mode_enabled(void) { return cvar(TOT_MODE_VARIABLE) != 0; } QW-Group-ktx-d05d6ca/src/ctf.c000066400000000000000000000503121475442401000161400ustar00rootroot00000000000000/* * $Id$ */ #include "g_local.h" // CTF todo: // . option to disable pents, but leave quads on? // . ability to drop backpacks of ammo to teammates // Changes from purectf: // . Close range grapple exploit removed // . Grapple speed stays consistent regardless of sv_maxspeed // . Status bar removed use +scores instead // . Physics are the same as those found on dm servers (you can accel jump, etc) // . Spawns are now random (except initial spawn in your base) with default spawnsafety mode // . Untouched runes respawn at 90 seconds instead of 120 (happens if in lava or falls through level, etc) // . Defending the flag is now two bonus points rather than one // Server config changes: // . add 64 to k_allowed_free_modes to enable ctf, 127 now enables all modes // . set k_mode 4 if you want server to default to ctf mode #define FLAG_RETURN_TIME 30 #define CARRIER_ASSIST_TIME 6 #define RETURN_ASSIST_TIME 4 #define RETURN_BONUS 1 #define CAPTURE_BONUS 15 #define TEAM_BONUS 10 #define CARRIER_ASSIST_BONUS 2 #define RETURN_ASSIST_BONUS 1 #define CARRIER_DEFEND_TIME 4 void DropFlag(gedict_t *flag, qbool tossed); void PlaceFlag(void); void FlagThink(void); void FlagTouch(void); void SP_item_flag_team1(void); void SP_item_flag_team2(void); // Allows us to add flags (or other items) to dm maps when ctfing without actually changing bsp void G_CallSpawn(gedict_t *ent); void SpawnCTFItem(char *classname, float x, float y, float z, float angle) { gedict_t *item = spawn(); item->classname = classname; setorigin(item, x, y, z); item->s.v.angles[0] = 0; item->s.v.angles[1] = angle; G_CallSpawn(item); } void spawn_item_flag(void) { if (k_ctf_custom_models) { setmodel(self, "progs/flag.mdl"); } self->noise = "misc/flagtk.wav"; self->noise1 = "doors/runetry.wav"; setsize(self, -16, -16, 0, 16, 16, 74); self->mdl = self->model; self->s.v.flags = FL_ITEM; self->s.v.solid = SOLID_TRIGGER; self->s.v.movetype = MOVETYPE_TOSS; SetVector(self->s.v.velocity, 0, 0, 0); self->s.v.origin[2] += 6; self->think = (func_t) FlagThink; self->touch = (func_t) FlagTouch; self->s.v.nextthink = g_globalvars.time + 0.1; self->cnt = FLAG_AT_BASE; self->cnt2 = 0.0; VectorCopy(self->s.v.angles, self->mangle); self->s.v.effects = (int)self->s.v.effects | EF_DIMLIGHT; if (!droptofloor(self)) { ent_remove(self); } else { VectorCopy(self->s.v.origin, self->s.v.oldorigin); } if (!isCTF()) { setmodel(self, ""); self->touch = (func_t) SUB_Null; } } void SP_item_flag_team1(void) { self->k_teamnumber = 1; self->s.v.items = IT_KEY2; self->s.v.skin = 0; self->s.v.effects = (int)self->s.v.effects | EF_RED; if (!k_ctf_custom_models) { setmodel(self, "progs/w_g_key.mdl"); } spawn_item_flag(); } void SP_item_flag_team2(void) { self->k_teamnumber = 2; self->s.v.items = IT_KEY1; self->s.v.skin = 1; self->s.v.effects = (int)self->s.v.effects | EF_BLUE; if (!k_ctf_custom_models) { setmodel(self, "progs/w_s_key.mdl"); } spawn_item_flag(); } // would love to know what a ctf wall is :O! void SP_func_ctf_wall(void) { SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_PUSH; self->s.v.solid = SOLID_BSP; setmodel(self, self->model); } #define TF_TEAM_BLUE 1 #define TF_TEAM_RED 2 void SP_item_tfgoal(void) { // NOTE: team_no inverted for flags!!! if (self->team_no == TF_TEAM_RED) { self->classname = "item_flag_team2"; SP_item_flag_team2(); } else if (self->team_no == TF_TEAM_BLUE) { self->classname = "item_flag_team1"; SP_item_flag_team1(); } else { G_Printf("SP_item_tfgoal: team_no %d unsupported\n", self->team_no); ent_remove(self); return; } } void SP_info_player_teamspawn(void) { if (self->team_no == TF_TEAM_RED) { self->classname = "info_player_team1"; } else if (self->team_no == TF_TEAM_BLUE) { self->classname = "info_player_team2"; } else { G_Printf("SP_info_player_teamspawn: team_no %d unsupported\n", self->team_no); ent_remove(self); return; } } void SP_i_p_t(void) { self->classname = "info_player_teamspawn"; SP_info_player_teamspawn(); } // add/remove hook item to/from player void AddHook(qbool yes) { gedict_t *e, *oself; oself = self; for (e = world; (e = find_plr(e));) { e->s.v.items = (yes ? ((int)e->s.v.items | IT_HOOK) : ((int)e->s.v.items & ~IT_HOOK)); self = e; // warning if (self->hook_out) { GrappleReset(self->hook); } self->hook_out = false; self->on_hook = false; if (!yes && (self->s.v.weapon == IT_HOOK)) { // actually remove hook from hands if hold, not just from items self->s.v.weapon = 0; W_SetCurrentAmmo(); } } self = oself; } void RegenFlag(gedict_t *flag) { flag->s.v.movetype = MOVETYPE_TOSS; flag->s.v.solid = SOLID_TRIGGER; setmodel(flag, flag->mdl); VectorCopy(flag->mangle, flag->s.v.angles); flag->cnt = FLAG_RETURNED; flag->cnt2 = 0.0; flag->s.v.owner = EDICT_TO_PROG(world); SetVector(flag->s.v.velocity, 0, 0, 0); sound(flag, CHAN_FLAG, "items/itembk2.wav", 1, ATTN_NORM); flag->s.v.nextthink = g_globalvars.time + 0.2; flag->s.v.groundentity = EDICT_TO_PROG(world); flag->touch = (func_t) FlagTouch; } // show/hide flag void RegenFlags(qbool yes) { gedict_t *flag; flag = find(world, FOFCLSN, "item_flag_team1"); if (flag) { if (!yes) { flag->touch = (func_t) SUB_Null; setmodel(flag, ""); } else { RegenFlag(flag); } } flag = find(world, FOFCLSN, "item_flag_team2"); if (flag) { if (!yes) { flag->touch = (func_t) SUB_Null; setmodel(flag, ""); } else { RegenFlag(flag); } } } void FlagThink(void) { if (!isCTF()) { return; } self->s.v.nextthink = g_globalvars.time + 0.1; if (self->cnt == FLAG_AT_BASE) { return; } if (self->cnt == FLAG_DROPPED) { self->cnt2 += 0.1; if (g_globalvars.time > self->super_time) { RegenFlag(self); G_bprint(2, "The %s flag has been returned\n", redtext(((int)self->s.v.items & IT_KEY1) ? "BLUE" : "RED")); } return; } if (self->cnt == FLAG_RETURNED) { setorigin(self, PASSVEC3(self->s.v.oldorigin)); self->cnt = FLAG_AT_BASE; return; } self->cnt2 += 0.1; } void FlagTouch(void) { gedict_t *p, *owner; if (!k_practice) { if (match_in_progress != 2) { return; } } if (other->ct != ctPlayer) { return; } if (other->s.v.health < 1) { return; } if (self->cnt == FLAG_RETURNED) { return; } // if owner of the flag, do nothing (probably toss in progress) if (self->s.v.owner == EDICT_TO_PROG(other)) { return; } // touching their own flag if (((self->k_teamnumber == 1) && streq(getteam(other), "red")) || ((self->k_teamnumber == 2) && streq(getteam(other), "blue"))) { if (self->cnt == FLAG_AT_BASE) { if (other->ctf_flag & CTF_FLAG) { gedict_t *cflag = NULL; // capture other->ctf_flag -= ((int)other->ctf_flag & CTF_FLAG); other->s.v.effects -= ((int)other->s.v.effects & (EF_FLAG1 | EF_FLAG2)); sound(other, CHAN_FLAG, "misc/flagcap.wav", 1, ATTN_NONE); G_bprint(2, "%s", other->netname); if (self->k_teamnumber == 1) { cflag = find(world, FOFCLSN, "item_flag_team2"); G_bprint(2, " %s the %s flag!\n", redtext("captured"), redtext("BLUE")); } else { cflag = find(world, FOFCLSN, "item_flag_team1"); G_bprint(2, " %s the %s flag!\n", redtext("captured"), redtext("RED")); } if (cflag) { G_bprint(2, "The capture took %.1f seconds\n", cflag->cnt2); } other->s.v.frags += CAPTURE_BONUS; other->ps.ctf_points += CAPTURE_BONUS; other->ps.caps++; // loop through all players on team to give bonus for (p = world; (p = find_plr(p));) { p->s.v.items -= ((int)p->s.v.items & (IT_KEY1 | IT_KEY2)); if (streq(getteam(p), getteam(other))) { if (p->return_flag_time + RETURN_ASSIST_TIME > g_globalvars.time) { p->return_flag_time = -1; p->s.v.frags += RETURN_ASSIST_BONUS; p->ps.ctf_points += RETURN_ASSIST_BONUS; G_bprint(2, "%s gets an assist for returning his flag!\n", p->netname); } if (p->carrier_frag_time + CARRIER_ASSIST_TIME > g_globalvars.time) { p->carrier_frag_time = -1; p->s.v.frags += CARRIER_ASSIST_BONUS; p->ps.ctf_points += CARRIER_ASSIST_BONUS; G_bprint(2, "%s gets an assist for fragging the flag carrier!\n", p->netname); } if (p != other) { p->s.v.frags += TEAM_BONUS; p->ps.ctf_points += TEAM_BONUS; } } else { p->carrier_hurt_time = -1; } } RegenFlags(true); k_nochange = 0; // Set it so it should update scores at next attempt. refresh_plus_scores(); return; } return; } else if (self->cnt == FLAG_DROPPED) { other->s.v.frags += RETURN_BONUS; other->ps.ctf_points += RETURN_BONUS; other->ps.returns++; other->return_flag_time = g_globalvars.time; sound(other, CHAN_FLAG, self->noise1, 1, ATTN_NONE); RegenFlag(self); G_bprint(2, "%s", other->netname); if (self->k_teamnumber == 1) { G_bprint(2, " %s the %s flag!\n", redtext("returned"), redtext("RED")); } else { G_bprint(2, " %s the %s flag!\n", redtext("returned"), redtext("BLUE")); } k_nochange = 0; // Set it so it should update scores at next attempt. refresh_plus_scores(); return; } } if (strneq(getteam(other), "red") && strneq(getteam(other), "blue")) { return; } refresh_plus_scores(); // update players status bar faster // Pick up the flag sound(other, CHAN_FLAG, self->noise, 1, ATTN_NONE); other->ctf_flag |= CTF_FLAG; other->s.v.items = (int)other->s.v.items | (int)self->s.v.items; self->cnt = FLAG_CARRIED; self->s.v.solid = SOLID_NOT; self->s.v.owner = EDICT_TO_PROG(other); owner = PROG_TO_EDICT(self->s.v.owner); owner->ps.pickups++; G_bprint(2, "%s", other->netname); if (streq(getteam(other), "red")) { G_bprint(2, " %s the %s flag!\n", redtext("got"), redtext("BLUE")); owner->s.v.effects = (int)owner->s.v.effects | EF_FLAG2; } else { G_bprint(2, " %s the %s flag!\n", redtext("got"), redtext("RED")); owner->s.v.effects = (int)owner->s.v.effects | EF_FLAG1; } setmodel(self, ""); } void FlagResetOwner(void) { self->think = (func_t) FlagThink; self->touch = (func_t) FlagTouch; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.owner = EDICT_TO_PROG(self); } void TossFlag(void) { PlayerDropFlag(self, true); } void PlayerDropFlag(gedict_t *player, qbool tossed) { gedict_t *flag; char *cn; if (!(player->ctf_flag & CTF_FLAG)) { return; } if (streq(getteam(player), "red")) { cn = "item_flag_team2"; } else { cn = "item_flag_team1"; } flag = find(world, FOFCLSN, cn); if (flag) { DropFlag(flag, tossed); } } void DropFlag(gedict_t *flag, qbool tossed) { gedict_t *p = PROG_TO_EDICT(flag->s.v.owner); gedict_t *p1; p->ctf_flag -= (p->ctf_flag & CTF_FLAG); p->s.v.effects -= ((int)p->s.v.effects & ( EF_FLAG1 | EF_FLAG2)); p->s.v.items -= ((int)p->s.v.items & (int)flag->s.v.items); setorigin(flag, PASSVEC3(p->s.v.origin)); flag->s.v.origin[2] -= 24; flag->cnt = FLAG_DROPPED; if (tossed) { trap_makevectors(p->s.v.v_angle); if (p->s.v.v_angle[0]) { flag->s.v.velocity[0] = g_globalvars.v_forward[0] * 300 + g_globalvars.v_up[0] * 200; flag->s.v.velocity[1] = g_globalvars.v_forward[1] * 300 + g_globalvars.v_up[1] * 200; flag->s.v.velocity[2] = g_globalvars.v_forward[2] * 300 + g_globalvars.v_up[2] * 200; } else { aim(flag->s.v.velocity); VectorScale(flag->s.v.velocity, 300, flag->s.v.velocity); flag->s.v.velocity[2] = 200; } } else { SetVector(flag->s.v.velocity, 0, 0, 300); } flag->s.v.flags = FL_ITEM; flag->s.v.solid = SOLID_TRIGGER; flag->s.v.movetype = MOVETYPE_TOSS; setmodel(flag, flag->mdl); setsize(flag, -16, -16, 0, 16, 16, 74); flag->super_time = g_globalvars.time + FLAG_RETURN_TIME; if (tossed) { flag->s.v.nextthink = g_globalvars.time + 0.75; flag->think = (func_t) FlagResetOwner; } else { flag->s.v.owner = EDICT_TO_PROG(flag); } G_bprint(2, "%s", p->netname); if (streq(getteam(p), "red")) { G_bprint(2, " %s the %s flag!\n", tossed ? redtext("tossed") : redtext("lost"), redtext("BLUE")); } else { G_bprint(2, " %s the %s flag!\n", tossed ? redtext("tossed") : redtext("lost"), redtext("RED")); } for (p1 = world; (p1 = find_plr(p1));) { if (strneq(getteam(p), getteam(p1))) { p1->carrier_hurt_time = -1; } } refresh_plus_scores(); // update players status bar faster } void FlagStatus(void) { gedict_t *flag1, *flag2; if (!isCTF()) { return; } flag1 = find(world, FOFCLSN, "item_flag_team1"); flag2 = find(world, FOFCLSN, "item_flag_team2"); if (!flag1 || !flag2) { return; } if (self->ct == ctSpec) { switch ((int)flag1->cnt) { case FLAG_AT_BASE: G_sprint(self, 2, "The %s flag is in base.\n", redtext("RED")); break; case FLAG_CARRIED: G_sprint(self, 2, "%s has the %s flag.\n", PROG_TO_EDICT(flag1->s.v.owner)->netname, redtext("RED")); break; case FLAG_DROPPED: G_sprint(self, 2, "The %s flag is lying about.\n", redtext("RED")); break; } switch ((int)flag2->cnt) { case FLAG_AT_BASE: G_sprint(self, 2, "The %s flag is in base. ", redtext("BLUE")); break; case FLAG_CARRIED: G_sprint(self, 2, "%s has the %s flag. ", PROG_TO_EDICT(flag1->s.v.owner)->netname, redtext("BLUE")); break; case FLAG_DROPPED: G_sprint(self, 2, "The %s flag is lying about. ", redtext("BLUE")); break; } return; } // Swap flags so that flag1 is "your" flag if (streq(getteam(self), "blue")) { gedict_t *swap = flag1; flag1 = flag2; flag2 = swap; } switch ((int)flag1->cnt) { case FLAG_AT_BASE: G_sprint(self, 2, "Your flag is in base. "); break; case FLAG_CARRIED: G_sprint(self, 2, "%s has your flag. ", PROG_TO_EDICT(flag1->s.v.owner)->netname); break; case FLAG_DROPPED: G_sprint(self, 2, "Your flag is lying about. "); break; } switch ((int)flag2->cnt) { case FLAG_AT_BASE: G_sprint(self, 2, "The enemy flag is in their base.\n"); break; case FLAG_CARRIED: if (self == PROG_TO_EDICT(flag2->s.v.owner)) G_sprint(self, 2, "You have the enemy flag.\n"); else G_sprint(self, 2, "%s has the enemy flag.\n", PROG_TO_EDICT(flag2->s.v.owner)->netname); break; case FLAG_DROPPED: G_sprint(self, 2, "The enemy flag is lying about.\n"); break; default: G_sprint(self, 2, "\n"); } } void CTF_CheckFlagsAsKeys(void) { gedict_t *flag1, *flag2; if (!isCTF()) { return; } flag1 = find(world, FOFCLSN, "item_flag_team1"); // RED flag2 = find(world, FOFCLSN, "item_flag_team2"); // BLUE if (!flag1 || !flag2) { return; } // remove keys/flags. self->s.v.items = (int)self->s.v.items & ~(IT_KEY1 | IT_KEY2); // add gold/RED. if (flag1->cnt != FLAG_AT_BASE) { self->s.v.items = (int)self->s.v.items | IT_KEY2; } // add silver/BLUE. if (flag2->cnt != FLAG_AT_BASE) { self->s.v.items = (int)self->s.v.items | IT_KEY1; } } void norunes(void) { if (match_in_progress && !k_matchLess) { return; } if (!isCTF()) { G_sprint(self, 2, "Can't do this in non CTF mode\n"); return; } cvar_toggle_msg(self, "k_ctf_runes", redtext("runes")); // In matchless mode, toggling runes normally won't do anything since match is already in progress. Call this to handle this scenario. if (k_matchLess) { // If a player is carrying a rune when runes are disabled, get rid of it if (!cvar("k_ctf_runes")) { gedict_t *p; for (p = world; (p = find_plr(p));) { p->ctf_flag -= (p->ctf_flag & (CTF_RUNE_MASK)); p->maxspeed = cvar("sv_maxspeed"); // Reset speed, in case was carrying haste } } SpawnRunes(cvar("k_ctf_runes")); // Toggle runes } } void nohook(void) { if (match_in_progress && !k_matchLess) { return; } if (!isCTF()) { G_sprint(self, 2, "Can't do this in non CTF mode\n"); return; } cvar_toggle_msg(self, "k_ctf_hook", redtext("hook")); // In matchless mode, toggling hook normally won't do anything since match is already in progress. Call this to handle this scenario. if (k_matchLess) { if (cvar("k_ctf_hook")) { AddHook(true); } else { AddHook(false); } } } void noga(void) { if (match_in_progress && !k_matchLess) { return; } if (!isCTF()) { G_sprint(self, 2, "Can't do this in non CTF mode\n"); return; } cvar_toggle_msg(self, "k_ctf_ga", redtext("green armor")); } void mctf(void) { if (match_in_progress && !k_matchLess) { return; } if (!isCTF()) { G_sprint(self, 2, "Can't do this in non CTF mode\n"); return; } if (!cvar("k_ctf_hook") && !cvar("k_ctf_runes")) { G_sprint(self, 2, "Already done\n"); return; } cvar_fset("k_ctf_hook", 0); cvar_fset("k_ctf_runes", 0); G_sprint(self, 2, "%s turn off: %s\n", getname(self), redtext("hook & runes")); // In matchless mode, toggling runes and hook normally won't do anything since match is already in progress. Call this to handle this scenario. if (k_matchLess) { // If a player is carrying a rune when runes are disabled, get rid of it if (!cvar("k_ctf_runes")) { gedict_t *p; for (p = world; (p = find_plr(p));) { p->ctf_flag -= (p->ctf_flag & (CTF_RUNE_MASK)); p->maxspeed = cvar("sv_maxspeed"); // Reset speed, in case was carrying haste } } SpawnRunes(0); AddHook(false); } } void CTFBasedSpawn(void) { if (match_in_progress && !k_matchLess) { return; } if (!isCTF()) { G_sprint(self, 2, "Can't do this in non CTF mode\n"); return; } if (cvar("k_ctf_based_spawn") && (find_cnt(FOFCLSN, "info_player_deathmatch") <= 1)) { G_sprint(self, 2, "Spawn on base enforced due to map limitation\n"); return; } cvar_toggle_msg(self, "k_ctf_based_spawn", redtext("spawn on base")); } void CTF_Obituary(gedict_t *targ, gedict_t *attacker) { qbool carrier_bonus = false; qbool flagdefended = false; gedict_t *head; char *attackerteam; if (!isCTF()) { return; } attackerteam = getteam(attacker); // 2 point bonus for killing enemy flag carrier if (targ->ctf_flag & CTF_FLAG) { attacker->ps.c_frags++; attacker->s.v.frags += 2; attacker->ps.ctf_points += 2; attacker->carrier_frag_time = g_globalvars.time; //G_sprint( attacker, 1, "Enemy flag carrier killed: 2 bonus frags\n" ); } // defending carrier from aggressive player if ((targ->carrier_hurt_time + CARRIER_DEFEND_TIME > g_globalvars.time) && !(attacker->ctf_flag & CTF_FLAG)) { carrier_bonus = true; attacker->ps.c_defends++; attacker->s.v.frags += 2; attacker->ps.ctf_points += 2; // Yes, aggressive is spelled wrong.. but dont want to fix now and break stat parsers G_bprint(2, "%s defends %s's flag carrier against an aggressive enemy\n", attacker->netname, streq(getteam(attacker), "red") ? redtext("RED") : redtext("BLUE")); } head = trap_findradius(world, targ->s.v.origin, 400); while (head) { if (head->ct == ctPlayer) { if ((head->ctf_flag & CTF_FLAG) && (head != attacker) && streq(getteam(head), getteam(attacker)) && !carrier_bonus) { attacker->ps.c_defends++; attacker->s.v.frags++; attacker->ps.ctf_points++; G_bprint(2, "%s defends %s's flag carrier\n", attacker->netname, streq(getteam(attacker), "red") ? redtext("RED") : redtext("BLUE")); } } if ((streq(getteam(attacker), "red") && streq(head->classname, "item_flag_team1")) || (streq(getteam(attacker), "blue") && streq(head->classname, "item_flag_team2"))) { flagdefended = true; attacker->ps.f_defends++; attacker->s.v.frags += 2; attacker->ps.ctf_points += 2; G_bprint(2, "%s defends the %s flag\n", attacker->netname, streq(getteam(attacker), "red") ? redtext("RED") : redtext("BLUE")); } head = trap_findradius(head, targ->s.v.origin, 400); } // Defend bonus if attacker is close to flag even if target is not head = trap_findradius(world, attacker->s.v.origin, 400); while (head) { if ((streq(head->classname, "item_flag_team1") && streq(attackerteam, "red")) || (streq(head->classname, "item_flag_team2") && streq(attackerteam, "blue"))) { if (!flagdefended) { attacker->ps.f_defends++; attacker->s.v.frags += 2; attacker->ps.ctf_points += 2; G_bprint(2, "%s defends the %s flag\n", attacker->netname, streq(attackerteam, "red") ? redtext("RED") : redtext("BLUE")); } } head = trap_findradius(head, attacker->s.v.origin, 400); } } QW-Group-ktx-d05d6ca/src/doors.c000066400000000000000000000547111475442401000165210ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" #define DOOR_START_OPEN 1 #define DOOR_DONT_LINK 4 #define DOOR_GOLD_KEY 8 #define DOOR_SILVER_KEY 16 #define DOOR_TOGGLE 32 /* Doors are similar to buttons, but can spawn a fat trigger field around them to open without a touch, and they link together to form simultanious double/quad doors. Door.owner is the master door. If there is only one door, it points to itself. If multiple doors, all will point to a single one. Door.enemy chains from the master door through all doors linked in the chain. */ /* ============================================================================= THINK FUNCTIONS ============================================================================= */ //#define STATE_TOP 0; //#define STATE_BOTTOM 1; //#define STATE_UP 2; //#define STATE_DOWN 3; void door_blocked(void); void door_hit_top(void); void door_hit_bottom(void); void door_go_down(void); void door_go_up(void); void door_fire(void); void door_blocked(void) { other->deathtype = dtSQUISH; T_Damage(other, self, PROG_TO_EDICT(self->s.v.goalentity), self->dmg); // if a door has a negative wait, it would never come back if blocked, // so let it just squash the object to death real fast if (self->wait >= 0) { if (self->state == STATE_DOWN) { door_go_up(); } else { door_go_down(); } } } void door_hit_top(void) { sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->state = STATE_TOP; #ifdef BOT_SUPPORT if (bots_enabled()) { BotEventDoorHitTop(self); } #endif if ((int)(self->s.v.spawnflags) & DOOR_TOGGLE) { return; // don't come down automatically } self->think = (func_t) door_go_down; self->s.v.nextthink = self->s.v.ltime + self->wait; } void door_hit_bottom(void) { sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->state = STATE_BOTTOM; #ifdef BOT_SUPPORT if (bots_enabled()) { BotEventDoorHitBottom(self); } #endif } void door_go_down(void) { sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); if (self->s.v.max_health) { self->s.v.takedamage = DAMAGE_YES; self->s.v.health = self->s.v.max_health; } self->state = STATE_DOWN; SUB_CalcMove(self->pos1, self->speed, door_hit_bottom); } void door_go_up(void) { if (self->state == STATE_UP) { return; // allready going up } if (self->state == STATE_TOP) { // reset top wait time self->s.v.nextthink = self->s.v.ltime + self->wait; return; } sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); self->state = STATE_UP; SUB_CalcMove(self->pos2, self->speed, door_hit_top); SUB_UseTargets(); } /* ============================================================================= ACTIVATION FUNCTIONS ============================================================================= */ void door_fire(void) { gedict_t *oself, *starte; if (PROG_TO_EDICT(self->s.v.owner) != self) { G_Error("door_fire: self.owner != self"); } // play use key sound if (self->s.v.items) { sound(self, CHAN_VOICE, self->noise4, 1, ATTN_NORM); } self->message = 0; // no more message oself = self; if ((int)(self->s.v.spawnflags) & DOOR_TOGGLE) { if ((self->state == STATE_UP) || (self->state == STATE_TOP)) { starte = self; do { door_go_down(); self = PROG_TO_EDICT(self->s.v.enemy); } while ((self != starte) && (self != world)); self = oself; return; } } // trigger all paired doors starte = self; do { self->s.v.goalentity = EDICT_TO_PROG(activator); // Who fired us door_go_up(); self = PROG_TO_EDICT(self->s.v.enemy); } while ((self != starte) && (self != world)); self = oself; } void door_use(void) { gedict_t *oself; self->message = ""; // door message are for touch only PROG_TO_EDICT(self->s.v.owner)->message = ""; PROG_TO_EDICT(self->s.v.enemy)->message = ""; oself = self; self = PROG_TO_EDICT(self->s.v.owner); door_fire(); self = oself; } void door_trigger_touch(void) { // return if countdown or map frozen if (!k_practice) // #practice mode# { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } } if (ISDEAD(other)) { return; } if (g_globalvars.time < self->attack_finished) { return; } self->attack_finished = g_globalvars.time + 1; activator = other; self = PROG_TO_EDICT(self->s.v.owner); door_use(); } void door_killed(void) { gedict_t *oself; if (!k_practice) // #practice mode# { if (match_in_progress != 2) { return; } } oself = self; self = PROG_TO_EDICT(self->s.v.owner); self->s.v.health = self->s.v.max_health; self->s.v.takedamage = DAMAGE_NO; // wil be reset upon return door_use(); self = oself; } /* ================ door_touch Prints messages and opens key doors ================ */ void door_touch(void) { char *msg; // return if countdown or map frozen if (!k_practice) // #practice mode# { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } } if (other->ct != ctPlayer) { return; } if (PROG_TO_EDICT(self->s.v.owner)->attack_finished > g_globalvars.time) { return; } PROG_TO_EDICT(self->s.v.owner)->attack_finished = g_globalvars.time + 2; msg = PROG_TO_EDICT(self->s.v.owner)->message; if (msg && msg[0]) { G_centerprint(other, "%s", PROG_TO_EDICT(self->s.v.owner)->message); sound(other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM); } // key door stuff if (self->s.v.items == 0) { return; } // FIXME: blink key on player's status bar if (((int)self->s.v.items & (int)other->s.v.items) != self->s.v.items) { if (PROG_TO_EDICT(self->s.v.owner)->s.v.items == IT_KEY1) { if (world->worldtype == 2) { G_centerprint(other, "You need the silver keycard"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } else if (world->worldtype == 1) { G_centerprint(other, "You need the silver runekey"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } else if (world->worldtype == 0) { G_centerprint(other, "You need the silver key"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } } else { if (world->worldtype == 2) { G_centerprint(other, "You need the gold keycard"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } else if (world->worldtype == 1) { G_centerprint(other, "You need the gold runekey"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } else if (world->worldtype == 0) { G_centerprint(other, "You need the gold key"); sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } } return; } other->s.v.items -= self->s.v.items; self->touch = (func_t) SUB_Null; if (self->s.v.enemy) { PROG_TO_EDICT(self->s.v.enemy)->touch = (func_t)SUB_Null; // get paired door } door_use(); } /* ============================================================================= SPAWNING FUNCTIONS ============================================================================= */ gedict_t* spawn_field(vec3_t fmins, vec3_t fmaxs) { gedict_t *trigger; trigger = spawn(); trigger->s.v.movetype = MOVETYPE_NONE; trigger->s.v.solid = SOLID_TRIGGER; trigger->s.v.owner = EDICT_TO_PROG(self); trigger->touch = (func_t) door_trigger_touch; setsize(trigger, fmins[0] - 60, fmins[1] - 60, fmins[2] - 8, fmaxs[0] + 60, fmaxs[1] + 60, fmaxs[2] + 8); return trigger; } qbool EntitiesTouching(gedict_t *e1, gedict_t *e2) { if (e1->s.v.mins[0] > e2->s.v.maxs[0]) { return false; } if (e1->s.v.mins[1] > e2->s.v.maxs[1]) { return false; } if (e1->s.v.mins[2] > e2->s.v.maxs[2]) { return false; } if (e1->s.v.maxs[0] < e2->s.v.mins[0]) { return false; } if (e1->s.v.maxs[1] < e2->s.v.mins[1]) { return false; } if (e1->s.v.maxs[2] < e2->s.v.mins[2]) { return false; } return true; } /* ============= LinkDoors ============= */ void LinkDoors(void) { gedict_t *t, *starte; vec3_t cmins, cmaxs; if (self->s.v.enemy) { return; // already linked by another door } if ((int)(self->s.v.spawnflags) & 4) { self->s.v.owner = self->s.v.enemy = EDICT_TO_PROG(self); return; // don't want to link this door } VectorCopy(self->s.v.mins, cmins); VectorCopy(self->s.v.maxs, cmaxs); //cmins = self->s.v.mins; //cmaxs = self->s.v.maxs; starte = self; t = self; do { self->s.v.owner = EDICT_TO_PROG(starte); // master door if (ISLIVE(self)) { starte->s.v.health = self->s.v.health; } if (self->targetname) { starte->targetname = self->targetname; } if (strneq(self->message, "")) { starte->message = self->message; } t = find(t, FOFCLSN, self->classname); if (!t) { self->s.v.enemy = EDICT_TO_PROG(starte); // make the chain a loop // shootable, fired, or key doors just needed the owner/enemy links, // they don't spawn a field self = PROG_TO_EDICT(self->s.v.owner); if (ISLIVE(self)) { return; } if (self->targetname) { return; } if (self->s.v.items) { return; } PROG_TO_EDICT(self->s.v.owner)->trigger_field = spawn_field(cmins, cmaxs); return; } if (EntitiesTouching(self, t)) { if (t->s.v.enemy) { G_Error("cross connected doors"); } self->s.v.enemy = EDICT_TO_PROG(t); self = t; if (t->s.v.mins[0] < cmins[0]) { cmins[0] = t->s.v.mins[0]; } if (t->s.v.mins[1] < cmins[1]) { cmins[1] = t->s.v.mins[1]; } if (t->s.v.mins[2] < cmins[2]) { cmins[2] = t->s.v.mins[2]; } if (t->s.v.maxs[0] > cmaxs[0]) { cmaxs[0] = t->s.v.maxs[0]; } if (t->s.v.maxs[1] > cmaxs[1]) { cmaxs[1] = t->s.v.maxs[1]; } if (t->s.v.maxs[2] > cmaxs[2]) { cmaxs[2] = t->s.v.maxs[2]; } } } while (1); } /*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE if two doors touch, they are assumed to be connected and operate as a unit. TOGGLE causes the door to wait in both the start and end states for a trigger event. START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors). Key doors are allways wait -1. "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" 0) no sound 1) stone 2) base 3) stone chain 4) screechy metal */ void SP_func_door(void) { float tmp; if (world->worldtype == 0) { trap_precache_sound("doors/medtry.wav"); trap_precache_sound("doors/meduse.wav"); self->noise3 = "doors/medtry.wav"; self->noise4 = "doors/meduse.wav"; } else if (world->worldtype == 1) { trap_precache_sound("doors/runetry.wav"); trap_precache_sound("doors/runeuse.wav"); self->noise3 = "doors/runetry.wav"; self->noise4 = "doors/runeuse.wav"; } else if (world->worldtype == 2) { trap_precache_sound("doors/basetry.wav"); trap_precache_sound("doors/baseuse.wav"); self->noise3 = "doors/basetry.wav"; self->noise4 = "doors/baseuse.wav"; } else { G_Printf("no worldtype set!\n"); } if (self->s.v.sounds == 0) { // trap_precache_sound( "misc/null.wav" ); // trap_precache_sound( "misc/null.wav" ); // self->noise1 = "misc/null.wav"; // self->noise2 = "misc/null.wav"; // qqshka: shut up null.wav, have some artefact, we can hear self->noise1 = ""; self->noise2 = ""; } if (self->s.v.sounds == 1) { trap_precache_sound("doors/drclos4.wav"); trap_precache_sound("doors/doormv1.wav"); self->noise1 = "doors/drclos4.wav"; self->noise2 = "doors/doormv1.wav"; } if (self->s.v.sounds == 2) { trap_precache_sound("doors/hydro1.wav"); trap_precache_sound("doors/hydro2.wav"); self->noise2 = "doors/hydro1.wav"; self->noise1 = "doors/hydro2.wav"; } if (self->s.v.sounds == 3) { trap_precache_sound("doors/stndr1.wav"); trap_precache_sound("doors/stndr2.wav"); self->noise2 = "doors/stndr1.wav"; self->noise1 = "doors/stndr2.wav"; } if (self->s.v.sounds == 4) { trap_precache_sound("doors/ddoor1.wav"); trap_precache_sound("doors/ddoor2.wav"); self->noise1 = "doors/ddoor2.wav"; self->noise2 = "doors/ddoor1.wav"; } SetMovedir(); self->s.v.max_health = self->s.v.health; self->s.v.solid = SOLID_BSP; self->s.v.movetype = MOVETYPE_PUSH; setorigin(self, PASSVEC3(self->s.v.origin)); setmodel(self, self->model); self->classname = "door"; self->blocked = (func_t) door_blocked; self->use = (func_t) door_use; if ((int)(self->s.v.spawnflags) & DOOR_SILVER_KEY) { self->s.v.items = IT_KEY1; } if ((int)(self->s.v.spawnflags) & DOOR_GOLD_KEY) { self->s.v.items = IT_KEY2; } if (!self->speed) { self->speed = 100; } if (!self->wait) { self->wait = 3; } if (!self->lip) { self->lip = 8; } if (!self->dmg) { self->dmg = 2; } VectorCopy(self->s.v.origin, self->pos1); // tmp = fabs(DotProduct(self->s.v.movedir, self->s.v.size)) - self->lip; self->pos2[0] = self->pos1[0] + self->s.v.movedir[0] * tmp; self->pos2[1] = self->pos1[1] + self->s.v.movedir[1] * tmp; self->pos2[2] = self->pos1[2] + self->s.v.movedir[2] * tmp; // DOOR_START_OPEN is to allow an entity to be lighted in the closed position // but spawn in the open position if ((int)(self->s.v.spawnflags) & DOOR_START_OPEN) { setorigin(self, PASSVEC3(self->pos2)); VectorCopy(self->pos1, self->pos2); VectorCopy(self->s.v.origin, self->pos1); } self->state = STATE_BOTTOM; if (ISLIVE(self)) { self->s.v.takedamage = DAMAGE_YES; self->th_die = door_killed; } if (self->s.v.items) { self->wait = -1; } self->touch = (func_t) door_touch; // LinkDoors can't be done until all of the doors have been spawned, so // the sizes can be detected properly. self->think = (func_t) LinkDoors; self->s.v.nextthink = self->s.v.ltime + 0.1; } /* ============================================================================= SECRET DOORS ============================================================================= */ void fd_secret_move1(void); void fd_secret_move2(void); void fd_secret_move3(void); void fd_secret_move4(void); void fd_secret_move5(void); void fd_secret_move6(void); void fd_secret_done(void); #define SECRET_OPEN_ONCE 1 // stays open #define SECRET_1ST_LEFT 2 // 1st move is left of arrow #define SECRET_1ST_DOWN 4 // 1st move is down from arrow #define SECRET_NO_SHOOT 8 // only opened by trigger #define SECRET_YES_SHOOT 16 // shootable even if targeted #define SECRET_NEVER 32 // lock it shut, CTF ONLY. void fd_secret_use(gedict_t *attacker, float take) { float temp; if (!k_practice) // #practice mode# { if (match_in_progress != 2) { return; } } self->s.v.health = 10000; // exit if still moving around... if (!VectorCompare(self->s.v.origin, self->s.v.oldorigin)) { return; } self->message = 0; // no more message //activator=attacker; SUB_UseTargets(); // fire all targets / killtargets if (isCTF() && ((int)(self->s.v.spawnflags) & SECRET_NEVER)) { return; // it never opens } if (!((int)(self->s.v.spawnflags) & SECRET_NO_SHOOT)) { self->th_pain = (th_pain_funcref_t)(0); //SUB_Null; self->s.v.takedamage = DAMAGE_NO; } VectorClear(self->s.v.velocity); // Make a sound, wait a little... sound(self, CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->s.v.nextthink = self->s.v.ltime + 0.1; temp = 1 - ((int)(self->s.v.spawnflags) & SECRET_1ST_LEFT); // 1 or -1 trap_makevectors(self->mangle); if (self->t_width == 0) { if ((int)(self->s.v.spawnflags) & SECRET_1ST_DOWN) { self->t_width = fabs(DotProduct(g_globalvars.v_up, self->s.v.size)); } else { self->t_width = fabs(DotProduct(g_globalvars.v_right, self->s.v.size)); } } if (self->t_length == 0) { self->t_length = fabs(DotProduct(g_globalvars.v_forward, self->s.v.size)); } if ((int)(self->s.v.spawnflags) & SECRET_1ST_DOWN) { self->dest1[0] = self->s.v.origin[0] - g_globalvars.v_up[0] * self->t_width; self->dest1[1] = self->s.v.origin[1] - g_globalvars.v_up[1] * self->t_width; self->dest1[2] = self->s.v.origin[2] - g_globalvars.v_up[2] * self->t_width; } else { self->dest1[0] = self->s.v.origin[0] + g_globalvars.v_right[0] * (self->t_width * temp); self->dest1[1] = self->s.v.origin[1] + g_globalvars.v_right[1] * (self->t_width * temp); self->dest1[2] = self->s.v.origin[2] + g_globalvars.v_right[2] * (self->t_width * temp); } self->dest2[0] = self->dest1[0] + g_globalvars.v_forward[0] * self->t_length; self->dest2[1] = self->dest1[1] + g_globalvars.v_forward[1] * self->t_length; self->dest2[2] = self->dest1[2] + g_globalvars.v_forward[2] * self->t_length; SUB_CalcMove(self->dest1, self->speed, fd_secret_move1); sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); } // Wait after first movement... void fd_secret_move1(void) { self->s.v.nextthink = self->s.v.ltime + 1.0; self->think = (func_t) fd_secret_move2; sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } // Start moving sideways w/sound... void fd_secret_move2(void) { sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); SUB_CalcMove(self->dest2, self->speed, fd_secret_move3); } // Wait here until time to go back... void fd_secret_move3(void) { sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); if (!((int)(self->s.v.spawnflags) & SECRET_OPEN_ONCE)) { self->s.v.nextthink = self->s.v.ltime + self->wait; self->think = (func_t) fd_secret_move4; } } // Move backward... void fd_secret_move4(void) { sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); SUB_CalcMove(self->dest1, self->speed, fd_secret_move5); } // Wait 1 second... void fd_secret_move5(void) { self->s.v.nextthink = self->s.v.ltime + 1.0; self->think = (func_t) fd_secret_move6; sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); } void fd_secret_move6(void) { sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); SUB_CalcMove(self->s.v.oldorigin, self->speed, fd_secret_done); } void fd_secret_done(void) { if (!self->targetname || ((int)(self->s.v.spawnflags) & SECRET_YES_SHOOT)) { self->s.v.health = 10000; self->s.v.takedamage = DAMAGE_YES; self->th_pain = fd_secret_use; self->th_die = (void (*)(void)) fd_secret_use; } sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise3, 1, ATTN_NORM); } void secret_blocked(void) { if (g_globalvars.time < self->attack_finished) { return; } self->attack_finished = g_globalvars.time + 0.5; other->deathtype = dtSQUISH; if (self->think1 == fd_secret_move1) { T_Damage(other, self, self, self->dmg * 100); } else { T_Damage(other, self, self, self->dmg); } } /* ================ secret_touch Prints messages ================ */ void secret_touch(void) { // return if countdown or map frozen if (!k_practice) // #practice mode# { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } } if (other->ct != ctPlayer) { return; } if (self->attack_finished > g_globalvars.time) { return; } self->attack_finished = g_globalvars.time + 2; if (self->message) { G_centerprint(other, "%s", self->message); sound(other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM); } } /*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot Basic secret door. Slides back, then to the side. Angle determines direction. wait = # of seconds before coming back 1st_left = 1st move is left of arrow 1st_down = 1st move is down from arrow always_shoot = even if targeted, keep shootable t_width = override WIDTH to move back (or height if going down) t_length = override LENGTH to move sideways "dmg" damage to inflict when blocked (2 default) If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage. "sounds" 1) medieval 2) metal 3) base */ void SP_func_door_secret(void) { if (self->s.v.sounds == 0) { self->s.v.sounds = 3; } if (self->s.v.sounds == 1) { trap_precache_sound("doors/latch2.wav"); trap_precache_sound("doors/winch2.wav"); trap_precache_sound("doors/drclos4.wav"); self->noise1 = "doors/latch2.wav"; self->noise2 = "doors/winch2.wav"; self->noise3 = "doors/drclos4.wav"; } if (self->s.v.sounds == 2) { trap_precache_sound("doors/airdoor1.wav"); trap_precache_sound("doors/airdoor2.wav"); self->noise2 = "doors/airdoor1.wav"; self->noise1 = "doors/airdoor2.wav"; self->noise3 = "doors/airdoor2.wav"; } if (self->s.v.sounds == 3) { trap_precache_sound("doors/basesec1.wav"); trap_precache_sound("doors/basesec2.wav"); self->noise2 = "doors/basesec1.wav"; self->noise1 = "doors/basesec2.wav"; self->noise3 = "doors/basesec2.wav"; } if (self->dmg == 0) { self->dmg = 2; } // Magic formula... VectorCopy(self->s.v.angles, self->mangle); SetVector(self->s.v.angles, 0, 0, 0); self->s.v.solid = SOLID_BSP; self->s.v.movetype = MOVETYPE_PUSH; self->classname = "door"; setmodel(self, self->model); setorigin(self, PASSVEC3(self->s.v.origin)); self->touch = (func_t) secret_touch; self->blocked = (func_t) secret_blocked; self->speed = 50; self->use = (func_t) fd_secret_use; if (!self->targetname || ((int)(self->s.v.spawnflags) & SECRET_YES_SHOOT)) { self->s.v.health = 10000; self->s.v.takedamage = DAMAGE_YES; self->th_pain = fd_secret_use; } VectorCopy(self->s.v.origin, self->s.v.oldorigin); // self.oldorigin = self.origin; if (self->wait == 0) { self->wait = 5; // 5 seconds before closing } } QW-Group-ktx-d05d6ca/src/fb_globals.c000066400000000000000000000143601475442401000174610ustar00rootroot00000000000000#ifdef BOT_SUPPORT // Converted from .qc on 05/02/2016 #include "g_local.h" float predict_dist = 0; gedict_t *test_enemy = 0; gedict_t *current_waiting_bot = 0; gedict_t *dropper = 0; gedict_t *m_P = 0; int m_D = 0; gedict_t *markers[NUMBER_MARKERS] = { 0 }; gedict_t *zone_head[NUMBER_ZONES] = { 0 }; gedict_t *zone_tail[NUMBER_ZONES] = { 0 }; qbool path_normal = false; gedict_t *from_marker = 0; gedict_t *middle_marker = 0; gedict_t *next_marker = 0; gedict_t *to_marker = 0; gedict_t *look_marker = 0; gedict_t *test_marker = 0; gedict_t *prev_marker = 0; gedict_t *goal_entity = 0; float lookahead_time_ = 0; // Safe to replace with self->fb.skill.lookahead_time vec3_t origin_ = { 0 }; float impulse_ = 0; float time_start = 0; float framecount_start = 0; float sv_accelerate = 0; float sv_maxfriction = 0; float sv_accelerate_frametime = 0; float sv_maxspeed = 0; float sv_maxwaterspeed = 0; float half_sv_maxspeed = 0; float inv_sv_maxspeed = 0; float sv_maxstrafespeed = 0; float friction_factor = 0; float old_time = 0; float distance = 0; vec3_t dir_forward = { 0 }; float current_maxspeed = 0; float max_accel_forward = 0; vec3_t desired_accel = { 0 }; vec3_t hor_velocity = { 0 }; vec3_t new_velocity = { 0 }; // Can make local to functions that use it. vec3_t jump_velocity = { 0 }; vec3_t jump_origin = { 0 }; float oldflags = 0; float current_arrow = 0; float content = 0; float content1 = 0; float content2 = 0; float content3 = 0; float fall = 0; float new_fall = 0; float current_fallspot = 0; vec3_t edge_normal = { 0 }; vec3_t self_view = { 0 }; vec3_t testplace = { 0 }; // FIXME: Make local... vec3_t last_clear_velocity = { 0 }; float jumpspeed = 0; float path_score = 0; float look_score = 0; float best_goal_score = 0; //gedict_t* linked_marker_ = 0; vec3_t linked_marker_origin = { 0 }; float goal_score = 0; float goal_score2 = 0; float enemy_score = 0; vec3_t rel_pos = { 0 }; vec3_t rel_pos2 = { 0 }; vec3_t rel_dir = { 0 }; float rel_dist = 0; float rel_time = 0; vec3_t rel_hor_dir = { 0 }; float hor_component = 0; gedict_t *enemy_touch_marker = 0; vec3_t src = { 0 }; vec3_t direction = { 0 }; float risk = 0; float risk_factor = 0; vec3_t enemy_angles = { 0 }; gedict_t *bot = 0; float rnd = 0; gedict_t *spawn_pos = 0; gedict_t *spots = 0; float pcount = 0; gedict_t *thing = 0; float numspots = 0; float totalspots = 0; vec3_t vec1 = { 0 }; vec3_t vec2 = { 0 }; vec3_t vec_ = { 0 }; gedict_t *think_ent = 0; gedict_t *trigger = 0; vec3_t cmins = { 0 }; vec3_t cmaxs = { 0 }; gedict_t *item = 0; vec3_t tmin = { 0 }; vec3_t tmax = { 0 }; float or = 0; float nr = 0; float best_weapon = 0; float score_count = 0; vec3_t item_pos = { 0 }; vec3_t marker_pos = { 0 }; gedict_t *marker_ = 0; gedict_t *marker2 = 0; float zone_time = 0; float real_yaw_ = 0; gedict_t *fireball = 0; gedict_t *bubble = 0; gedict_t *bubble_spawner = 0; vec3_t org_ = { 0 }; float rnd1 = 0; float rnd2 = 0; float rnd3 = 0; float character = 0; float block_ = 0; float char_count = 0; float word_count = 0; float spawnflags_ = 0; float digit = 0; float exponent = 0; float previous_exponent = 0; gedict_t *target_ = 0; float traveltime = 0; float traveltime2 = 0; float traveltime3 = 0; float look_traveltime = 0; float look_traveltime_squared = 0; gedict_t *flag_self = 0; float flag_pos = 0; gedict_t *flag1 = 0; gedict_t *flag2 = 0; gedict_t *tfog = 0; vec3_t weapons_vel = { 0 }; gedict_t *death = 0; gedict_t *trace_ent1 = 0; gedict_t *trace_ent2 = 0; gedict_t *old_self = 0; gedict_t *old_other = 0; float forward = 0; vec3_t start = { 0 }; vec3_t end = { 0 }; int description = 0; float path_time = 0; float component_speed = 0; float dm = 0; float count_ = 0; gedict_t *array_sub_object_ = 0; float bind_char = 0; float dodge_factor = 0; vec3_t hor_normal_vec = { 0 }; vec3_t last_clear_angle = { 0 }; vec3_t velocity_hor_angle = { 0 }; gedict_t *to_zone = 0; gedict_t *search_entity = 0; qbool fb_lg_disabled(void) { return (qbool)((int)cvar("k_disallow_weapons") & IT_LIGHTNING) != 0; } // taken from pr1 implementation float pr1_rint(float f) { if (f > 0) { return (int)(f + 0.5); } else { return (int)(f - 0.5); } } // match.qc qbool HasWeapon(gedict_t *player, int weapon) { return ((int)player->s.v.items & weapon); } qbool enemy_shaft_attack(gedict_t *self, gedict_t *enemy) { if (enemy->ct != ctPlayer) { return false; } return (HasWeapon(enemy, IT_LIGHTNING) && enemy->s.v.ammo_cells && (self->fb.enemy_dist < 630) && (g_globalvars.time < enemy->attack_finished)); } qbool bots_enabled(void) { return (cvar(FB_CVAR_ENABLED) == 1); } static qbool HasRLOrLG(gedict_t *self) { return ((((int)self->s.v.items & IT_ROCKET_LAUNCHER) && (self->s.v.ammo_rockets > 1)) || (((int)self->s.v.items & IT_LIGHTNING) && (self->s.v.ammo_cells > 5))); } static qbool EnemyHasRLorLG(gedict_t *self) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; if (self->s.v.enemy == 0) { return false; } return ((((int)enemy->s.v.items & IT_ROCKET_LAUNCHER) && (enemy->s.v.ammo_rockets > 1)) || (((int)enemy->s.v.items & IT_LIGHTNING) && (enemy->s.v.ammo_cells > 5))); } static qbool IsDanger(gedict_t *self) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; if (self->s.v.enemy == 0) { return false; } if ((self->s.v.health < enemy->s.v.health) && (self->s.v.armorvalue < enemy->s.v.armorvalue) && (self->s.v.armortype < enemy->s.v.armortype) && (self->fb.firepower < enemy->fb.firepower)) { return true; } if (((int)enemy->s.v.items & (IT_INVULNERABILITY | IT_QUAD | IT_INVISIBILITY)) && (!((int)self->s.v.items & (IT_INVULNERABILITY | IT_INVISIBILITY)))) { return false; } return false; } qbool EnemyDefenceless(gedict_t *self) { if (!EnemyHasRLorLG(self) && HasRLOrLG(self)) { return (!IsDanger(self) && (self->s.v.health > 50) && (self->s.v.armorvalue >= 50)); } return false; } gedict_t* FirstZoneMarker(int zone) { return zone_head[zone - 1]; } void AddZoneMarker(gedict_t *marker) { int zone = marker->fb.Z_ - 1; if ((zone < 0) || (zone >= NUMBER_ZONES)) { return; } if (zone_tail[zone]) { zone_tail[zone]->fb.Z_next = marker; zone_tail[zone] = marker; } else { zone_head[zone] = zone_tail[zone] = marker; } marker->fb.Z_head = zone_head[zone]; // FIXME: this can't be trustworthy in future? } #endif QW-Group-ktx-d05d6ca/src/files.c000066400000000000000000000036671475442401000165010ustar00rootroot00000000000000#include "g_local.h" #define MAX_TXTLEN 128 fileHandle_t std_fropen(const char *fmt, ...) { va_list argptr; fileHandle_t handle; char text[MAX_TXTLEN] = { 0 }; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; if (trap_FS_OpenFile(text, &handle, FS_READ_BIN) < 0) { //G_bprint( 2, "Failed to open file: %s\n", text ); return -1; } //G_bprint( 2, "Succesfully opened file: %s\n", text ); return handle; } int std_fgetc(fileHandle_t handle) { char c; int retval; if (handle < 0) { return -2; } retval = trap_FS_ReadFile(&c, 1, handle); //G_bprint( 2, "====> Read char: %d\n", c ); return (retval == 1 ? c : -1); } char* std_fgets(fileHandle_t handle, char *buf, int limit) { int c = '\0'; char *string; if (handle < 0) { return NULL; } string = buf; while (--limit > 0 && ((c = std_fgetc(handle)) != -1)) { if ((*string++ = c) == '\n') { break; } } *string = '\0'; //G_bprint( 2, "====> Read string: %s\n", buf ); return (((c == -1) && (string = buf)) ? NULL : buf); } void std_fclose(fileHandle_t handle) { if (handle < 0) { return; } trap_FS_CloseFile(handle); } // Writing fileHandle_t std_fwopen(const char *fmt, ...) { va_list argptr; fileHandle_t handle; char text[MAX_TXTLEN] = { 0 }; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; if (trap_FS_OpenFile(text, &handle, FS_WRITE_BIN) < 0) { //G_bprint( 2, "Failed to open file: %s\n", text ); return -1; } //G_bprint( 2, "Succesfully opened file: %s\n", text ); return handle; } void std_fprintf(fileHandle_t handle, const char *fmt, ...) { va_list argptr; char text[MAX_TXTLEN] = { 0 }; if (handle < 0) { return; } va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_FS_WriteFile(text, strlen(text), handle); } QW-Group-ktx-d05d6ca/src/func_bob.c000066400000000000000000000044041475442401000171420ustar00rootroot00000000000000#include "g_local.h" // Stripped down port of dumptruckDS's func_bob.qc // progsdump / Arcane Dimensions spawnflags #define BOB_COLLISION 2 #define BOB_NONSOLID 4 // Dimension of the Machine spawnflags // Not yet supported, uses different easing function, might be possible to detect. // https://github.com/id-Software/quake-rerelease-qc/blob/main/quakec_mg1/func_bob.qc #define FUNC_BOB_NONSOLID 1 #define FUNC_BOB_START_ON 2 static void func_bob_timer(void) { vec3_t delta; // Has the cycle completed? if (self->endtime < g_globalvars.time) { // Setup bob cycle and half way point for slowdown self->endtime = g_globalvars.time + self->count; self->distance = g_globalvars.time + (self->count * 0.5f); // Flip direction of bmodel bob self->lefty = 1 - self->lefty; if (self->lefty < 1) { self->t_length = self->height; } else { self->t_length = -self->height; } // Always reset velocity at pivot SetVector(self->s.v.velocity, 0, 0, 0); } if (self->distance < g_globalvars.time) { // Slow down velocity (gradually) VectorScale(self->s.v.velocity, self->waitmin2, self->s.v.velocity); } else { // Speed up velocity (linear/exponentially) self->t_length *= self->waitmin; VectorScale(self->s.v.movedir, self->t_length, delta); VectorAdd(self->s.v.velocity, delta, self->s.v.velocity); } self->s.v.nextthink = self->s.v.ltime + 0.1f; } void SP_func_bob(void) { // Non-solid bobs not implemented yet, remove for now to not block player. if ((int) self->s.v.spawnflags & (BOB_NONSOLID | FUNC_BOB_NONSOLID)) { ent_remove(self); return; } self->s.v.movetype = MOVETYPE_PUSH; self->s.v.solid = SOLID_BSP; setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); SetMovedir(); VectorNormalize(self->s.v.movedir); if (self->height <= 0) { self->height = 8; // Direction intensity } if (self->count < 1) { self->count = 2; // Direction switch timer } if (self->waitmin <= 0) { self->waitmin = 1; // Speed up } if (self->waitmin2 <= 0) { self->waitmin2 = 0.75f; // Slow down } if (self->delay < 0) { self->delay = g_random() + g_random() + g_random(); } self->think = (func_t) func_bob_timer; self->s.v.nextthink = g_globalvars.time + 0.1 + self->delay; } QW-Group-ktx-d05d6ca/src/func_laser.c000066400000000000000000000070211475442401000175040ustar00rootroot00000000000000#include "g_local.h" #define START_OFF 1 #define LASER_SOLID 2 static void laser_helper_think(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); float alpha = ExtFieldGetAlpha(self); if (!((int) owner->s.v.spawnflags & START_OFF)) { ExtFieldSetAlpha(self, alpha * 0.8f + alpha * g_random() * 0.4f); } self->s.v.nextthink = g_globalvars.time + 0.05f; } static void init_laser_noise(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); sound(owner, CHAN_VOICE, owner->noise, 1, ATTN_NORM); self->think = (func_t) laser_helper_think; self->s.v.nextthink = g_globalvars.time + 0.05f; } static void func_laser_touch(void) { // from Copper -- dumptruck_ds if (other->s.v.movetype == MOVETYPE_NOCLIP) { return; } if (other->s.v.takedamage && self->attack_finished < g_globalvars.time) { T_Damage (other, self, self, self->dmg); // add "zap" sound when damage is dealt sound (self, CHAN_WEAPON, self->noise2, 1, ATTN_NORM); self->attack_finished = g_globalvars.time + 0.333f; } } static void func_laser_use(void) { if ((int) self->s.v.spawnflags & START_OFF) { setorigin(self, 0, 0, 0); self->s.v.spawnflags = self->s.v.spawnflags - START_OFF; sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); } else { sound (self, CHAN_VOICE, self->noise1, 1, ATTN_NORM); setorigin(self, 0, 0, 9000); self->s.v.spawnflags = self->s.v.spawnflags + START_OFF; } }; /** * QUAKED func_laser (0 .5 .8) ? START_OFF LASER_SOLID X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY * A toggleable laser, hurts to touch, can be used to block players * START_OFF: Laser starts off. * LASER_SOLID: Laser blocks movement while turned on. * Keys: * "dmg" damage to do on touch. default 1 * "alpha" approximate alpha you want the laser drawn at. default 0.5. alpha will vary by 20% of this value. * "message" message to display when activated (not supported) * "message2" message to display when deactivated (not supported) */ void SP_func_laser(void) { gedict_t *helper; float alpha; setmodel(self, self->model); trap_precache_sound ("buttons/switch02.wav"); trap_precache_sound ("buttons/switch04.wav"); trap_precache_sound ("misc/null.wav"); if ((int) self->s.v.spawnflags & LASER_SOLID) { self->s.v.solid = SOLID_BSP; //so you can shoot between lasers in a single bmodel self->s.v.movetype = MOVETYPE_PUSH; //required becuase of SOLID_BSP } else { self->s.v.solid = SOLID_TRIGGER; self->s.v.movetype = MOVETYPE_NONE; } alpha = ExtFieldGetAlpha(self); if (!alpha) { alpha = 0.5f; } ExtFieldSetAlpha(self, alpha); if (!self->dmg) { self->dmg = 1; } self->use = (func_t) func_laser_use; self->touch = (func_t) func_laser_touch; if ((int) self->s.v.spawnflags & START_OFF) { setorigin(self, 0, 0, 9000); } else { setorigin(self, 0, 0, 0); } if (!strnull(self->noise)) { trap_precache_sound(self->noise); } else { self->noise = "buttons/switch02.wav"; } if (!strnull(self->noise1)) { trap_precache_sound(self->noise1); } else { self->noise1 = "buttons/switch04.wav"; } if (!strnull(self->noise2)) { trap_precache_sound(self->noise2); } else { self->noise2 = "misc/null.wav"; } //spawn a second entity to handle alpha changes, since MOVETYPE_PUSH doesn't support think functions helper = spawn(); helper->s.v.owner = EDICT_TO_PROG(self); helper->s.v.nextthink = g_globalvars.time + 2; ExtFieldSetAlpha(helper, alpha); helper->think = (func_t) init_laser_noise; } QW-Group-ktx-d05d6ca/src/g_cmd.c000066400000000000000000000605141475442401000164420ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ #include "g_local.h" void cmdinfo(void); void cmduinfo(void); void cmd_wreg_do(byte c); void cmd_ack(void); void cmd_al(void); void s_common(gedict_t *from, gedict_t *to, char *msg); void s_p(void); void s_lr(float l); void s_t_do(char *str, char *tname); void s_t(void); void s_m_do(char *str, int m); // do multi print void s_m(void); void multi_do(int from_arg, qbool from_mmode); // set up multi set qbool ClientCommand(void) { char cmd_command[1024]; self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return false; // cmon, u r zombie or etc... } trap_CmdArgv(0, cmd_command, sizeof(cmd_command)); /* { char arg_x[1024]; trap_CmdArgv( 1, arg_x, sizeof( arg_x ) ); G_bprint(2, "ClientCommand '%s' '%s'\n", cmd_command, arg_x); } */ // ack allowed when even classname is not set if (!strcmp(cmd_command, "ack")) { cmd_ack(); return true; } if ((self->ct != ctPlayer) && (self->ct != ctSpec)) { return true; // not connected yet or something } if (cmd_command[0] && !cmd_command[1]) { // one character command, this is wreg command cmd_wreg_do(cmd_command[0]); return true; } else if (only_digits(cmd_command) // strlen(cmd_command) == 3 for now, but I omit this && (DoCommand(atoi(cmd_command)) != DO_OUT_OF_RANGE_CMDS)) { return true; // command may fail in some way, but at least command exist, so return true } else if (DoCommand_Name(cmd_command) != DO_OUT_OF_RANGE_CMDS) { return true; // command may fail in some way, but at least command exist, so return true } return false; } void cmd_ack(void) { int argc = trap_CmdArgc(); char arg_1[64]; if (argc != 2) { return; // something wrong } trap_CmdArgv(1, arg_1, sizeof(arg_1)); if (streq(arg_1, "infoset")) { on_connect(); // qqshka: on_connect is useless IMO, but ktpro compatible on_enter(); } else if (streq(arg_1, "noinfoset")) { on_enter(); } } // i dunno where put this. so put here. // SAY / SAY_TEAM mod handler // { static int k_say_fp_per = 1, k_say_fp_for = 1, k_say_fp_count = 9; // for players static int k_say_fp_per_spec = 1, k_say_fp_for_spec = 1, k_say_fp_count_spec = 9; // for specs static int get_k_say_fp_per(gedict_t *p) { return ((p->ct == ctPlayer) ? k_say_fp_per : k_say_fp_per_spec); } static int get_k_say_fp_for(gedict_t *p) { return ((p->ct == ctPlayer) ? k_say_fp_for : k_say_fp_for_spec); } static int get_k_say_fp_count(gedict_t *p) { return ((p->ct == ctPlayer) ? k_say_fp_count : k_say_fp_count_spec); } typedef struct say_fp_level_s { int fp_count; int fp_per; int fp_for; char *name; } say_fp_level_t; say_fp_level_t say_fp_levels[] = { { 9, 1, 1, "Low" }, { 4, 1, 5, "Medium" }, { 5, 3, 7, "High" } }; int say_fp_levels_cnt = sizeof(say_fp_levels) / sizeof(say_fp_levels[0]); void FixSayFloodProtect(void) { static int k_fp_last = -1; char buf[1024 * 4]; int k_fp = bound(1, cvar("k_fp"), say_fp_levels_cnt); // player int k_fp_spec = bound(1, cvar("k_fp_spec"), say_fp_levels_cnt); // spec // player k_say_fp_count = say_fp_levels[k_fp - 1].fp_count; k_say_fp_per = say_fp_levels[k_fp - 1].fp_per; k_say_fp_for = say_fp_levels[k_fp - 1].fp_for; // spec k_say_fp_count_spec = say_fp_levels[k_fp_spec - 1].fp_count; k_say_fp_per_spec = say_fp_levels[k_fp_spec - 1].fp_per; k_say_fp_for_spec = say_fp_levels[k_fp_spec - 1].fp_for; // retarded/backward compatibility if (k_fp != k_fp_last) { // qqshka: generally mod ignore server floodprot, but if server not support // redirect say/say_team to mod, then try use server floodprot, so // in most cases this code useless. trap_readcmd(va("floodprot %d %d %d\n", k_say_fp_count, k_say_fp_per, k_say_fp_for), buf, sizeof(buf)); G_cprint("%s", buf); } k_fp_last = k_fp; } void fp_toggle(float type) { char *k_fp_name = (type == 1 ? "k_fp" : "k_fp_spec"); int k_fp = bound(1, cvar(k_fp_name), say_fp_levels_cnt); if (!is_adm(self)) { G_sprint(self, 2, "You are not an admin\n"); return; } if (++k_fp > say_fp_levels_cnt) { k_fp = 1; } cvar_fset(k_fp_name, k_fp); FixSayFloodProtect(); G_bprint(2, "%s level %s \x90%s %s %s\x91 %6s\n", type == 1 ? "floodprot" : "spec floodprot", dig3(k_fp), dig3(say_fp_levels[k_fp - 1].fp_count), dig3(say_fp_levels[k_fp - 1].fp_per), dig3(say_fp_levels[k_fp - 1].fp_for), say_fp_levels[k_fp - 1].name); } qbool isSayFlood(gedict_t *p) { int idx; float say_time; idx = bound(0, p->fp_s.last_cmd, MAX_FP_CMDS - 1); say_time = p->fp_s.cmd_time[idx]; if (!cvar("sv_paused") && g_globalvars.time < p->fp_s.locked) { G_sprint(p, PRINT_CHAT, "You can't talk for %d more seconds\n", (int)(p->fp_s.locked - g_globalvars.time + 1)); return true; // flooder } if (!cvar("sv_paused") && say_time && (g_globalvars.time - say_time < get_k_say_fp_per(p))) { G_sprint(p, PRINT_CHAT, "FloodProt: You can't talk for %d seconds.\n", (int)get_k_say_fp_for(p)); p->fp_s.locked = g_globalvars.time + get_k_say_fp_for(p); p->fp_s.warnings += 1; // collected but unused stat return true; // flooder } p->fp_s.cmd_time[idx] = g_globalvars.time; if (++idx >= get_k_say_fp_count(p)) { idx = 0; } p->fp_s.last_cmd = idx; return false; } static int HexToInt(char c) { if (isdigit(c)) { return (c - '0'); } else if ((c >= 'a') && (c <= 'f')) { return (10 + c - 'a'); } else if ((c >= 'A') && (c <= 'F')) { return (10 + c - 'A'); } else { return -1; } } static qbool isSupport_ColoredText(gedict_t *p) { return !iKey(p, "nocolors"); } qbool ClientSay(qbool isTeamSay) { int j, l, mmode, flags; char text[1024] = { 0 }, textuncolored[1024] = { 0 }, text2[1024] = { 0 }, prefix[128] = { 0 }; char arg_2[64], *str, *clr, *name, *team, *result_msg; int sv_spectalk = cvar("sv_spectalk"); int sv_sayteam_to_spec = cvar("sv_sayteam_to_spec"); gedict_t *client, *goal; qbool fake = false, ignore_in_demos, spec_talk = false; self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return true; // cmon, u r zombie or etc... } trap_CmdArgs(str = text, sizeof(text)); if ((str[0] == '"') && (j = strlen(str)) > 2) { str[j - 1] = 0; str++; trap_CmdArgv(0, arg_2, sizeof(arg_2)); strlcat(text2, arg_2, sizeof(text2)); strlcat(text2, " ", sizeof(text2)); strlcat(text2, str, sizeof(text2)); trap_CmdTokenize(text2); } if (f_check && (self->ct == ctPlayer)) { if (!self->f_checkbuf) { return true; // just in case } strlcat(self->f_checkbuf, str, F_CHECK_SIZE); strlcat(self->f_checkbuf, "\n", F_CHECK_SIZE); return true; } if (isSayFlood(self)) { return true; // flooder } trap_CmdArgv(1, arg_2, sizeof(arg_2)); if (streq(arg_2, "s-p")) { s_p(); return true; } if ((l = (streq(arg_2, "s-l") ? 1 : 0)) || (l = (streq(arg_2, "s-r") ? 2 : 0))) { s_lr(l); return true; } if (streq(arg_2, "s-t")) { s_t(); return true; } if (streq(arg_2, "s-m")) { s_m(); return true; } mmode = iKey(self, "*mm"); switch (mmode) { case MMODE_PLAYER: if ((goal = SpecPlayer_by_id(iKey(self, "*mp")))) { s_common(self, goal, str); } else { G_sprint(self, 2, "mmode(player): can't find player\n"); } return true; case MMODE_TEAM: s_t_do(str, ezinfokey(self, "*mt")); return true; case MMODE_MULTI: s_m_do(str, iKey(self, "*mu")); return true; case MMODE_NAME: stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "name \"%s\"\n", str); return true; case MMODE_RCON: /* if ( !VIP_IsFlags(self, VIP_RCON) ) { // just sanity check G_sprint(self, 2, "mmode(rcon): access denied...\n"); } else */ { G_cprint("MM RCON from: %s: %s: %s\n", getname(self), ezinfokey(self, "ip"), str); //trap_redirectcmd(self, va("%s\n", str)); // !!! WARNING: FULL ACCESS TO SERVER CONSOLE !!! } return true; } // { MVDSV //bliP: kick fake -> if (!isTeamSay && cvar("sv_unfake")) { char *ch; for (ch = str; *ch; ch++) { if (*ch == 13) //bliP: 24/9 kickfake to unfake -> { *ch = '#'; } } } //<- // skip ezquake color sequence for (clr = str, j = 0; clr[0]; /* nothing */) { if (clr[0] == '&') { if (clr[1] == 'c' && HexToInt(clr[2]) >= 0 && HexToInt(clr[3]) >= 0 && HexToInt(clr[4]) >= 0) { clr += 5; // skip "&cRGB" continue; } else if (clr[1] == 'r') { clr += 2; // skip "&r" continue; } } textuncolored[(int)bound(0, j, sizeof(textuncolored) - 1)] = clr[0]; clr++; j++; } textuncolored[(int)bound(0, j, sizeof(textuncolored) - 1)] = 0; name = (strnull(self->netname) ? "!noname!" : self->netname); if (self->ct == ctSpec) { if (!sv_spectalk || isTeamSay) { // such messages seen only for specs, // we handle it specially for demos, so when you watch demo you can see that specs talked spec_talk = true; snprintf(prefix, sizeof(prefix), "[SPEC] %s:", name); } else { snprintf(prefix, sizeof(prefix), "%s:", name); } } else { if (isTeamSay) { snprintf(prefix, sizeof(prefix), "(%s):", name); } else { snprintf(prefix, sizeof(prefix), "%s:", name); } } fake = (strchr(str, 13) ? true : false); // check if string contain "$\" G_cprint("%s %s\n", prefix, textuncolored); team = ezinfokey(self, "team"); if (spec_talk) // this should go to demo only { // if k_keepspectalkindemos == 0 then this goes to qtv mvd stream only flags = BPRINT_IGNORECONSOLE | BPRINT_IGNORECLIENTS; flags |= (cvar("k_keepspectalkindemos") ? 0 : BPRINT_QTVONLY); G_bprint_flags(PRINT_CHAT, flags, "%s %s\n", prefix, str); } for (j = 1, client = &(g_edicts[j]); j <= MAX_CLIENTS; j++, client++) { //bliP: everyone sees all -> //if (client->state != cs_spawned) // continue; //<- if ((self->ct == ctSpec) && !sv_spectalk) { if (client->ct != ctSpec) { continue; } } if (isTeamSay) { // the spectator team if (self->ct == ctSpec) { if (client->ct != ctSpec) { continue; } } else { if (self == client) { ; // send msg to self anyway } else if (client->ct == ctSpec) { goal = PROG_TO_EDICT(client->s.v.goalentity); if (!sv_sayteam_to_spec // player can't say_team to spec in this case || !fake // self say_team does't contain $\ so this is treat as private message || ((goal != world && goal->ct == ctPlayer) // spec track player && strneq(team, ezinfokey(goal, "team"))) // spec track player on different team || (!(goal != world && goal->ct == ctPlayer) // spec _not_ track player && strneq(team, ezinfokey(client, "team")))) // spec do not track player and on different team { continue; // on different teams } } else if (coop) { ; // allow team messages to everyone in coop from players. } else if (!isTeam() && !isCTF()) { continue; // non team game } else if (strneq(team, ezinfokey(client, "team"))) { continue; // on different teams } } } // do not put private info in demos: private is team say from player without $\ symbol ignore_in_demos = ((self->ct == ctPlayer && isTeamSay && (!fake || match_in_progress != 2)) || spec_talk); flags = (ignore_in_demos ? SPRINT_IGNOREINDEMO : 0); result_msg = (isSupport_ColoredText(client) ? str : textuncolored); G_sprint_flags(client, PRINT_CHAT, flags, "%s %s\n", prefix, result_msg); } // } MVDSV return true; } // } // { additional communication commands void s_common(gedict_t *from, gedict_t *to, char *msg) { char *ch; if (from == to) { return; // ignore sending text to self } if (match_in_progress && (from->ct != to->ct)) { return; // spec to player or player to spec, disallowed in match } from->s_last_to = to; to->s_last_from = from; for (ch = msg; *ch; ch++) { if (*ch == 13) // kickfake to unfake -> { *ch = ' '; } } G_sprint_flags(to, PRINT_CHAT, SPRINT_IGNOREINDEMO, "[%s->]: %s\n", getname(from), msg); G_sprint_flags(from, PRINT_CHAT, SPRINT_IGNOREINDEMO, "[->%s]: %s\n", getname(to), msg); } void s_p(void) { int argc = trap_CmdArgc(); gedict_t *p; char arg_3[1024], *str; if (argc < 4) { G_sprint(self, 2, "usage: s-p id/name txt\n"); return; } trap_CmdArgv(2, arg_3, sizeof(arg_3)); if ((p = SpecPlayer_by_IDorName(arg_3))) { str = params_str(3, -1); s_common(self, p, str); } else { G_sprint(self, 2, "s-p: client %s not found\n", arg_3); return; } } /* void s_p_cmd() // just redirect /s-p command to /say { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "say s-p %s\n", params_str(1, -1)); } */ void s_lr(float l) { int argc = trap_CmdArgc(); gedict_t *p; char *str; if (argc < 3) { G_sprint(self, 2, "usage: %s txt\n", (l == 1 ? "s-l" : "s-r")); return; } p = (l == 1 ? self->s_last_to : self->s_last_from); if (p && GetUserID(p)) { str = params_str(2, -1); s_common(self, p, str); } else { G_sprint(self, 2, "%s: client not found\n", (l == 1 ? "s-l" : "s-r")); return; } } /* void s_lr_cmd( float l ) // just redirect /s-l or /s-r command to /say { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "say %s %s\n", ( l == 1 ? "s-l" : "s-r" ), params_str(1, -1)); } */ void s_lr_clear(gedict_t *dsc) { gedict_t *p; for (p = world; (p = find_client(p));) { if (p->s_last_to == dsc) { p->s_last_to = NULL; } if (p->s_last_from == dsc) { p->s_last_from = NULL; } } } void s_t_do(char *str, char *tname) { int i; gedict_t *p; char *name, *ch; name = getname(self); for (ch = str; *ch; ch++) { if (*ch == 13) // kickfake to unfake -> { *ch = ' '; } } for (i = 0, p = world; (p = find_client(p));) { if (self == p) // ignore sending text to self { continue; } if (match_in_progress && (self->ct != p->ct)) { continue; // spec to player or player to spec, disallowed in match } if (!((streq(tname, "player") && (p->ct == ctPlayer)) || (streq(tname, "spectator") && (p->ct == ctSpec)) || (streq(tname, "admin") && is_adm(p)) || (streq(tname, getteam(p))))) { continue; } //[sender ]: txt G_sprint(p, PRINT_CHAT, "[%s ]: %s\n", name, tname, str); i++; } if (!i) { G_sprint(self, 2, "s-t: no clients found for team %s\n", tname); return; } G_sprint(self, PRINT_CHAT, "[]: %s\n", tname, str); } void s_t(void) { int argc = trap_CmdArgc(); char arg_3[1024], *str; if (argc < 4) { G_sprint(self, 2, "usage: s-t team txt\n"); return; } str = params_str(3, -1); trap_CmdArgv(2, arg_3, sizeof(arg_3)); s_t_do(str, arg_3); } /* void s_t_cmd() // just redirect /s-t command to /say { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "say s-t %s\n", params_str(1, -1)); } */ void s_m_do(char *str, int m) { int i, bit; gedict_t *p; char *name, *ch; name = getname(self); for (ch = str; *ch; ch++) { if (*ch == 13) // kickfake to unfake -> { *ch = ' '; } } for (i = 0, p = world; (p = find_client(p));) { if (self == p) // ignore sending text to self { continue; } if (match_in_progress && (self->ct != p->ct)) { continue; // spec to player or player to spec, disallowed in match } bit = 1 << (int)(p - g_edicts - 1); if (!(m & bit)) { continue; // not in multi set } //[sender ]: txt G_sprint(p, PRINT_CHAT, "[%s ]: %s\n", name, m, str); i++; } if (!i) { G_sprint(self, 2, "s-m: no clients found\n"); return; } G_sprint(self, PRINT_CHAT, "[]: %s\n", m, str); } void s_m(void) { if (trap_CmdArgc() < 3) { G_sprint(self, 2, "usage: s-m txt\n"); return; } s_m_do(params_str(2, -1), iKey(self, "*mu")); } // "/multi" void multi(void) { multi_do(1, false); } void multi_usage(void) { G_sprint(self, 2, "Usage: multi <=/+/-/\?/\?\?> id1/name1 id2/name2 ...\n"); } #define MMOP_N (0) // none #define MMOP_S (1) // = #define MMOP_P (2) // + #define MMOP_M (3) // - #define MMOP_Q (4) // ? #define MMOP_QQ (5) // ?? void multi_do(int from_arg, qbool from_mmode) { gedict_t *p; char arg_1[1024], arg_2[1024], arg_x[1024], multi[1024]; int argc = trap_CmdArgc(), mmop, k, i, m, bit; trap_CmdArgv(from_arg, arg_1, sizeof(arg_1)); trap_CmdArgv(from_arg + 1, arg_2, sizeof(arg_2)); // argh, this case/hack for "/mmode multi" if (from_mmode && strnull(arg_1)) { m = iKey(self, "*mu"); for (multi[0] = 0, k = 0, i = 0; i < MAX_CLIENTS; i++) { p = &(g_edicts[i + 1]); if (!((p->ct == ctPlayer) || (p->ct == ctSpec))) { continue; // not valid } bit = 1 << i; if (!(m & bit)) { continue; // not in multi set } if (k) { strlcat(multi, ", ", sizeof(multi)); } strlcat(multi, getname(p), sizeof(multi)); k++; } if (k) { SetUserInfo(self, "*mm", va("%d", MMODE_MULTI), SETUSERINFO_STAR); SetUserInfo(self, "*mu", va("%d", m), SETUSERINFO_STAR); G_sprint(self, 2, "mmode(multi): %s\n", multi); } else { G_sprint(self, 2, "mmode(multi): 0 players found\n"); } return; } if (strneq(arg_1, "?") && strnull(arg_2)) { // something like: "/mmode multi =" or /multi =" - too few params multi_usage(); return; } if (streq(arg_1, "=")) { mmop = MMOP_S; } else if (streq(arg_1, "+")) { mmop = MMOP_P; } else if (streq(arg_1, "-")) { mmop = MMOP_M; } else if (streq(arg_1, "?")) { mmop = MMOP_Q; } else if (streq(arg_1, "??")) { mmop = MMOP_QQ; } else { mmop = MMOP_N; } m = 0; // set this for MMOP_S switch (mmop) { case MMOP_P: case MMOP_M: m = iKey(self, "*mu"); case MMOP_S: for (multi[0] = 0, k = 0, i = from_arg + 1; i < argc; i++) { trap_CmdArgv(i, arg_x, sizeof(arg_x)); if (!(p = SpecPlayer_by_IDorName(arg_x)) || (p == self)) { continue; } bit = 1 << (int)(p - g_edicts - 1); if (mmop == MMOP_M) { if (!(m & bit)) { continue; // nothing remove } m &= ~bit; // minus bit } else { if ((m & bit)) { continue; // already set } m |= bit; // plus bit } if (k) { strlcat(multi, ", ", sizeof(multi)); } strlcat(multi, getname(p), sizeof(multi)); k++; } if (k) { if (from_mmode) // allow set up mmode only from /mmode cmd, not from /multi cmd { SetUserInfo(self, "*mm", va("%d", MMODE_MULTI), SETUSERINFO_STAR); } SetUserInfo(self, "*mu", va("%d", m), SETUSERINFO_STAR); // this must be set in both cases G_sprint(self, 2, "multi %s: %s\n", arg_1, multi); } else { G_sprint(self, 2, "multi %s: 0 players found\n", arg_1); } return; case MMOP_Q: case MMOP_QQ: m = (mmop == MMOP_Q ? iKey(self, "*mu") : atoi(arg_2)); for (multi[0] = 0, k = 0, i = 0; i < MAX_CLIENTS; i++) { p = &(g_edicts[i + 1]); if (!((p->ct == ctPlayer) || (p->ct == ctSpec))) { continue; // not valid } bit = 1 << i; if (!(m & bit)) { continue; // not in multi set } if (k) { strlcat(multi, ", ", sizeof(multi)); } strlcat(multi, getname(p), sizeof(multi)); k++; } if (k) { G_sprint(self, 2, "multi %s: %s\n", arg_1, multi); } else { G_sprint(self, 2, "multi %s: 0 players found\n", arg_1); } return; default: multi_usage(); return; } } void mmode_usage(void) { G_sprint(self, 2, "Usage: mmode [params]\n"); } void info_sys_mm_update(gedict_t *p, char *from, char *to) { int mm = atoi(to); int omm = atoi(from); if (mm == omm) { return; } if (mm == MMODE_NONE) { return; } SetUserInfo(p, "*ml", va("%d", mm), SETUSERINFO_STAR); } char* mmode_str(int mmode) { switch (mmode) { case MMODE_NONE: return "none"; case MMODE_PLAYER: return "player"; case MMODE_TEAM: return "team"; case MMODE_MULTI: return "multi"; case MMODE_RCON: return "rcon"; case MMODE_NAME: return "name"; } return "unknown"; } void mmode(void) { qbool set; gedict_t *p = NULL; int argc = trap_CmdArgc(), id, mmode, till; char arg_2[1024], arg_3[1024], *tname, *rcpass; mmode = (argc < 2 ? iKey(self, "*mm") : MMODE_NONE); // try serve "/mmode" cmd without params trap_CmdArgv(1, arg_2, sizeof(arg_2)); // if argc >= 2 trap_CmdArgv(2, arg_3, sizeof(arg_3)); // if argc >= 3 if (argc >= 2) { // try serve cmd "/mmode" with at least one param if (streq(arg_2, "off")) { mmode = MMODE_NONE; } else if (streq(arg_2, "player")) { mmode = MMODE_PLAYER; } else if (streq(arg_2, "team")) { mmode = MMODE_TEAM; } else if (streq(arg_2, "multi")) { mmode = MMODE_MULTI; } else if (streq(arg_2, "name")) { mmode = MMODE_NAME; } else if (streq(arg_2, "rcon")) { mmode = MMODE_RCON; } else if (streq(arg_2, ".") || streq(arg_2, ",")) { p = (streq(arg_2, ".") ? self->s_last_to : self->s_last_from); argc = -1; // hint for code below mmode = MMODE_PLAYER; } else if (streq(arg_2, "last")) { int last = iKey(self, "*ml"); /* if ( last == MMODE_RCON && !VIP_IsFlags(self, VIP_RCON) ) { // just sanity check G_sprint(self, 2, "mmode(rcon): access denied...\n"); return; } */ SetUserInfo(self, "*mm", va("%d", last), SETUSERINFO_STAR); G_sprint(self, 2, "last mmode(%s)\n", mmode_str(last)); return; } else { mmode_usage(); return; } } switch (mmode) { case MMODE_PLAYER: if (argc != -1) // ok apply hint here { p =(argc < 3 ? SpecPlayer_by_id(iKey(self, "*mp")) : SpecPlayer_by_IDorName(arg_3)); } if (!p || !(id = GetUserID(p)) || (p == self)) { G_sprint(self, 2, "mmode(player): can't find player\n"); return; } // check do we need set this values or not if ((set = (mmode != iKey(self, "*mm") || id != iKey(self, "*mp")))) { SetUserInfo(self, "*mm", va("%d", mmode), SETUSERINFO_STAR); SetUserInfo(self, "*mp", va("%d", id), SETUSERINFO_STAR); } G_sprint(self, 2, "mmode(player)%s: %s\n", (set ? " set" : ""), getname(p)); return; case MMODE_TEAM: tname = (argc < 3 ? ezinfokey(self, "*mt") : arg_3); // check do we need set this values or not if ((set = (mmode != iKey(self, "*mm") || strneq(tname, ezinfokey(self, "*mt"))))) { SetUserInfo(self, "*mm", va("%d", mmode), SETUSERINFO_STAR); SetUserInfo(self, "*mt", va("%s", tname), SETUSERINFO_STAR); } G_sprint(self, 2, "mmode(team)%s: %s\n", (set ? " set" : ""), tname); return; case MMODE_MULTI: multi_do(2, true); return; case MMODE_NAME: // check do we need set this values or not if ((set = (mmode != iKey(self, "*mm")))) { SetUserInfo(self, "*mm", va("%d", mmode), SETUSERINFO_STAR); } G_sprint(self, 2, "mmode(name)%s\n", (set ? " set" : "")); return; case MMODE_RCON: rcpass = cvar_string("rcon_password"); till = Q_rint(self->k_adm_lasttime + 5 - g_globalvars.time); if (self->k_adm_lasttime && (till > 0)) { // probably must help against brute force G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } if (!((!strnull(arg_3) && strneq("none", rcpass) && streq(arg_3, rcpass)) // rcon via pass || VIP_IsFlags(self, VIP_RCON))) // rcon via VIP rights { // ok, here we really need check access G_cprint("RCON failed from: %s: %s\n", getname(self), ezinfokey(self, "ip")); G_sprint(self, 2, "mmode(rcon): access denied...\n"); self->k_adm_lasttime = g_globalvars.time; return; } // check do we need set this values or not if ((set = (mmode != iKey(self, "*mm")))) { SetUserInfo(self, "*mm", va("%d", mmode), SETUSERINFO_STAR); } G_sprint(self, 2, "mmode(rcon)%s\n", (set ? " set" : "")); return; case MMODE_NONE: default: G_sprint(self, 2, "mmode: off\n"); SetUserInfo(self, "*mm", va("%d", MMODE_NONE), SETUSERINFO_STAR); return; } } // } QW-Group-ktx-d05d6ca/src/g_main.c000066400000000000000000000353541475442401000166270ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ #include "g_local.h" #include "rng.h" /* global 4 fix entity self; entity other; entity world; entity newmis; // if this is set, the entity that just // run created a new missile that should // be simulated immediately entity trace_ent; entity msg_entity; // destination of single entity writes */ void initialise_spawned_ent(gedict_t *ent); gedict_t g_edicts[MAX_EDICTS]; //768 gedict_t *world = g_edicts; gedict_t *self, *other; //short shortvar=0xfedc; globalvars_t g_globalvars; field_t expfields[] = { { "vw_index", FOFS(vw_index), F_FLOAT }, { "movement", FOFS(movement), F_VECTOR }, { "maxspeed", FOFS(maxspeed), F_FLOAT }, { "gravity", FOFS(gravity), F_FLOAT }, { "isBot", FOFS(isBot), F_INT }, { "brokenankle", FOFS(brokenankle), F_FLOAT }, { "items2", FOFS(items2), F_FLOAT }, { "hideentity", FOFS(hideentity), F_INT }, { "trackent", FOFS(trackent), F_INT }, { "hideplayers", FOFS(hideplayers), F_INT }, // FTE does not support this. // We does not really have to explicitly disable them since server engine should ignore unsupported fields. // But Spike insists on this. Probably for clarity. #ifndef FTESV { "mod_admin", FOFS(k_admin), F_INT }, { "teleported", FOFS(teleported), F_INT }, #endif { NULL } }; char mapname[64]; static char worldmodel[64] = "worldmodel"; // FIXME: consider replacing usage of this with mapname. // Client names assigned in: // * G_InitGame() // * GAME_CLIENT_CONNECT // * ClientUserInfoChanged() static char netnames[MAX_CLIENTS][CLIENT_NAME_LEN]; static char callalias_buf[MAX_CLIENTS][CALLALIAS_SIZE]; static char f_checks[MAX_CLIENTS][F_CHECK_SIZE]; static wreg_t wregs[MAX_CLIENTS][MAX_WREGS]; static plrfrm_t plrfrms[MAX_CLIENTS][MAX_PLRFRMS]; gameData_t gamedata = { (edict_t*) g_edicts, sizeof(gedict_t), &g_globalvars, expfields, GAME_API_VERSION, MAX_EDICTS }; float starttime; int g_matchstarttime; int sv_extensions; void G_InitGame(int levelTime, int randomSeed); void G_ShutDown(void); void StartFrame(int time); qbool ClientCommand(void); qbool ClientUserInfoChanged(int after); void G_EdictTouch(void); void G_EdictThink(void); void G_EdictBlocked(void); void ClearGlobals(void); void PausedTic(int duration); qbool ClientSay(qbool isTeamSay); void RemoveMOTD(void); void ShowVersion(void); static qbool check_ezquake(gedict_t *p); void SaveLevelStartParams(gedict_t *e); qbool FTE_sv = false; static qbool G_InitExtensions(void); /* ================ vmMain This is the only way control passes into the module. This must be the very first function compiled into the .q3vm file ================ */ intptr_t VISIBILITY_VISIBLE vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11) { int api_ver; switch (command) { case GAME_INIT: ClearGlobals(); api_ver = trap_GetApiVersion(); #if defined(idx64) || defined(PR_ALWAYS_REFS) // We set references cvar_fset("sv_pr2references", 1); #endif if (api_ver < GAME_API_VERSION) { G_cprint("Mod requires API_VERSION %d or higher, server have %d\n", GAME_API_VERSION, api_ver); return 0; } if (strstr(ezinfokey(world, "*version"), "FTE")) { G_cprint("^2KTX: FTE server detected, yay!\n"); FTE_sv = true; } if (!G_InitExtensions()) return 0; G_InitGame(arg0, arg1); return (intptr_t)(&gamedata); case GAME_LOADENTS: ClearGlobals(); G_SpawnEntitiesFromString(); return 1; case GAME_START_FRAME: ClearGlobals(); if (arg1) { #ifdef BOT_SUPPORT extern void BotStartFrame(void); if (bots_enabled()) { BotStartFrame(); } #endif } else { if (framecount == 0) { infokey(world, "mapname", mapname, sizeof(mapname)); infokey(world, "modelname", worldmodel, sizeof(worldmodel)); world->model = worldmodel; } StartFrame(arg0); } return 1; case GAME_CLIENT_CONNECT: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); // Init client name. self->netname = netnames[NUM_FOR_EDICT(self)-1]; infokey(self, "name", self->netname, CLIENT_NAME_LEN); self->last_rune = "setme"; self->classname = ""; // at least empty classname self->connect_time = g_globalvars.time; self->k_lastspawn = world; // set safe value self->k_msgcount = g_globalvars.time; self->wreg = wregs[(int)(self - world) - 1]; self->plrfrms = plrfrms[(int)(self - world) - 1]; memset(self->wreg, 0, sizeof(wreg_t) * MAX_WREGS); // clear memset(self->plrfrms, 0, sizeof(plrfrm_t) * MAX_PLRFRMS); // clear self->callalias = callalias_buf[(int)(self - world) - 1]; self->callalias[0] = 0; self->f_checkbuf = f_checks[(int)(self - world) - 1]; self->f_checkbuf[0] = 0; check_ezquake(self); if (strnull(ezinfokey(self, "*is"))) // show this only ones at connect time { ShowVersion(); } if (arg0) { SpectatorConnect(); } else { ClientConnect(); } if (self->k_accepted) { cmdinfo_infoset(self); } update_ghosts(); self->hideplayers_default = (self->ezquake_version < 4957); return 1; case GAME_PUT_CLIENT_IN_SERVER: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return 1; } SaveLevelStartParams(self); if (!arg0) { k_respawn(self, false); } else { PutSpectatorInServer(); } return 1; case GAME_CLIENT_DISCONNECT: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); RemoveMOTD(); // remove MOTD entitys s_lr_clear(self); if (arg0) { SpectatorDisconnect(); } else { ClientDisconnect(); } // { guarantee this set to some safe values after client disconnect self->classname = ""; self->ct = ctNone; self->k_accepted = 0; // } update_ghosts(); return 1; case GAME_SETNEWPARMS: ClearGlobals(); SetNewParms(); return 1; case GAME_CLIENT_PRETHINK: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return 1; } if (self->wreg_attack) // client simulate +attack via "cmd wreg" feature { self->s.v.button0 = true; } if (k_bloodfest) { extern void bloodfest_client_think(void); bloodfest_client_think(); } if (!arg0) { PlayerPreThink(); } return 1; case GAME_CLIENT_POSTTHINK: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return 1; } self->k_lastPostThink = g_globalvars.time; if (self->wreg_attack) // client simulate +attack via "cmd wreg" feature { self->s.v.button0 = true; } if (!arg0) { PlayerPostThink(); } else { SpectatorThink(); } BothPostThink(); return 1; case GAME_EDICT_TOUCH: ClearGlobals(); G_EdictTouch(); return 1; case GAME_EDICT_THINK: ClearGlobals(); G_EdictThink(); return 1; case GAME_EDICT_BLOCKED: ClearGlobals(); G_EdictBlocked(); return 1; case GAME_SETCHANGEPARMS: ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); SetChangeParms(); return 1; case GAME_CLIENT_COMMAND: ClearGlobals(); return ClientCommand(); case GAME_CLIENT_USERINFO_CHANGED: // Called when client userinfo is changed. // Return non zero zero if such userinfo invalid. // argv(0) = "setinfo", argv(1) = key, argv(2) = value. // Userinfo change performed in two stages, // first stage is when server and mod validating if new userinfo is allowed, // during this stage argument 'after' is zero, after userinfo allowed // server execute this function second time with non zero 'after' argument. ClearGlobals(); self = PROG_TO_EDICT(g_globalvars.self); if (!self->k_accepted) { return 0; // cmon, u r zombie or etc... } // allow change even not connected, or disconnected return ClientUserInfoChanged(arg0); case GAME_SHUTDOWN: // called before level change/spawn // qqshka: YES, REALLY COOL QVM FEATURE COMPARING TO QC, U CAN CATCH LEVEL CHANGE // INVOKED FROM SERVER CONSOLE !!! ClearGlobals(); G_ShutDown(); return 0; case GAME_CONSOLE_COMMAND: // called on server console command "mod" // params like GAME_CLIENT_COMMAND, but argv(0) always "mod" ClearGlobals(); return 0; //ConsoleCommand(); case GAME_CLIENT_SAY: // called on user /say or /say_team // arg0 non zero if say_team // return non zero if say/say_team handled by mod // params like GAME_CLIENT_COMMAND ClearGlobals(); return ClientSay(arg0); case GAME_PAUSED_TIC: // called every frame when the game is paused ClearGlobals(); PausedTic(arg0); return 0; case GAME_CLEAR_EDICT: // Don't ClearGlobals() as this will be called during spawn() initialise_spawned_ent(PROG_TO_EDICT(g_globalvars.self)); return 0; case GAME_EDICT_CSQCSEND: self = PROG_TO_EDICT(g_globalvars.self); other = PROG_TO_EDICT(g_globalvars.other); if (self->SendEntity) { return ((int(*)(int))(self->SendEntity))(arg0); } return 0; } return 0; } //=================================================================== void G_Printf(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_DPrintf(text); } void G_Error(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_Error(text); } //=================================================================== void G_InitGame(int levelTime, int randomSeed) { int i; g_random_seed(randomSeed); framecount = 0; starttime = levelTime * 0.001; G_Printf("Init Game\n"); G_InitMemory(); memset(g_edicts, 0, sizeof(gedict_t) * MAX_EDICTS); for ( i = 0; i < MAX_CLIENTS; i++ ) { g_edicts[i + 1].netname = netnames[i]; } GetMapList(); ra_init_que(); Init_cmds(); race_init(); // put mod version in serverinfo localcmd("serverinfo \"%s\" \"%s\"\n", MOD_SERVERINFO_MOD_KEY, MOD_VERSION); // set mod information cvars cvar_set("qwm_name", MOD_NAME); cvar_set("qwm_fullname", MOD_FULLNAME); cvar_set("qwm_version", MOD_VERSION); cvar_set("qwm_buildnum", (GIT_COMMIT ? GIT_COMMIT : "unknown")); cvar_set("qwm_platform", QW_PLATFORM_SHORT); cvar_set("qwm_builddate", MOD_BUILD_DATE); cvar_set("qwm_homepage", MOD_URL); sv_extensions = cvar("sv_mod_extensions"); } void G_ShutDown(void) { extern int IsMapInCycle(char *map); extern qbool force_map_reset; char *map = mapname; AbortElect(); if (!cvar("lock_practice") && k_practice) // #practice mode# { SetPractice(0, NULL); // return server to normal mode } if (match_in_progress) { EndMatch(1); // skip demo, make some other stuff } cvar_set("_k_lastmap", (strnull(map) || force_map_reset ? "" : map)); cvar_fset("_k_pow_last", Get_Powerups()); } //=========================================================================== // Physics // //=========================================================================== //////////////// // GlobalParams: // time // self // other /////////////// void G_EdictTouch(void) { self = PROG_TO_EDICT(g_globalvars.self); other = PROG_TO_EDICT(g_globalvars.other); if (self->touch) { /* #ifdef DEBUG if(self->classname && other->classname) if(!strcmp(self->classname,"player")||!strcmp(other->classname,"player")) G_bprint(2, "touch %s <-> %s\n", self->classname,other->classname); #endif */ ((void(*)(void))(self->touch))(); } else { G_Printf("Null touch func"); } } //////////////// // GlobalParams: // time // self // other=world /////////////// void G_EdictThink(void) { self = PROG_TO_EDICT(g_globalvars.self); other = PROG_TO_EDICT(g_globalvars.other); if (self->think) { ((void(*)(void))(self->think))(); } else { G_Printf("Null think func"); } } //////////////// // GlobalParams: // time // self=pusher // other=check // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone /////////////// void G_EdictBlocked(void) { self = PROG_TO_EDICT(g_globalvars.self); other = PROG_TO_EDICT(g_globalvars.other); if (self->blocked) { ((void(*)(void))(self->blocked))(); } else { //G_Printf("Null blocked func"); } } void ClearGlobals(void) { damage_attacker = damage_inflictor = activator = self = other = newmis = world; } //=========================================================================== // yeah its lame, but better than checking setinfo each time. static qbool check_ezquake(gedict_t *p) { char *clinfo = ezinfokey(p, "*client"); if (!strnull(clinfo) && strstr(clinfo, "ezQuake")) // seems ezQuake { while (Q_isalpha(clinfo[0])) { clinfo++; } p->ezquake_version = atoi(clinfo); return true; } return false; } //=========================================================================== qbool haveextensiontab[G_EXTENSIONS_LAST-G_EXTENSIONS_FIRST]; static qbool G_InitExtensions(void) { qbool success = true; struct { const char *name; int id; } exttraps[] = { {"SetExtField", G_SETEXTFIELD}, {"GetExtField", G_GETEXTFIELD}, {"ChangeLevelHub", G_CHANGELEVEL_HUB}, {"URI_Query", G_URI_QUERY}, {"particleeffectnum", G_PARTICLEEFFECTNUM}, {"trailparticles", G_TRAILPARTICLES}, {"pointparticles", G_POINTPARTICLES}, {"clientstat", G_CLIENTSTAT}, {"pointerstat", G_POINTERSTAT}, {"MapExtFieldPtr", G_MAPEXTFIELDPTR}, {"SetExtFieldPtr", G_SETEXTFIELDPTR}, {"GetExtFieldPtr", G_GETEXTFIELDPTR}, {"setsendneeded", G_SETSENDNEEDED}, }; int i; for (i = 0; i < sizeof(exttraps)/sizeof(exttraps[0]); i++) { haveextensiontab[exttraps[i].id-G_EXTENSIONS_FIRST] = trap_Map_Extension(exttraps[i].name, exttraps[i].id)>=0; } // // Here you should check extensions which required and terminate server if something is missed. // return success; } QW-Group-ktx-d05d6ca/src/g_mem.c000066400000000000000000000026551475442401000164570ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ // g_mem.c // #include "g_local.h" #define POOLSIZE (256 * 1024) static char memoryPool[POOLSIZE]; static int allocPoint; void* G_Alloc(int size) { char *p; /* if ( g_debugAlloc.integer ) { G_Printf( "G_Alloc of %i bytes (%i left)\n", size, POOLSIZE - allocPoint - ( ( size + 31 ) & ~31 ) ); }*/ if (allocPoint + size > POOLSIZE) { G_Error("G_Alloc: failed on allocation of %i bytes\n", size);// bk010103 - was %u, but is signed return NULL; } p = &memoryPool[allocPoint]; allocPoint += (size + 31) & ~31; return p; } void G_InitMemory(void) { allocPoint = 0; } QW-Group-ktx-d05d6ca/src/g_spawn.c000066400000000000000000000547401475442401000170330ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ #include "g_local.h" #define MAX_SPAWN_VARS 64 #define MAX_SPAWN_VARS_CHARS 4096 int numSpawnVars; char *spawnVars[MAX_SPAWN_VARS][2]; // key / value pairs int numSpawnVarChars; char spawnVarChars[MAX_SPAWN_VARS_CHARS]; qbool G_SpawnString(const char *key, const char *defaultString, char **out) { int i; /* if ( !level.spawning ) { *out = (char *)defaultString; // G_Error( "G_SpawnString() called while not spawning" ); }*/ for (i = 0; i < numSpawnVars; i++) { if (!Q_stricmp(key, spawnVars[i][0])) { *out = spawnVars[i][1]; return true; } } *out = (char*) defaultString; return false; } qbool G_SpawnFloat(const char *key, const char *defaultString, float *out) { char *s; qbool present; present = G_SpawnString(key, defaultString, &s); *out = atof(s); return present; } qbool G_SpawnInt(const char *key, const char *defaultString, int *out) { char *s; qbool present; present = G_SpawnString(key, defaultString, &s); *out = atoi(s); return present; } qbool G_SpawnVector(const char *key, const char *defaultString, float *out) { char *s; qbool present; present = G_SpawnString(key, defaultString, &s); sscanf(s, "%f %f %f", &out[0], &out[1], &out[2]); return present; } // // fields are needed for spawning from the entity string // field_t fields[] = { { "classname", FOFCLSN, F_LSTRING }, { "origin", FOFS(s.v.origin), F_VECTOR }, { "model", FOFS(model), F_LSTRING }, { "message", FOFS(message), F_LSTRING }, { "target", FOFS(target), F_LSTRING }, { "map", FOFS(map), F_LSTRING }, { "killtarget", FOFS(killtarget), F_LSTRING }, { "count", FOFS(count), F_FLOAT }, { "targetname", FOFS(targetname), F_LSTRING }, { "wait", FOFS(wait), F_FLOAT }, { "skin", FOFS(s.v.skin), F_FLOAT }, { "effects", FOFS(s.v.effects), F_FLOAT }, { "speed", FOFS(speed), F_FLOAT }, { "spawnflags", FOFS(s.v.spawnflags), F_FLOAT }, { "health", FOFS(s.v.health), F_FLOAT }, { "takedamage", FOFS(s.v.takedamage), F_FLOAT }, { "dmg", FOFS(dmg), F_FLOAT }, { "delay", FOFS(delay), F_FLOAT }, { "worldtype", FOFS(worldtype), F_INT }, { "lip", FOFS(lip), F_FLOAT }, { "height", FOFS(height), F_FLOAT }, { "sounds", FOFS(s.v.sounds), F_FLOAT }, { "angles", FOFS(s.v.angles), F_VECTOR }, { "mangle", FOFS(mangle), F_VECTOR }, { "style", FOFS(style), F_INT }, { "angle", FOFS(s.v.angles), F_ANGLEHACK }, { "light", 0, F_IGNORE }, { "wad", 0, F_IGNORE }, { "noise", FOFS(noise), F_LSTRING }, { "noise1", FOFS(noise1), F_LSTRING }, { "noise2", FOFS(noise2), F_LSTRING }, { "noise3", FOFS(noise3), F_LSTRING }, { "noise4", FOFS(noise4), F_LSTRING }, { "deathtype", FOFS(deathtype), F_LSTRING }, { "t_length", FOFS(t_length), F_FLOAT }, { "t_width", FOFS(t_width), F_FLOAT }, // TF { "team_no", FOFS(team_no), F_INT }, // custom teleporters { "size", FOFS(s.v.size), F_VECTOR }, // race routes { "race_route_name", FOFS(race_route_name), F_LSTRING }, { "race_route_description", FOFS(race_route_description), F_LSTRING }, { "race_route_timeout", FOFS(race_route_timeout), F_INT }, { "race_route_weapon_mode", FOFS(race_route_weapon_mode), F_INT }, { "race_route_falsestart_mode", FOFS(race_route_falsestart_mode), F_INT }, { "race_route_start_yaw", FOFS(race_route_start_yaw), F_FLOAT }, { "race_route_start_pitch", FOFS(race_route_start_yaw), F_FLOAT }, { "race_flags", FOFS(race_flags), F_INT }, // advanced hoonymode (spawn points determine how the player spawns) { "spawn_items", FOFS(s.v.items), F_FLOAT }, { "spawn_armorvalue", FOFS(s.v.armorvalue), F_FLOAT }, { "spawn_ammo_shells", FOFS(s.v.ammo_shells), F_FLOAT }, { "spawn_ammo_nails", FOFS(s.v.ammo_nails), F_FLOAT }, { "spawn_ammo_rockets", FOFS(s.v.ammo_rockets), F_FLOAT }, { "spawn_ammo_cells", FOFS(s.v.ammo_cells), F_FLOAT }, { "spawn_initial_delay", FOFS(initial_spawn_delay), F_FLOAT }, { "hoony_timelimit", FOFS(hoony_timelimit), F_INT }, { "hoony_defaultwinner", FOFS(hoony_defaultwinner), F_LSTRING }, // KTX teleporter flags { "ktx_votemap", FOFS(ktx_votemap), F_LSTRING }, // Transparent entities in map { "alpha", -1, F_FLOAT }, // Rotate { "rotate", FOFS(rotate), F_VECTOR }, { "path", FOFS(path), F_LSTRING }, { "event", FOFS(event), F_LSTRING }, { "group", FOFS(group), F_LSTRING }, // Bob { "waitmin", FOFS(waitmin), F_FLOAT}, { "waitmin2", FOFS(waitmin2), F_FLOAT}, // ambient_general { "volume", FOFS(volume), F_FLOAT }, // trigger_heal { "heal_amount", FOFS(healamount), F_FLOAT }, // Colorized entities in map { "colormod" -1, F_VECTOR }, { NULL } }; typedef struct { char *name; void (*spawn)(void); } spawn_t; void SUB_Remove(void) { // if (self && self->classname ) // G_bprint(2, "rm: %s\n", self->classname); if (self && streq(self->classname, "backpack")) { if ((self->s.v.items == IT_ROCKET_LAUNCHER) || (self->s.v.items == IT_LIGHTNING)) { // Ugh... get away with 'world' because mvdsv will exit before test with STUFFCMD_DEMOONLY stuffcmd_flags(world, STUFFCMD_DEMOONLY, "//ktx expire %d\n", NUM_FOR_EDICT(self)); } } ent_remove(self); } void SUB_RM_01(gedict_t *ent) { if (ent) { ent->s.v.nextthink = g_globalvars.time + 0.001f; // remove later ent->think = (func_t) SUB_Remove; } } void SUB_Null(void) { } void SP_light(void); void SP_light_fluoro(void); void SP_light_fluorospark(void); void SP_light_globe(void); void SP_light_torch_small_walltorch(void); void SP_light_flame_large_yellow(void); void SP_light_flame_small_yellow(void); void SP_light_flame_small_white(void); void SP_ambient_suck_wind(void); void SP_ambient_drone(void); void SP_ambient_flouro_buzz(void); void SP_ambient_drip(void); void SP_ambient_comp_hum(void); void SP_ambient_thunder(void); void SP_ambient_light_buzz(void); void SP_ambient_swamp1(void); void SP_ambient_swamp2(void); void SP_misc_noisemaker(void); void SP_misc_explobox(void); void SP_misc_explobox2(void); void SP_air_bubbles(void); void SP_trap_spikeshooter(void); void SP_trap_shooter(void); void SP_func_wall(void); void SP_func_ctf_wall(void); void SP_func_illusionary(void); void SP_func_episodegate(void); void SP_func_bossgate(void); void SP_func_door(void); void SP_func_door_secret(void); void SP_func_plat(void); void SP_func_train(void); void SP_misc_teleporttrain(void); void SP_func_button(void); void SP_func_bob(void); void SP_func_laser(void); void SP_trigger_multiple(void); void SP_trigger_once(void); void SP_trigger_relay(void); void SP_trigger_secret(void); void SP_trigger_counter(void); void SP_info_teleport_destination(void); void SP_trigger_teleport(void); void SP_trigger_custom_teleport(void); void SP_trigger_setskill(void); void SP_trigger_onlyregistered(void); void SP_trigger_hurt(void); void SP_trigger_push(void); void SP_trigger_custom_push(void); void SP_trigger_monsterjump(void); void SP_trigger_custom_monsterjump(void); void SP_trigger_changelevel(void); void SP_path_corner(void); void SP_item_health(void); void SP_item_armor1(void); void SP_item_armor2(void); void SP_item_armorInv(void); void SP_weapon_supershotgun(void); void SP_weapon_nailgun(void); void SP_weapon_supernailgun(void); void SP_weapon_grenadelauncher(void); void SP_weapon_rocketlauncher(void); void SP_weapon_lightning(void); void SP_item_shells(void); void SP_item_spikes(void); void SP_item_rockets(void); void SP_item_cells(void); void SP_item_weapon(void); void SP_item_artifact_invulnerability(void); void SP_item_artifact_envirosuit(void); void SP_item_artifact_invisibility(void); void SP_item_artifact_super_damage(void); void SP_item_flag_team1(void); void SP_item_flag_team2(void); void SP_item_sigil(void); void SP_item_key1(void); void SP_item_key2(void); void SP_misc_fireball(void); void SP_info_intermission(void); void SP_info_player_deathmatch(void); void SP_monster_dog(void); void SP_monster_demon1(void); void SP_monster_enforcer(void); void SP_monster_fish(void); void SP_monster_hell_knight(void); void SP_monster_knight(void); void SP_monster_ogre(void); void SP_monster_shalrath(void); void SP_monster_shambler(void); void SP_monster_army(void); void SP_monster_tarbaby(void); void SP_monster_wizard(void); void SP_monster_zombie(void); void SP_monster_boss(void); void SP_monster_oldone(void); void SP_event_lightning(void); void SP_info_monster_start(void); // TF void SP_item_tfgoal(void); void SP_info_player_teamspawn(void); void SP_i_p_t(void); // Races void SP_race_route_start(void); // Rotate void SP_info_rotate(void); void SP_path_rotate(void); void SP_func_rotate_entity(void); void SP_func_rotate_train(void); void SP_func_movewall(void); void SP_rotate_object(void); void SP_func_rotate_door(void); void SP_ambient_general(void); void SP_trigger_heal(void); spawn_t spawns[] = { // info entities don't do anything at all, but provide positional // information for things controlled by other processes { "info_player_start", SUB_Null }, { "info_player_start2", SUB_Null }, { "info_player_deathmatch", SP_info_player_deathmatch }, { "info_player_coop", SUB_Null }, { "info_intermission", SP_info_intermission }, { "trigger_changelevel", SP_trigger_changelevel }, /*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) Used as a positional target for lightning. */ { "info_notnull", SUB_Null }, { "light", SP_light }, { "light_fluoro", SP_light_fluoro }, { "light_fluorospark", SP_light_fluorospark }, { "light_globe", SP_light_globe }, { "light_torch_small_walltorch", SP_light_torch_small_walltorch }, { "light_flame_large_yellow", SP_light_flame_large_yellow }, { "light_flame_small_yellow", SP_light_flame_small_yellow }, { "light_flame_small_white", SP_light_flame_small_white }, { "air_bubbles", SP_air_bubbles }, { "misc_fireball", SP_misc_fireball }, { "ambient_suck_wind", SP_ambient_suck_wind }, { "ambient_drone", SP_ambient_drone }, { "ambient_flouro_buzz", SP_ambient_flouro_buzz }, { "ambient_drip", SP_ambient_drip }, { "ambient_comp_hum", SP_ambient_comp_hum }, { "ambient_thunder", SP_ambient_thunder }, { "ambient_light_buzz", SP_ambient_light_buzz }, { "ambient_swamp1", SP_ambient_swamp1 }, { "ambient_swamp2", SP_ambient_swamp2 }, { "ambient_general", SP_ambient_general }, { "misc_noisemaker", SP_misc_noisemaker }, { "misc_explobox", SP_misc_explobox }, { "misc_explobox2", SP_misc_explobox2 }, { "trap_spikeshooter", SP_trap_spikeshooter }, { "trap_shooter", SP_trap_shooter }, { "func_wall", SP_func_wall }, { "func_illusionary", SP_func_illusionary }, { "func_episodegate", SP_func_episodegate }, { "func_bossgate", SP_func_bossgate }, { "func_door", SP_func_door }, { "func_door_secret", SP_func_door_secret }, { "func_plat", SP_func_plat }, { "func_train", SP_func_train }, { "misc_teleporttrain", SP_misc_teleporttrain }, { "func_button", SP_func_button }, { "func_bob", SP_func_bob }, { "func_laser", SP_func_laser }, { "trigger_multiple", SP_trigger_multiple }, { "trigger_once", SP_trigger_once }, { "trigger_relay", SP_trigger_relay }, { "trigger_secret", SP_trigger_secret }, { "trigger_counter", SP_trigger_counter }, { "info_teleport_destination", SP_info_teleport_destination }, { "trigger_teleport", SP_trigger_teleport }, { "trigger_custom_teleport", SP_trigger_custom_teleport }, { "trigger_setskill", SP_trigger_setskill }, { "trigger_onlyregistered", SP_trigger_onlyregistered }, { "trigger_hurt", SP_trigger_hurt }, { "trigger_push", SP_trigger_push }, { "trigger_custom_push", SP_trigger_custom_push }, { "trigger_monsterjump", SP_trigger_monsterjump }, { "trigger_custom_monsterjump", SP_trigger_custom_monsterjump }, { "path_corner", SP_path_corner }, { "item_health", SP_item_health }, { "item_armor1", SP_item_armor1 }, { "item_armor2", SP_item_armor2 }, { "item_armorInv", SP_item_armorInv }, { "weapon_supershotgun", SP_weapon_supershotgun }, { "weapon_nailgun", SP_weapon_nailgun }, { "weapon_supernailgun", SP_weapon_supernailgun }, { "weapon_grenadelauncher", SP_weapon_grenadelauncher }, { "weapon_rocketlauncher", SP_weapon_rocketlauncher }, { "weapon_lightning", SP_weapon_lightning }, { "item_shells", SP_item_shells }, { "item_spikes", SP_item_spikes }, { "item_rockets", SP_item_rockets }, { "item_cells", SP_item_cells }, { "item_weapon", SP_item_weapon }, { "item_artifact_invulnerability", SP_item_artifact_invulnerability }, { "item_artifact_envirosuit", SP_item_artifact_envirosuit }, { "item_artifact_invisibility", SP_item_artifact_invisibility }, { "item_artifact_super_damage", SP_item_artifact_super_damage }, { "item_sigil", SP_item_sigil }, { "item_key1", SP_item_key1 }, { "item_key2", SP_item_key2 }, // ctf ents { "item_flag_team1", SP_item_flag_team1 }, { "item_flag_team2", SP_item_flag_team2 }, { "item_rune_res", SUB_Null }, { "item_rune_str", SUB_Null }, { "item_rune_hst", SUB_Null }, { "item_rune_rgn", SUB_Null }, { "func_ctf_wall", SP_func_ctf_wall }, { "info_player_team1", SUB_Null }, { "info_player_team2", SUB_Null }, // k_ctf_based_spawn 2 "within home base" spawns. { "info_player_team1_deathmatch", SUB_Null }, { "info_player_team2_deathmatch", SUB_Null }, // // TF -- well, we does not support TF but require it for loading TF map as CTF map. // { "item_tfgoal", SP_item_tfgoal }, // FLAG { "info_player_teamspawn", SP_info_player_teamspawn }, // red/blue team player spawns. { "i_p_t", SP_i_p_t }, // same as "info_player_teamspawn". //not used ents /*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) Used as a positional target for spotlights, etc. */ { "info_null", SUB_Remove }, { "monster_ogre", SP_monster_ogre }, { "monster_demon1", SP_monster_demon1 }, { "monster_shambler", SP_monster_shambler }, { "monster_knight", SP_monster_knight }, { "monster_army", SP_monster_army }, { "monster_wizard", SP_monster_wizard }, { "monster_dog", SP_monster_dog }, { "monster_zombie", SP_monster_zombie }, { "monster_boss", SP_monster_boss }, { "monster_tarbaby", SP_monster_tarbaby }, { "monster_hell_knight", SP_monster_hell_knight }, { "monster_fish", SP_monster_fish }, { "monster_shalrath", SP_monster_shalrath }, { "monster_enforcer", SP_monster_enforcer }, { "monster_oldone", SP_monster_oldone }, { "event_lightning", SP_event_lightning }, { "info_monster_start", SP_info_monster_start }, // race routes { "race_route_start", SP_race_route_start }, { "race_route_marker", SUB_Null }, // rotate { "info_rotate", SP_info_rotate }, { "path_rotate", SP_path_rotate }, { "rotate_object", SP_rotate_object }, { "func_movewall", SP_func_movewall }, { "func_rotate_door", SP_func_rotate_door }, { "func_rotate_train", SP_func_rotate_train }, { "func_rotate_entity", SP_func_rotate_entity }, { "trigger_heal", SP_trigger_heal }, { 0, 0 } }; /* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning false if not found =============== */ qbool G_CallSpawn(gedict_t *ent) { spawn_t *s; // gitem_t *item; if (!ent->classname) { G_Printf("G_CallSpawn: NULL classname\n"); return false; } /* // check item spawn functions for ( item=bg_itemlist+1 ; item->classname ; item++ ) { if ( !strcmp(item->classname, ent->classname) ) { G_SpawnItem( ent, item ); return true; } }*/ // check normal spawn functions for (s = spawns; s->name; s++) { if (!strcmp(s->name, ent->classname)) { // found it self = ent; //G_Printf("%8i %s\n",ent->classname,ent->classname); s->spawn(); return true; } } G_Printf("%s doesn't have a spawn function\n", ent->classname); return false; } /* ============= G_NewString Builds a copy of the string, translating \n to real linefeeds so message texts can be multi-line ============= */ char* G_NewString(const char *string) { char *newb, *new_p; int i, l; l = strlen(string) + 1; newb = G_Alloc(l); new_p = newb; // turn \n into a real linefeed 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; } /* =============== G_ParseField Takes a key/value pair and sets the binary values in a gentity =============== */ static void G_ParseField(const char *key, const char *value, gedict_t *ent) { field_t *f; byte *b; float v; vec3_t vec; for (f = fields; f->name; f++) { if (!Q_stricmp(f->name, key)) { // found it b = (byte*) ent; switch (f->type) { case F_LSTRING: *(char**)(b + f->ofs) = G_NewString(value); break; case F_VECTOR: sscanf(value, "%f %f %f", &vec[0], &vec[1], &vec[2]); if (f->ofs >= 0) { ((float*)(b + f->ofs))[0] = vec[0]; ((float*)(b + f->ofs))[1] = vec[1]; ((float*)(b + f->ofs))[2] = vec[2]; } else if (!strcmp(f->name, "colormod")) { ExtFieldSetColorMod(ent, vec[0], vec[1], vec[2]); } break; case F_INT: *(int*)(b + f->ofs) = atoi(value); break; case F_FLOAT: if (f->ofs >= 0) { *(float*)(b + f->ofs) = atof(value); } else if (!strcmp(f->name, "alpha")) { ExtFieldSetAlpha(ent, atof(value)); } break; case F_ANGLEHACK: v = atof(value); ((float*)(b + f->ofs))[0] = 0; ((float*)(b + f->ofs))[1] = v; ((float*)(b + f->ofs))[2] = 0; break; default: case F_IGNORE: break; } return; } } G_Printf("unknown field: %s\n", key); } /* =================== G_SpawnGEntityFromSpawnVars Spawn an entity and fill in all of the level fields from level.spawnVars[], then call the class specfic spawn function =================== */ void G_SpawnGEntityFromSpawnVars(void) { int i; gedict_t *ent; // get the next free entity ent = spawn(); for (i = 0; i < numSpawnVars; i++) { G_ParseField(spawnVars[i][0], spawnVars[i][1], ent); } if (deathmatch) { if (((int)ent->s.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH)) { // G_cprint( "%s removed because of SPAWNFLAG_NOT_DEATHMATCH\n", ent->classname ); ent_remove(ent); return; } } else if (((skill == 0) && ((int)ent->s.v.spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill == 1) && ((int)ent->s.v.spawnflags & SPAWNFLAG_NOT_MEDIUM)) || ((skill >= 2) && ((int)ent->s.v.spawnflags & SPAWNFLAG_NOT_HARD))) { // G_cprint( "%s removed because of SPAWNFLAG_NOT_XXX\n", ent->classname ); ent_remove(ent); return; } // if we didn't get a classname, don't bother spawning anything if (!G_CallSpawn(ent)) { ent_remove(ent); return; } } /* ==================== G_AddSpawnVarToken ==================== */ char* G_AddSpawnVarToken(const char *string) { int l; char *dest; l = strlen(string); if ((numSpawnVarChars + l + 1) > MAX_SPAWN_VARS_CHARS) { G_Error("G_AddSpawnVarToken: MAX_SPAWN_CHARS"); } dest = spawnVarChars + numSpawnVarChars; memcpy(dest, string, l + 1); numSpawnVarChars += l + 1; return dest; } /* ==================== G_ParseSpawnVars Parses a brace bounded set of key / value pairs out of the level's entity strings into level.spawnVars[] This does not actually spawn an entity. ==================== */ qbool G_ParseSpawnVars(void) { char keyname[MAX_TOKEN_CHARS]; char com_token[MAX_TOKEN_CHARS]; numSpawnVars = 0; numSpawnVarChars = 0; // parse the opening brace if (!trap_GetEntityToken(com_token, sizeof(com_token))) { // end of spawn string return false; } if (com_token[0] != '{') { G_Error("G_ParseSpawnVars: found %s when expecting {", com_token); } // go through all the key / value pairs while (1) { // parse key if (!trap_GetEntityToken(keyname, sizeof(keyname))) { G_Error("G_ParseSpawnVars: EOF without closing brace"); } if (keyname[0] == '}') { break; } // parse value if (!trap_GetEntityToken(com_token, sizeof(com_token))) { G_Error("G_ParseSpawnVars: EOF without closing brace"); } // G_Printf("%s\t%s\n",keyname,com_token); if (com_token[0] == '}') { G_Error("G_ParseSpawnVars: closing brace without data"); } if (numSpawnVars == MAX_SPAWN_VARS) { G_Error("G_ParseSpawnVars: MAX_SPAWN_VARS"); } spawnVars[numSpawnVars][0] = G_AddSpawnVarToken(keyname); spawnVars[numSpawnVars][1] = G_AddSpawnVarToken(com_token); numSpawnVars++; } return true; } void SP_worldspawn(void); /* ============== G_SpawnEntitiesFromString Parses textual entity definitions out of an entstring and spawns gentities. ============== */ void G_SpawnEntitiesFromString(void) { int i; // the worldspawn is not an actual entity, but it still // has a "spawn" function to perform any global setup // needed by a level (setting configstrings or cvars, etc) if (!G_ParseSpawnVars()) { G_Error("SpawnEntities: no entities"); } self = world; for (i = 0; i < numSpawnVars; i++) { G_ParseField(spawnVars[i][0], spawnVars[i][1], world); } SP_worldspawn(); // parse ents while (G_ParseSpawnVars()) { G_SpawnGEntityFromSpawnVars(); trap_FlushSignon(); } race_add_standard_routes(); } QW-Group-ktx-d05d6ca/src/g_syscalls.asm000066400000000000000000000062471475442401000200750ustar00rootroot00000000000000code equ trap_GetApiVersion -1 equ trap_DPrintf -2 equ trap_Error -3 equ trap_GetEntityToken -4 equ trap_spawn -5 equ trap_remove -6 equ trap_precache_sound -7 equ trap_precache_model -8 equ trap_lightstyle -9 equ trap_setorigin -10 equ trap_setsize -11 equ trap_setmodel -12 equ trap_BPrint -13 equ trap_SPrint -14 equ trap_CenterPrint -15 equ trap_ambientsound -16 equ trap_sound -17 equ trap_traceline -18 equ trap_checkclient -19 equ trap_stuffcmd -20 equ trap_localcmd -21 equ trap_cvar -22 equ trap_cvar_set -23 equ trap_findradius -24 equ trap_walkmove -25 equ trap_droptofloor -26 equ trap_checkbottom -27 equ trap_pointcontents -28 equ trap_nextent -29 equ trap_makestatic -31 equ trap_setspawnparam -32 equ trap_changelevel -33 equ trap_logfrag -34 equ trap_infokey -35 equ trap_multicast -36 equ trap_disableupdates -37 equ trap_WriteByte -38 equ trap_WriteChar -39 equ trap_WriteShort -40 equ trap_WriteLong -41 equ trap_WriteAngle -42 equ trap_WriteCoord -43 equ trap_WriteString -44 equ trap_WriteEntity -45 equ trap_FlushSignon -46 equ memset -47 equ memcpy -48 equ strncpy -49 equ sin -50 equ cos -51 equ atan2 -52 equ sqrt -53 equ floor -54 equ ceil -55 equ acos -56 equ trap_CmdArgc -57 equ trap_CmdArgv -58 equ trap_TraceCapsule -59 equ trap_FS_OpenFile -60 equ trap_FS_CloseFile -61 equ trap_FS_ReadFile -62 equ trap_FS_WriteFile -63 equ trap_FS_SeekFile -64 equ trap_FS_TellFile -65 equ trap_FS_GetFileList -66 equ trap_cvar_set_float -67 equ trap_cvar_string -68 equ trap_Map_Extension -69 equ strcmp -70 equ strncmp -71 equ stricmp -72 equ strnicmp -73 equ trap_find -74 equ trap_executecmd -75 equ trap_conprint -76 equ trap_readcmd -77 equ trap_redirectcmd -78 equ trap_AddBot -79 equ trap_RemoveBot -80 equ trap_SetBotUserInfo -81 equ trap_SetBotCMD -82 equ QVMstrftime -83 equ trap_CmdArgs -84 equ trap_CmdTokenize -85 equ strlcpy -86 equ strlcat -87 equ trap_makevectors -88 equ trap_nextclient -89 equ trap_precache_vwep_model -90 equ trap_setpause -91 equ trap_SetUserInfo -92 equ trap_movetogoal -93 equ trap_VisibleTo -94 equ trap_SetExtField -257 equ trap_GetExtField -258 equ trap_changelevelHub -259 equ trap_URI_Query -260 equ trap_particleeffectnum -261 equ trap_trailparticles -262 equ trap_pointparticles -263 equ trap_clientstat -264 equ trap_pointerstat -265 equ trap_MapExtFieldPtr -266 equ trap_SetExtFieldPtr -267 equ trap_GetExtFieldPtr -268 equ trap_SetSendNeeded -269 QW-Group-ktx-d05d6ca/src/g_syscalls.c000066400000000000000000000327701475442401000175370ustar00rootroot00000000000000/* * QWProgs-QVM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id$ */ //#include "g_local.h" // this file is only included when building a dll // g_syscalls.asm is included instead when building a qvm #ifdef Q3_VM #error "Do not use in VM build" #endif #include "g_local.h" static intptr_t ( QDECL *syscall)(intptr_t arg, ...) = ( intptr_t ( QDECL * ) ( intptr_t, ... ) ) -1; void VISIBILITY_VISIBLE dllEntry(intptr_t ( QDECL *syscallptr)(intptr_t arg, ...)) { syscall = syscallptr; } typedef union fi_s { float _float; intptr_t _int; } fi_t; static intptr_t PASSFLOAT(float x) { fi_t rc; rc._float = x; return rc._int; } intptr_t trap_GetApiVersion(void) { return syscall(G_GETAPIVERSION); } qbool trap_GetEntityToken(char *token, intptr_t size) { return (qbool)syscall(G_GetEntityToken, (intptr_t) token, size); } void trap_DPrintf(const char *fmt) { syscall(G_DPRINT, (intptr_t) fmt); } void trap_conprint(const char *fmt) { syscall(G_conprint, (intptr_t) fmt); } void trap_BPrint(intptr_t level, const char *fmt, intptr_t flags) { syscall(G_BPRINT, level, (intptr_t) fmt, flags); } void trap_SPrint(intptr_t edn, intptr_t level, const char *fmt, intptr_t flags) { syscall(G_SPRINT, edn, level, (intptr_t) fmt, flags); } void trap_CenterPrint(intptr_t edn, const char *fmt) { syscall(G_CENTERPRINT, edn, (intptr_t) fmt); } void trap_Error(const char *fmt) { syscall(G_ERROR, (intptr_t) fmt); } intptr_t trap_spawn(void) { return syscall(G_SPAWN_ENT); } void trap_remove(intptr_t edn) { syscall(G_REMOVE_ENT, edn); } void trap_precache_sound(char *name) { syscall(G_PRECACHE_SOUND, (intptr_t) name); } void trap_precache_model(char *name) { syscall(G_PRECACHE_MODEL, (intptr_t) name); } intptr_t trap_precache_vwep_model(char *name) { return syscall(G_PRECACHE_VWEP_MODEL, (intptr_t) name); } void trap_setorigin(intptr_t edn, float origin_x, float origin_y, float origin_z) { syscall(G_SETORIGIN, edn, PASSFLOAT(origin_x), PASSFLOAT(origin_y), PASSFLOAT(origin_z)); } void trap_setsize(intptr_t edn, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { syscall(G_SETSIZE, edn, PASSFLOAT(min_x), PASSFLOAT(min_y), PASSFLOAT(min_z), PASSFLOAT(max_x), PASSFLOAT(max_y), PASSFLOAT(max_z)); } void trap_setmodel(intptr_t edn, char *model) { syscall(G_SETMODEL, edn, (intptr_t) model); } void trap_ambientsound(float pos_x, float pos_y, float pos_z, char *samp, float vol, float atten) { syscall(G_AMBIENTSOUND, PASSFLOAT(pos_x), PASSFLOAT(pos_y), PASSFLOAT(pos_z), (intptr_t) samp, PASSFLOAT(vol), PASSFLOAT(atten)); } void trap_sound(intptr_t edn, intptr_t channel, char *samp, float vol, float att) { syscall(G_SOUND, edn, channel, (intptr_t) samp, PASSFLOAT(vol), PASSFLOAT(att)); } intptr_t trap_checkclient(void) { return syscall(G_CHECKCLIENT); } void trap_traceline(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, intptr_t nomonst, intptr_t edn) { syscall(G_TRACELINE, PASSFLOAT(v1_x), PASSFLOAT(v1_y), PASSFLOAT(v1_z), PASSFLOAT(v2_x), PASSFLOAT(v2_y), PASSFLOAT(v2_z), nomonst, edn); } void trap_stuffcmd(intptr_t edn, const char *fmt, intptr_t flags) { syscall(G_STUFFCMD, edn, (intptr_t) fmt, flags); } void trap_localcmd(const char *fmt) { syscall(G_LOCALCMD, (intptr_t) fmt); } void trap_executecmd(void) { syscall(G_executecmd); } void trap_readcmd(const char *str, char *buf, intptr_t size) { syscall(G_readcmd, (intptr_t) str, (intptr_t) buf, size); } void trap_redirectcmd(gedict_t *ent, char *str) { syscall(G_redirectcmd, (intptr_t) ent, (intptr_t) str); } float trap_cvar(const char *var) { fi_t tmp; tmp._int = syscall(G_CVAR, (intptr_t) var); return tmp._float; } void trap_cvar_string(const char *var, char *buffer, intptr_t buffsize) { syscall(G_CVAR_STRING, (intptr_t) var, (intptr_t) buffer, buffsize); } void trap_cvar_set(const char *var, const char *val) { syscall(G_CVAR_SET, (intptr_t) var, (intptr_t) val); } void trap_cvar_set_float(const char *var, float val) { syscall(G_CVAR_SET_FLOAT, (intptr_t) var, PASSFLOAT(val)); } intptr_t trap_droptofloor(intptr_t edn) { return syscall(G_DROPTOFLOOR, edn); } intptr_t trap_walkmove(intptr_t edn, float yaw, float dist) { return syscall(G_WALKMOVE, edn, PASSFLOAT(yaw), PASSFLOAT(dist)); } intptr_t trap_movetogoal(float dist) { return syscall(G_MOVETOGOAL, PASSFLOAT(dist)); } void trap_lightstyle(intptr_t style, char *val) { syscall(G_LIGHTSTYLE, style, (intptr_t) val); } intptr_t trap_checkbottom(intptr_t edn) { return syscall(G_CHECKBOTTOM, edn); } intptr_t trap_pointcontents(float origin_x, float origin_y, float origin_z) { return syscall(G_POINTCONTENTS, PASSFLOAT(origin_x), PASSFLOAT(origin_y), PASSFLOAT(origin_z)); } intptr_t trap_nextent(intptr_t n) { return syscall(G_NEXTENT, n); } gedict_t* trap_nextclient(gedict_t *ent) { return (gedict_t*) syscall(G_NEXTCLIENT, (intptr_t) ent); } /*intptr_t trap_find( intptr_t n,intptr_t fofs, char*str ) { return syscall( G_Find, n, fofs, (intptr_t)str ); }*/ gedict_t* trap_find(gedict_t *ent, intptr_t fofs, char *str) { return (gedict_t*) syscall(G_Find, (intptr_t) ent, fofs, (intptr_t) str); } gedict_t* trap_findradius(gedict_t *ent, float *org, float rad) { return (gedict_t*) syscall(G_FINDRADIUS, (intptr_t) ent, (intptr_t) org, PASSFLOAT(rad)); } void trap_makestatic(intptr_t edn) { syscall(G_MAKESTATIC, edn); } void trap_setspawnparam(intptr_t edn) { syscall(G_SETSPAWNPARAMS, edn); } void trap_changelevel(const char *name, const char *entityname) { syscall(G_CHANGELEVEL, name, entityname); } intptr_t trap_multicast(float origin_x, float origin_y, float origin_z, intptr_t to) { return syscall(G_MULTICAST, PASSFLOAT(origin_x), PASSFLOAT(origin_y), PASSFLOAT(origin_z), to); } void trap_logfrag(intptr_t killer, intptr_t killee) { syscall(G_LOGFRAG, killer, killee); } void trap_infokey(intptr_t edn, char *key, char *valbuff, intptr_t sizebuff) { syscall(G_GETINFOKEY, edn, (intptr_t) key, (intptr_t) valbuff, sizebuff); } void trap_WriteByte(intptr_t to, intptr_t data) { syscall(G_WRITEBYTE, to, data); } void trap_WriteChar(intptr_t to, intptr_t data) { syscall(G_WRITECHAR, to, data); } void trap_WriteShort(intptr_t to, intptr_t data) { syscall(G_WRITESHORT, to, data); } void trap_WriteLong(intptr_t to, intptr_t data) { syscall(G_WRITELONG, to, data); } void trap_WriteAngle(intptr_t to, float data) { syscall(G_WRITEANGLE, to, PASSFLOAT(data)); } void trap_WriteCoord(intptr_t to, float data) { syscall(G_WRITECOORD, to, PASSFLOAT(data)); } void trap_WriteString(intptr_t to, char *data) { syscall(G_WRITESTRING, to, (intptr_t) data); } void trap_WriteEntity(intptr_t to, intptr_t edn) { syscall(G_WRITEENTITY, to, edn); } void trap_FlushSignon(void) { syscall(G_FLUSHSIGNON); } void trap_disableupdates(intptr_t edn, float time) { syscall(G_DISABLEUPDATES, edn, PASSFLOAT(time)); } intptr_t trap_CmdArgc(void) { return syscall(G_CMD_ARGC); } void trap_CmdArgv(intptr_t arg, char *valbuff, intptr_t sizebuff) { syscall(G_CMD_ARGV, arg, (intptr_t) valbuff, sizebuff); } void trap_CmdArgs(char *valbuff, intptr_t sizebuff) { syscall(G_CMD_ARGS, (intptr_t) valbuff, sizebuff); } void trap_CmdTokenize(char *str) { syscall(G_CMD_TOKENIZE, (intptr_t) str); } void trap_TraceCapsule(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, intptr_t nomonst, intptr_t edn, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { syscall(G_TraceCapsule, PASSFLOAT(v1_x), PASSFLOAT(v1_y), PASSFLOAT(v1_z), PASSFLOAT(v2_x), PASSFLOAT(v2_y), PASSFLOAT(v2_z), nomonst, edn, PASSFLOAT(min_x), PASSFLOAT(min_y), PASSFLOAT(min_z), PASSFLOAT(max_x), PASSFLOAT(max_y), PASSFLOAT(max_z)); } intptr_t trap_FS_OpenFile(char *name, fileHandle_t *handle, fsMode_t fmode) { return syscall(G_FSOpenFile, (intptr_t) name, (intptr_t) handle, fmode); } void trap_FS_CloseFile(fileHandle_t handle) { syscall(G_FSCloseFile, handle); } intptr_t trap_FS_ReadFile(char *dest, intptr_t quantity, fileHandle_t handle) { return syscall(G_FSReadFile, (intptr_t) dest, quantity, handle); } intptr_t trap_FS_WriteFile(char *src, intptr_t quantity, fileHandle_t handle) { return syscall(G_FSWriteFile, (intptr_t) src, quantity, handle); } intptr_t trap_FS_SeekFile(fileHandle_t handle, intptr_t offset, intptr_t type) { return syscall(G_FSSeekFile, handle, offset, type); } intptr_t trap_FS_GetFileList(const char *path, const char *extension, char *listbuf, intptr_t bufsize, intptr_t flags) { return syscall(G_FSGetFileList, (intptr_t) path, (intptr_t) extension, (intptr_t) listbuf, bufsize, flags); } intptr_t trap_Map_Extension(const char *ext_name, intptr_t mapto) { return syscall(G_Map_Extension, (intptr_t) ext_name, mapto); } intptr_t trap_AddBot(const char *name, intptr_t bottomcolor, intptr_t topcolor, const char *skin) { return syscall(G_Add_Bot, (intptr_t) name, bottomcolor, topcolor, (intptr_t) skin); } intptr_t trap_RemoveBot(intptr_t edn) { return syscall(G_Remove_Bot, edn); } intptr_t trap_SetBotUserInfo(intptr_t edn, const char *varname, const char *value, intptr_t flags) { return syscall(G_SetBotUserInfo, edn, (intptr_t) varname, (intptr_t) value, flags); } intptr_t trap_SetBotCMD(intptr_t edn, intptr_t msec, float angles_x, float angles_y, float angles_z, intptr_t forwardmove, intptr_t sidemove, intptr_t upmove, intptr_t buttons, intptr_t impulse) { return syscall(G_SetBotCMD, edn, msec, PASSFLOAT(angles_x), PASSFLOAT(angles_y), PASSFLOAT(angles_z), forwardmove, sidemove, upmove, buttons, impulse); } void trap_setpause(intptr_t pause) { syscall(G_SETPAUSE, pause); } intptr_t QVMstrftime(char *valbuff, intptr_t sizebuff, const char *fmt, intptr_t offset) { return syscall(G_QVMstrftime, (intptr_t) valbuff, sizebuff, (intptr_t) fmt, offset); } void trap_makevectors(float *v) { syscall(G_MAKEVECTORS, (intptr_t) v); } #if defined( __linux__ ) || defined( _WIN32 ) /* || defined( __APPLE__ ) require?*/ size_t strlcpy(char *dst, const char *src, size_t siz) { return syscall(g_strlcpy, (intptr_t) dst, (intptr_t) src, (intptr_t) siz); } size_t strlcat(char *dst, const char *src, size_t siz) { return syscall(g_strlcat, (intptr_t) dst, (intptr_t) src, (intptr_t) siz); } #endif intptr_t trap_SetUserInfo(intptr_t edn, const char *varname, const char *value, intptr_t flags) { return syscall(G_SETUSERINFO, edn, (intptr_t) varname, (intptr_t) value, flags); } void trap_VisibleTo(intptr_t viewer, intptr_t first, intptr_t len, byte *visible) { syscall(G_VISIBLETO, viewer, first, len, (intptr_t) visible); } intptr_t trap_MapExtFieldPtr(const char *fieldname) { return syscall(G_MAPEXTFIELDPTR, (intptr_t)fieldname); } intptr_t trap_SetExtFieldPtr(gedict_t *ed, intptr_t fieldref, intptr_t *data, intptr_t size) { return syscall(G_SETEXTFIELDPTR, (intptr_t)ed, fieldref, (intptr_t)data, size); } intptr_t trap_GetExtFieldPtr(gedict_t *ed, intptr_t fieldref, intptr_t *data, intptr_t size) { return syscall(G_GETEXTFIELDPTR, (intptr_t)ed, fieldref, (intptr_t)data, size); } void trap_SetExtField(gedict_t *ed, const char *fieldname, intptr_t val) { syscall(G_SETEXTFIELD, (intptr_t)ed, (intptr_t)fieldname, val); } int trap_GetExtField(gedict_t *ed, const char *fieldname) { return syscall(G_GETEXTFIELD, (intptr_t)ed, (intptr_t)fieldname); } void trap_changelevelHub(const char *name, const char *entityname, const char *startspot) { syscall(G_CHANGELEVEL_HUB, name, entityname, startspot); } int trap_URI_Query(const char *uri, int vmentry/*GAME_...*/, void *cbcontext, const char *mimetype, const char *data, size_t datasize) { return syscall(G_URI_QUERY, (intptr_t)uri, vmentry, (intptr_t)cbcontext, (intptr_t)mimetype, (intptr_t)data, (intptr_t)datasize); } int trap_particleeffectnum(const char *effectname) { return syscall(G_PARTICLEEFFECTNUM, (intptr_t)effectname); } int trap_trailparticles(int effecttype, int entnum, float start_x, float start_y, float start_z, float end_x, float end_y, float end_z) { return syscall(G_TRAILPARTICLES, (intptr_t)effecttype, entnum, PASSFLOAT(start_x), PASSFLOAT(start_y), PASSFLOAT(start_z), PASSFLOAT(end_x), PASSFLOAT(end_y), PASSFLOAT(end_z)); } int trap_pointparticles(int effecttype, float org_x, float org_y, float org_z, float vel_x, float vel_y, float vel_z, int count) { return syscall(G_POINTPARTICLES, (intptr_t)effecttype, PASSFLOAT(org_x), PASSFLOAT(org_y), PASSFLOAT(org_z), PASSFLOAT(vel_x), PASSFLOAT(vel_y), PASSFLOAT(vel_z), count); } int trap_clientstat(int statidx, int stattype, int fieldoffset) { return syscall(G_CLIENTSTAT, statidx, stattype, fieldoffset); } int trap_pointerstat(int statidx, int stattype, void *offset) { return syscall(G_POINTERSTAT, statidx, stattype, (intptr_t)offset); } intptr_t trap_SetSendNeeded(intptr_t subject, intptr_t flags, intptr_t to) { return syscall(G_SETSENDNEEDED, subject, flags, to); } QW-Group-ktx-d05d6ca/src/g_syscalls_extra.c000066400000000000000000000070021475442401000207300ustar00rootroot00000000000000#include "g_local.h" #include "g_syscalls.h" typedef union fi_s { float _float; int _int; } fi_t; static unsigned int field_ref_alpha = 0; static unsigned int field_ref_colormod = 0; static unsigned int field_ref_sendentity = 0; static unsigned int field_ref_pvsflags = 0; void ExtFieldSetAlpha(gedict_t *ed, float alpha) { alpha = bound(0.0f, alpha, 1.0f); if (!field_ref_alpha && HAVEEXTENSION(G_MAPEXTFIELDPTR) && HAVEEXTENSION(G_SETEXTFIELDPTR)) { field_ref_alpha = trap_MapExtFieldPtr("alpha"); } if (field_ref_alpha) { trap_SetExtFieldPtr(ed, field_ref_alpha, (void*)&alpha, sizeof(float)); } else if (HAVEEXTENSION(G_SETEXTFIELD)) { fi_t v; v._float = alpha; trap_SetExtField(ed, "alpha", v._int); } else if (cvar("developer")) { G_bprint(PRINT_HIGH, "alpha needs SetExtField or MapExtFieldPtr and SetExtFieldPtr support in server\n"); } } float ExtFieldGetAlpha(gedict_t *ed) { fi_t tmp; tmp._float = -1.0f; if (!field_ref_alpha && HAVEEXTENSION(G_MAPEXTFIELDPTR) && HAVEEXTENSION(G_GETEXTFIELDPTR)) { field_ref_alpha = trap_MapExtFieldPtr("alpha"); } if (field_ref_alpha) { trap_GetExtFieldPtr(ed, field_ref_alpha, (void*)&tmp._float, sizeof(float)); } else if (HAVEEXTENSION(G_GETEXTFIELD)) { tmp._int = trap_GetExtField(ed, "alpha"); } else if (cvar("developer")) { G_bprint(PRINT_HIGH, "alpha needs GetExtField or MapExtFieldPtr and GetExtFieldPtr support in server\n"); } return tmp._float; } void ExtFieldSetColorMod(gedict_t *ed, float r, float g, float b) { if (!field_ref_colormod && HAVEEXTENSION(G_MAPEXTFIELDPTR) && HAVEEXTENSION(G_SETEXTFIELDPTR)) { field_ref_colormod = trap_MapExtFieldPtr("colormod"); } if (field_ref_colormod) { float rgb[3]; rgb[0] = max(0.0f, r); rgb[1] = max(0.0f, g); rgb[2] = max(0.0f, b); trap_SetExtFieldPtr(ed, field_ref_colormod, (void*)&rgb, sizeof(rgb)); } else if (cvar("developer")) { G_bprint(PRINT_HIGH, "colormod needs MapExtFieldPtr and SetExtFieldPtr support in server\n"); } } void ExtFieldSetSendEntity(gedict_t *ed, func_t callback) { if (!field_ref_sendentity && HAVEEXTENSION(G_MAPEXTFIELDPTR) && HAVEEXTENSION(G_SETEXTFIELDPTR)) { field_ref_sendentity = trap_MapExtFieldPtr("SendEntity"); } if (field_ref_sendentity) { int enable = 1; trap_SetExtFieldPtr(ed, field_ref_sendentity, (void*)&enable, sizeof(int)); ed->SendEntity = callback; // invoked via GAME_EDICT_CSQCSEND } else if (HAVEEXTENSION(G_SETEXTFIELD)) { trap_SetExtField(ed, "SendEntity", 1); ed->SendEntity = callback; // invoked via GAME_EDICT_CSQCSEND } else if (cvar("developer")) { G_bprint(PRINT_HIGH, "SendEntity needs SetExtField or MapExtFieldPtr and SetExtFieldPtr support in server\n"); } } void ExtFieldSetPvsFlags(gedict_t *ed, float pvsflags) { if (!field_ref_pvsflags && HAVEEXTENSION(G_MAPEXTFIELDPTR) && HAVEEXTENSION(G_SETEXTFIELDPTR)) { field_ref_pvsflags = trap_MapExtFieldPtr("pvsflags"); } if (field_ref_pvsflags) { trap_SetExtFieldPtr(ed, field_ref_pvsflags, (void*)&pvsflags, sizeof(float)); } else if (HAVEEXTENSION(G_SETEXTFIELD)) { fi_t tmp; tmp._float = pvsflags; trap_SetExtField(ed, "pvsflags", tmp._int); } else if (cvar("developer")) { G_bprint(PRINT_HIGH, "pvsflags needs SetExtField or MapExtFieldPtr and SetExtFieldPtr support in server\n"); } } void SetSendNeeded(gedict_t *ed, int sendflags, int unicast) { if (!HAVEEXTENSION(G_SETSENDNEEDED)) { G_bprint(PRINT_HIGH, "SetSendNeeded needs support in server\n"); return; } trap_SetSendNeeded(NUM_FOR_EDICT(ed), sendflags, unicast); } QW-Group-ktx-d05d6ca/src/g_userinfo.c000066400000000000000000000257171475442401000175370ustar00rootroot00000000000000/* * 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 * * * $Id$ */ #include "g_local.h" extern qbool isSupport_Params(gedict_t *p); extern void info_sys_mm_update(gedict_t *p, char *from, char *to); void info_wpsx_update(gedict_t* p, char* from, char* to); //======================================================== // // ktpro like 'cmd info' compatibility // //======================================================== #define isSysKey( key ) ( !strnull(key) && *(key) == '*' ) typedef struct cmdinfo_s { char *key; void (*f)(gedict_t *p, char *from, char *to); } cmdinfo_t; cmdinfo_t cinfos[] = { // { "*is", 0 }, // keys with * is for internal use ONLY { "*mm", info_sys_mm_update }, // for mmode // { "*ml", 0 }, // for mmode last // { "*mp", 0 }, // for mmode player // { "*mt", 0 }, // for mmode team // { "*mu", 0 }, // for mmode multi // { "*at", 0 }, // autotrack { "mi", info_mi_update }, // spec moreinfo // { "b_switch", 0 }, // { "e-mail", 0 }, { "ev", info_ev_update }, { "wpsx", info_wpsx_update }, // { "fs", 0 }, // for force_spec // { "gender", 0 }, // { "k", 0 }, // { "k_nick", 0 }, { "kf", info_kf_update }, // { "ln", 0 }, // { "ls", 0 }, // { "lw", 0 }, // { "lw_x", 0 }, // { "ktpl", 0 }, // zzz, so "ln" "ls" "lw" keys will work like in ktpro // { "postmsg", 0 }, // { "premsg", 0 }, // { "ti", 0 }, // specifie use team info or not // { "w_switch", 0 }, // { "k_sdir", 0 }, // { "wps", 0 }, // { "lra", 0 }, // ra status bar modificator // { "pbspeed", 0 }, // for /trx_play // { "runes", 0 } // for stuffing "set rune xxx" in CTF }; int cinfos_cnt = sizeof(cinfos) / sizeof(cinfos[0]); void cmdinfo(void) { int argc = trap_CmdArgc(); char arg_1[128], arg_2[128]; if (trap_CmdArgc() < 1) { return; // something wrong } trap_CmdArgv(1, arg_1, sizeof(arg_1)); trap_CmdArgv(2, arg_2, sizeof(arg_2)); if ((argc == 1) || (argc > 3)) { // just show info about all keys stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd setinfo\n"); return; } if (argc == 2) { // show info about particular key G_sprint(self, 2, "key %s = \"%s\"\n", arg_1, ezinfokey(self, arg_1)); return; } if (argc == 3) { // set/remove particular key SetUserInfo(self, arg_1, arg_2, 0); return; } } void cmduinfo(void) { gedict_t *p; int argc = trap_CmdArgc(); char *v; char arg_1[128], arg_2[128]; if (trap_CmdArgc() < 1) { return; // something wrong } if ((argc == 1) || (argc > 3)) { // just show info about usage if (isSupport_Params(self)) { G_sprint(self, 2, "usage: kuinfo [key]\n"); } else { G_sprint(self, 2, "usage: cmd uinfo [key]\n"); } return; } if (argc == 2) { // show info about keys of someone int i; trap_CmdArgv(1, arg_1, sizeof(arg_1)); if (!(p = SpecPlayer_by_IDorName(arg_1))) { G_sprint(self, 2, "client \"%s\" not found\n", arg_1); return; } G_sprint(self, 2, "%s's personal keys:\n", p->netname); for (i = 0; i < cinfos_cnt; i++) { if (isSysKey(cinfos[i].key)) { continue; // sys keys is not showed for mortals %) } v = ezinfokey(p, cinfos[i].key); if (!strnull(v)) // show not empty keys only { G_sprint(self, 2, "key %s = \"%s\"\n", cinfos[i].key, v); } } return; } if (argc == 3) { // show someone particular key trap_CmdArgv(1, arg_1, sizeof(arg_1)); trap_CmdArgv(2, arg_2, sizeof(arg_2)); if (!(p = SpecPlayer_by_IDorName(arg_1))) { G_sprint(self, 2, "client \"%s\" not found\n", arg_1); return; } if (isSysKey(arg_2)) { v = NULL; // sys keys is not showed for mortals %) } else { v = ezinfokey(p, arg_2); } if (!v) { G_sprint(self, 2, "key \"%s\" is hidden\n", arg_2); } else { G_sprint(self, 2, "%s's %s = \"%s\"\n", p->netname, arg_2, v); } return; } } // this issued on each client connect. // stuff/call "infoset" alias for player and "sinfoset" for spec void cmdinfo_infoset(gedict_t *p) { if (strnull(ezinfokey(p, "*is"))) { SetUserInfo(p, "*is", "1", SETUSERINFO_STAR); // mark we are call infoset already stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "%sinfoset\n", p->ct == ctSpec ? "s" : ""); // and call infoset stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "ktx_%sinfoset\n", p->ct == ctSpec ? "s" : ""); // and call ktx_infoset // kick cmd back to server, so we know client get infoset, // so we can invoke on_connect and on_enter stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "wait;wait;wait;cmd ack infoset\n"); } else { // kick cmd back to server, so we know client already get infoset, // so we can invoke on_enter stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "wait;wait;wait;cmd ack noinfoset\n"); } } //=================================================== // // native setinfo // //=================================================== qbool FixPlayerTeam(char *newteam); qbool FixPlayerColor(char *newcolor); qbool ClientUserInfoChanged(int after) { char arg_0[1024], arg_1[1024], arg_2[1024], *old; int i; if (trap_CmdArgc() != 3) { return false; // something wrong } trap_CmdArgv(0, arg_0, sizeof(arg_0)); trap_CmdArgv(1, arg_1, sizeof(arg_1)); trap_CmdArgv(2, arg_2, sizeof(arg_2)); // G_bprint(2, "'%s' '%s' '%s'\n", arg_0, arg_1, arg_2 ); if (after && !strcmp(arg_1, "name")) { trap_CmdArgv(2, self->netname, CLIENT_NAME_LEN); return false; } if (streq("team", arg_1)) { return FixPlayerTeam(arg_2); } if (streq("rate", arg_1)) { return CheckRate(self, arg_2); } if (streq("bottomcolor", arg_1)) { return FixPlayerColor(arg_2); } // call assigned function if any for this key old = ezinfokey(self, arg_1); for (i = 0; i < cinfos_cnt; i++) { if (streq(cinfos[i].key, arg_1)) { if (cinfos[i].f) // call some handler, if set { (cinfos[i].f)(self, old, arg_2); } break; } } return false; } //=================================================== // // different handlers // //=================================================== // in ctf we dont want red team players to be blue, etc qbool FixPlayerColor(char *newcolor) { if (self->ct == ctSpec) { return false; } if (isCTF()) { if (streq(getteam(self), "red")) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %d %d\n", iKey(self, "topcolor") == 13 ? 4 : iKey(self, "topcolor"), 4); } else if (streq(getteam(self), "blue")) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %d %d\n", iKey(self, "topcolor") == 4 ? 13 : iKey(self, "topcolor"), 13); } } return false; } // check if player tried to change team and this is allowed qbool FixPlayerTeam(char *newteam) { char *s1, *s2; if (self->ct == ctSpec) { // coach or potential coach may not change team if (coach_num(self) || is_elected(self, etCoach)) { if (strneq(getteam(self), newteam)) { G_sprint(self, 2, "You may %s change team\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", getteam(self)); // sends this to client - so he get right team too } return true; } // do we need this at all? // it is here because the coach stuff was copied from captain if (k_coaches == 2) { // get the strings to compare s1 = newteam; if (self->k_picked == 1) { s2 = cvar_string("_k_coachteam1"); } else if (self->k_picked == 2) { s2 = cvar_string("_k_coachteam2"); } else { s2 = ""; } if (strneq(s1, s2)) { G_sprint(self, 2, "You may %s change team\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", s2); // sends this to client - so he get right team too return true; } } return false; } if (isCA() && match_in_progress) { // in CA/wipeout, non-participating players are forced to not have a team. // so we must allow team change if player isn't ca_ready and newteam is "" if (self->ca_ready || strneq(newteam, "")) { G_sprint(self, 2, "You may %s change team during game\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", getteam(self)); // sends this to client - so he get right team too return true; } return false; } if (isCA() && !match_in_progress) { return false; } // do not allow change team in game / countdown if (match_in_progress || coop) { s1 = newteam; s2 = getteam(self); if (strneq(s1, s2)) { G_sprint(self, 2, "You may %s change team during game\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", s2); // sends this to client - so he get right team too } return true; } // captain or potential captain may not change team if (capt_num(self) || is_elected(self, etCaptain)) { if (strneq(getteam(self), newteam)) { G_sprint(self, 2, "You may %s change team\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", getteam(self)); // sends this to client - so he get right team too } return true; } if (k_captains == 2) { // get the strings to compare s1 = newteam; if (self->k_picked == 1) { s2 = cvar_string("_k_captteam1"); } else if (self->k_picked == 2) { s2 = cvar_string("_k_captteam2"); } else { s2 = ""; } if (strneq(s1, s2)) { G_sprint(self, 2, "You may %s change team\n", redtext("not")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", s2); // sends this to client - so he get right team too return true; } } if (!match_in_progress && isCTF() && self->ready) { // if CTF and player ready allow change team to red or blue s1 = newteam; s2 = getteam(self); if (strneq(s1, "red") && strneq(s1, "blue")) { G_sprint(self, 2, "You must be on team red or blue for CTF\n"); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", s2); // sends this to client - so he get right team too return true; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color %d\n", streq(s1, "red") ? 4 : 13); } if (!match_in_progress && (isTeam() || isCTF()) && self->ready && strnull(newteam)) { // do not allow empty team, because it cause problems G_sprint(self, 2, "Empty %s not allowed\n", redtext("team")); stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "team \"%s\"\n", getteam(self)); // sends this to client - so he get right team too return true; } if (isCTF() && (streq(newteam, "red") || streq(newteam, "blue"))) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "auto%s\n", newteam); } return false; } QW-Group-ktx-d05d6ca/src/g_utils.c000066400000000000000000001423541475442401000170420ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on Q3 VM code by 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 * * * $Id: g_utils.c 522 2007-09-15 00:32:32Z qqshka $ */ #include "g_local.h" void Sc_Stats(float on); void race_stoprecord(qbool cancel); void BotsSoundMadeEvent(gedict_t *entity); int NUM_FOR_EDICT(gedict_t *e) { int b; b = e - g_edicts; if ((b < 0) || (b >= MAX_EDICTS)) { DebugTrap("NUM_FOR_EDICT: bad pointer"); } return b; } void g_random_seed(int seed) { rng_seed_global(seed); } float g_random(void) { return (rng_next_global() >> 8 & 0xffffff) / 16777216.0f; } float crandom(void) { return (2 * (g_random() - 0.5)); } int i_rnd(int from, int to) { float r; if (from >= to) { return from; } r = (int)(from + (1.0 + to - from) * g_random()); return bound(from, r, to); } // Returns random value based on (approx) normal distribution float dist_random(float minValue, float maxValue, float spreadFactor) { float sum = 0.0f; // sum follows normal distribution from 0->6 sum += g_random(); sum += g_random(); sum += g_random(); sum += g_random(); sum += g_random(); sum += g_random(); // normal distribution will produce very low % of tail probabilities, so alter std deviation if (spreadFactor != 1) { sum = bound(0.0f, 3 + (sum - 3) * spreadFactor, 6.0f); } sum /= 6.0f; // Move to be around the average return (minValue + (maxValue - minValue) * sum); } // Should be "" but too many references in code simply checking for 0 to mean null string... #define PR2SetStringFieldOffset(ent, field) \ ent->s.v.field ## _ = NUM_FOR_EDICT(ent) * sizeof(gedict_t) + FOFS(field); \ ent->field = 0; #define PR2SetFuncFieldOffset(ent, field) \ ent->s.v.field ## _ = NUM_FOR_EDICT(ent) * sizeof(gedict_t) + FOFS(field); \ ent->field = (func_t) SUB_Null; void initialise_spawned_ent(gedict_t *ent) { #if defined(idx64) || defined(PR_ALWAYS_REFS) PR2SetStringFieldOffset(ent, classname); PR2SetStringFieldOffset(ent, model); PR2SetFuncFieldOffset(ent, touch); PR2SetFuncFieldOffset(ent, use); PR2SetFuncFieldOffset(ent, think); PR2SetFuncFieldOffset(ent, blocked); PR2SetStringFieldOffset(ent, weaponmodel); PR2SetStringFieldOffset(ent, netname); PR2SetStringFieldOffset(ent, target); PR2SetStringFieldOffset(ent, targetname); PR2SetStringFieldOffset(ent, message); PR2SetStringFieldOffset(ent, noise); PR2SetStringFieldOffset(ent, noise1); PR2SetStringFieldOffset(ent, noise2); PR2SetStringFieldOffset(ent, noise3); #endif } float next_frame(void) { return g_globalvars.time + g_globalvars.frametime; } gedict_t* spawn(void) { gedict_t *t = &g_edicts[trap_spawn()]; if (!t || (t == world)) { DebugTrap("spawn return world\n"); } t->spawn_time = g_globalvars.time; initialise_spawned_ent(t); return t; } void ent_remove(gedict_t *t) { if (!t || (t == world)) { DebugTrap("BUG BUG BUG remove world\n"); } if (NUM_FOR_EDICT(t) <= MAX_CLIENTS) // debug { G_Error("remove client"); } trap_remove(NUM_FOR_EDICT(t)); } // The bots need map entities for route-finding, so don't remove void soft_ent_remove(gedict_t *ent) { #ifdef BOT_SUPPORT if (bots_enabled()) { ent->model = ""; ent->s.v.solid = SOLID_TRIGGER; ent->s.v.nextthink = 0; ent->think = (func_t)SUB_Null; ent->touch = (func_t)marker_touch; ent->fb.desire = goal_NULL; ent->fb.goal_respawn_time = 0; } else { ent_remove(ent); } #else ent_remove(ent); #endif } gedict_t* nextent(gedict_t *ent) { int entn; if (!ent) { G_Error("find: NULL start\n"); } entn = trap_nextent(NUM_FOR_EDICT(ent)); if (entn) { return &g_edicts[entn]; } else { return NULL; } } /*gedict_t *find( gedict_t * start, int fieldoff, char *str ) { gedict_t *e; char *s; if ( !start ) G_Error( "find: NULL start\n" ); for ( e = nextent( start ); e; e = nextent( e ) ) { s = *( char ** ) ( ( byte * ) e + fieldoff ); if ( s && !strcmp( s, str ) ) return e; } return NULL; }*/ gedict_t* find(gedict_t *start, int fieldoff, char *str) { return trap_find(start, fieldoff, str); } // well, this is probably must be most common function for edicts find(), but I "invented" it too late. gedict_t* ez_find(gedict_t *start, char *str) { return trap_find(start, FOFCLSN, str); } // find count of "good" edicts int find_cnt(int fieldoff, char *str) { int cnt; gedict_t *p; for (cnt = 0, p = world; (p = find(p, fieldoff, str));) { cnt++; } return cnt; } gedict_t* find_idx(int idx, int fieldoff, char *str) { int cnt; gedict_t *p; if (idx < 0) { return NULL; } for (cnt = 0, p = world; (p = find(p, fieldoff, str)); cnt++) { if (cnt == idx) { break; } } return p; } void normalize(vec3_t value, vec3_t newvalue) { float new; new = value[0] * value[0] + value[1] * value[1] + value[2] * value[2]; new = sqrt(new); if (new == 0) { newvalue[0] = newvalue[1] = newvalue[2] = 0; } else { new = 1 / new; newvalue[0] = value[0] * new; newvalue[1] = value[1] * new; newvalue[2] = value[2] * new; } } void aim(vec3_t ret) { VectorCopy(g_globalvars.v_forward, ret); } const char null_str[] = ""; int streq(const char *s1, const char *s2) { if (!s1) { s1 = null_str; } if (!s2) { s2 = null_str; } return (!strcmp(s1, s2)); } int strneq(const char *s1, const char *s2) { if (!s1) { s1 = null_str; } if (!s2) { s2 = null_str; } return (strcmp(s1, s2)); } int strnull(const char *s1) { return (!s1 || !*s1); } // qqshka - not sure is this a good idea replacing max/min with real function #ifdef KTX_MIN float min(float a, float b) { return (a < b ? a : b); } #endif #ifdef KTX_MAX float max(float a, float b) { return (a > b ? a : b); } #endif float bound(float a, float b, float c) { return ((a >= c) ? a : (b < a) ? a : (b > c) ? c : b); } /* ================= vlen scalar vlen(vector) ================= */ float vlen(vec3_t value1) { float new; new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2] * value1[2]; new = sqrt(new); return new; } float vectoyaw(vec3_t value1) { float yaw; if ((value1[1] == 0) && (value1[0] == 0)) { yaw = 0; } else { yaw = /*( int )*/(atan2(value1[1], value1[0]) * 180 / M_PI); if (yaw < 0) { yaw += 360; } } return yaw; } void vectoangles(vec3_t value1, vec3_t ret) { float forward; float yaw, pitch; if (value1[1] == 0 && value1[0] == 0) { yaw = 0; if (value1[2] > 0) { pitch = 90; } else { pitch = 270; } } else { yaw = /*( int )*/(atan2(value1[1], value1[0]) * 180 / M_PI); 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; } } ret[0] = pitch; ret[1] = yaw; ret[2] = 0; } /* ================= Returns a chain of entities that have origins within a spherical area findradius (origin, radius) ================= */ #if 0 // worked, but unused since we have trap_findradius gedict_t *findradius( gedict_t * start, vec3_t org, float rad ) { gedict_t *ent; vec3_t eorg; int j; for (ent = nextent(start); ent; ent = nextent(ent)) { if (ent->s.v.solid == SOLID_NOT) { continue; } for (j = 0; j < 3; j++) { eorg[j] = org[j] - (ent->s.v.origin[j] + (ent->s.v.mins[j] + ent->s.v.maxs[j]) * 0.5); } if (VectorLength(eorg) > rad) { continue; } return ent; } return NULL; } #endif // Same as findradius but ignore solid field. gedict_t* findradius_ignore_solid(gedict_t *start, vec3_t org, float rad) { gedict_t *ent; vec3_t eorg; int j; for (ent = nextent(start); ent; ent = nextent(ent)) { // if ( ent->s.v.solid == SOLID_NOT ) // continue; for (j = 0; j < 3; j++) { eorg[j] = org[j] - (ent->s.v.origin[j] + (ent->s.v.mins[j] + ent->s.v.maxs[j]) * 0.5); } if (VectorLength(eorg) > rad) { continue; } return ent; } return NULL; } /* ============== changeyaw This was a major timewaster in progs, so it was converted to C Turns towards self.ideal_yaw at self.yaw_speed Sets the global variable current_yaw Called every 0.1 sec by monsters ============== */ void changeyaw(gedict_t *ent) { float ideal, current, move, speed; current = anglemod(ent->s.v.angles[1]); ideal = ent->s.v.ideal_yaw; speed = ent->s.v.yaw_speed; if (current == ideal) { return; } move = ideal - current; 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.v.angles[1] = anglemod(current + move); } /* ============== PF_makevectors Writes new values for v_forward, v_up, and v_right based on angles makevectors(vector) ============== */ /* replaced with trap_makevectors void makevectors( vec3_t vector ) { AngleVectors( vector, g_globalvars.v_forward, g_globalvars.v_right, g_globalvars.v_up ); } */ /* ============ va does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functions. FIXME: make this buffer size safe someday ============ */ char* va(char *format, ...) { va_list argptr; static char string[MAX_STRINGS * 2][1024]; // qqshka - brrr static int index = 0; index %= MAX_STRINGS; va_start(argptr, format); Q_vsnprintf(string[index], sizeof(string[0]), format, argptr); va_end(argptr); string[index][sizeof(string[0]) - 1] = '\0'; return string[index++]; } char* redtext(char *format) { // >>>> like va(...) static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; strlcpy(string[index], format ? format : "", sizeof(string[0])); // <<<< { // convert to red unsigned char *i = (unsigned char*) string[index]; for (; *i; i++) { if ((*i > 32) && (*i < 128)) { *i |= 128; } } return string[index++]; } } char* cleantext(char *format) { // >>>> like va(...) static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; strlcpy(string[index], format ? format : "", sizeof(string[0])); // <<<< { // convert to red unsigned char *i = (unsigned char*) string[index]; for (; *i; i++) { if ((*i < 32) || ((*i > 126) && (*i < 160)) || (*i > 254)) { *i = 95; } } return string[index++]; } } char* dig3(int d) { static char string[MAX_STRINGS][32]; static int index = 0; index %= MAX_STRINGS; snprintf(string[index], sizeof(string[0]), "%d", d); string[index][sizeof(string[0]) - 1] = '\0'; { // convert digits unsigned char *i = (unsigned char*)(string[index]); for (; *i; i++) { if ((*i >= '0') && (*i <= '9')) { *i += 98; } } } return string[index++]; } char* dig3s(const char *format, ...) { // >>>> like va(...) va_list argptr; static char string[MAX_STRINGS][32]; static int index = 0; index %= MAX_STRINGS; va_start(argptr, format); Q_vsnprintf(string[index], sizeof(string[0]), format, argptr); va_end(argptr); string[index][sizeof(string[0]) - 1] = '\0'; // <<<< { // convert digits unsigned char *i = (unsigned char*)(string[index]); for (; *i; i++) { if ((*i >= '0') && (*i <= '9')) { *i += 98; } } } return string[index++]; } char* striphigh(char *format) { // >>>> like va(...) static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; strlcpy(string[index], format ? format : "", sizeof(string[0])); // <<<< { unsigned char *i = (unsigned char*) string[index]; for (; *i; i++) { *i &= 127; } return string[index++]; } } char* stripcaps(char *format) { // >>>> like va(...) static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; strlcpy(string[index], format ? format : "", sizeof(string[0])); // <<<< { unsigned char *i = (unsigned char*) string[index]; for (; *i; i++) { if ((*i >= 'A') && (*i <= 'Z')) { *i += 'a' - 'A'; } } } return string[index++]; } /* ============== print functions ============== */ void G_sprint(gedict_t *ed, int level, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_SPrint(NUM_FOR_EDICT(ed), level, text, 0); } void G_sprint_flags(gedict_t *ed, int level, int flags, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_SPrint(NUM_FOR_EDICT(ed), level, text, flags); } void G_bprint(int level, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_BPrint(level, text, 0); } void G_bprint_flags(int level, int flags, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_BPrint(level, text, flags); } void G_cprint(const char *fmt, ...) { va_list argptr; char text[1024 * 4]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_conprint(text); } void G_centerprint(gedict_t *ed, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_CenterPrint(NUM_FOR_EDICT(ed), text); } // centerprint to all clients void G_cp2all(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); text[sizeof(text) - 1] = 0; va_end(argptr); if (FTE_sv) { gedict_t *p; for (p = world; (p = find_client(p));) { G_centerprint(p, "%s", text); } } else { WriteByte(MSG_ALL, SVC_CENTERPRINT); WriteString(MSG_ALL, text); } } void G_dprint(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_DPrintf(text); } void localcmd(const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_localcmd(text); } void stuffcmd(gedict_t *ed, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_stuffcmd(NUM_FOR_EDICT(ed), text, 0); } void stuffcmd_flags(gedict_t *ed, int flags, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); trap_stuffcmd(NUM_FOR_EDICT(ed), text, flags); } void setorigin(gedict_t *ed, float origin_x, float origin_y, float origin_z) { trap_setorigin(NUM_FOR_EDICT(ed), origin_x, origin_y, origin_z); } void setsize(gedict_t *ed, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { trap_setsize(NUM_FOR_EDICT(ed), min_x, min_y, min_z, max_x, max_y, max_z); } void setmodel(gedict_t *ed, char *model) { trap_setmodel(NUM_FOR_EDICT(ed), model); } void sound(gedict_t *ed, int channel, char *samp, float vol, float att) { if (!samp || !*samp) return; // ignore null sample if (isRACE() && ed->muted) return; #ifdef BOT_SUPPORT if (bots_enabled()) { BotsSoundMadeEvent(ed); } #endif trap_sound(NUM_FOR_EDICT(ed), channel, samp, vol, att); } gedict_t* checkclient(void) { return &g_edicts[trap_checkclient()]; } void traceline(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, int nomonst, gedict_t *ed) { trap_traceline(v1_x, v1_y, v1_z, v2_x, v2_y, v2_z, nomonst, NUM_FOR_EDICT(ed)); } void TraceCapsule(float v1_x, float v1_y, float v1_z, float v2_x, float v2_y, float v2_z, int nomonst, gedict_t *ed, float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { trap_TraceCapsule(v1_x, v1_y, v1_z, v2_x, v2_y, v2_z, nomonst, NUM_FOR_EDICT(ed), min_x, min_y, min_z, max_x, max_y, max_z); } int droptofloor(gedict_t *ed) { return trap_droptofloor(NUM_FOR_EDICT(ed)); } int checkbottom(gedict_t *ed) { return trap_checkbottom(NUM_FOR_EDICT(ed)); } void makestatic(gedict_t *ed) { trap_makestatic(NUM_FOR_EDICT(ed)); } void setspawnparam(gedict_t *ed) { trap_setspawnparam(NUM_FOR_EDICT(ed)); } void logfrag(gedict_t *killer, gedict_t *killee) { trap_logfrag(NUM_FOR_EDICT(killer), NUM_FOR_EDICT(killee)); } // WARNING: this function doest support 'cmd info' keys and this is MUST be so char* infokey(gedict_t *ed, char *key, char *valbuff, int sizebuff) { trap_infokey(NUM_FOR_EDICT(ed), key, valbuff, sizebuff); return valbuff; } char* ezinfokey(gedict_t *ed, char *key) { static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; trap_infokey(NUM_FOR_EDICT(ed), key, string[index], sizeof(string[0])); return string[index++]; } int iKey(gedict_t *ed, char *key) { char string[128]; // which size will be best? trap_infokey(NUM_FOR_EDICT(ed), key, string, sizeof(string)); return atoi(string); } float fKey(gedict_t *ed, char *key) { char string[128]; // which size will be best? trap_infokey(NUM_FOR_EDICT(ed), key, string, sizeof(string)); return atof(string); } void WriteEntity(int to, gedict_t *ed) { trap_WriteEntity(to, NUM_FOR_EDICT(ed)); } void WriteByte(int to, int data) { trap_WriteByte(to, data); } void WriteShort(int to, int data) { trap_WriteShort(to, data); } void WriteLong(int to, int data) { trap_WriteLong(to, data); } void WriteString(int to, char *data) { trap_WriteString(to, data); } void WriteAngle(int to, float data) { trap_WriteAngle(to, data); } void WriteCoord(int to, float data) { trap_WriteCoord(to, data); } void disableupdates(gedict_t *ed, float time) { trap_disableupdates(NUM_FOR_EDICT(ed), time); } int walkmove(gedict_t *ed, float yaw, float dist) { gedict_t *saveself, *saveother, *saveactivator; int retv; saveself = self; saveother = other; saveactivator = activator; retv = trap_walkmove(NUM_FOR_EDICT(ed), yaw, dist); self = saveself; other = saveother; activator = saveactivator; return retv; } int movetogoal(float dist) { gedict_t *saveself, *saveother, *saveactivator; int retv; saveself = self; saveother = other; saveactivator = activator; retv = trap_movetogoal(dist); self = saveself; other = saveother; activator = saveactivator; return retv; } float cvar(const char *var) { if (strnull(var)) G_Error("cvar null"); return trap_cvar(var); } char* cvar_string(const char *var) { static char string[MAX_STRINGS][1024]; static int index = 0; index %= MAX_STRINGS; trap_cvar_string(var, string[index], sizeof(string[0])); return string[index++]; } void cvar_set(const char *var, const char *val) { if (strnull(var) || val == NULL) G_Error("cvar_set null"); trap_cvar_set(var, val); } void cvar_fset(const char *var, float val) { if (strnull(var)) G_Error("cvar_fset null"); trap_cvar_set_float(var, val); } int getteams(char teams[MAX_CLIENTS][MAX_TEAM_NAME]) { char *team; int i, j; // clear array for (i = 0; i < MAX_CLIENTS; i++) { teams[i][0] = 0; } for (i = 1; i <= MAX_CLIENTS; i++) { if (g_edicts[i].ct != ctPlayer) { continue; // collect only players teams } team = getteam(&(g_edicts[i])); if (strnull(team)) { continue; // empty team } for (j = 0; j < MAX_CLIENTS; j++) { if (strnull(teams[j])) { strlcat(teams[j], team, MAX_TEAM_NAME); // add new team to array break; } if (streq(teams[j], team)) { break; // team already in array } } } for (j = 0; j < MAX_CLIENTS; j++) { if (strnull(teams[j])) { break; } } return j; } // i'm tired of this shit, so implement this // return team of edict, edict may has "player" or "ghost" classname char* getteam(gedict_t *ed) { static char string[MAX_STRINGS][128]; static int index = 0; char *team = NULL; int num = (int)(ed - g_edicts); index %= MAX_STRINGS; if ((num >= 1) && (num <= MAX_CLIENTS)) { team = ezinfokey(ed, "team"); } else if (streq(ed->classname, "ghost")) { team = ezinfokey(world, va("%d", (int)ed->k_teamnum)); } else { // G_Error("getteam: wrong classname %s", ed->classname); team = ""; } string[index][0] = 0; strlcat(string[index], team, sizeof(string[0])); return string[index++]; } char* getname(gedict_t *ed) { static char string[MAX_STRINGS][1024]; static int index = 0; char *name = NULL; int num = (int)(ed - g_edicts); index %= MAX_STRINGS; if ((num >= 1) && (num <= MAX_CLIENTS)) { name = ed->netname; } else if (streq(ed->classname, "ghost")) { name = ezinfokey(world, va("%d", (int)ed->cnt2)); } else { name = ""; // G_Error("getname: wrong classname %s", ed->classname); } string[index][0] = 0; strlcat(string[index], name, sizeof(string[0])); return string[index++]; } // return "his" or "her" depend on gender of player char* g_his(gedict_t *ed) { static char string[MAX_STRINGS][5]; static int index = 0; char *sex = "his"; index %= MAX_STRINGS; // if ( ed->ct != ctPlayer && ed->ct != ctSpec ) // G_Error("g_his: not client, classname %s", ed->classname); if (streq(ezinfokey(ed, "gender"), "f")) { sex = "her"; } string[index][0] = 0; strlcat(string[index], sex, sizeof(string[0])); return string[index++]; } // return "he" or "she" depend on gender of player char* g_he(gedict_t *ed) { static char string[MAX_STRINGS][5]; static int index = 0; char *sex = "he"; index %= MAX_STRINGS; // if ( ed->ct != ctPlayer && ed->ct != ctSpec ) // G_Error("g_his: not client, classname %s", ed->classname); if (streq(ezinfokey(ed, "gender"), "f")) { sex = "she"; } string[index][0] = 0; strlcat(string[index], sex, sizeof(string[0])); return string[index++]; } // return "himself" or "herself" depend on gender of player char* g_himself(gedict_t *ed) { static char string[MAX_STRINGS][9]; static int index = 0; char *sex = "himself"; index %= MAX_STRINGS; // if ( ed->ct != ctPlayer && ed->ct != ctSpec ) // G_Error("g_himself: not client, classname %s", ed->classname); if (streq(ezinfokey(ed, "gender"), "f")) { sex = "herself"; } string[index][0] = 0; strlcat(string[index], sex, sizeof(string[0])); return string[index++]; } gedict_t* find_client(gedict_t *start) { for (; (start = trap_nextclient(start));) { if ((start->ct == ctPlayer) || (start->ct == ctSpec)) { return start; } } return NULL; } gedict_t* find_plr(gedict_t *start) { for (; (start = trap_nextclient(start));) { if (start->ct == ctPlayer) { return start; } } return NULL; } // little helper function that tries to locate a player within the given team // it return the player, or NULL of no player found gedict_t* find_plr_same_team(gedict_t *start, char *team) { for (; (start = trap_nextclient(start));) { if ((start->ct == ctPlayer) && (streq(getteam(start), team))) { return start; } } return NULL; } gedict_t* find_spc(gedict_t *start) { for (; (start = trap_nextclient(start));) { if (start->ct == ctSpec) { return start; } } return NULL; } // this help me walk from both players and ghosts, made code more simple // int from = 0; // gedict_t *p = world ; // while ( p = find_plrghst(p, &from) ) { // ... some code ... // } gedict_t* find_plrghst(gedict_t *start, int *from) { gedict_t *next = (*from ? find(start, FOFCLSN, "ghost") : find_plr(start)); if (!next && !*from) { *from = 1; next = find(world, FOFCLSN, "ghost"); } return next; } // this help me walk from both players and specs, made code more simple gedict_t* find_plrspc(gedict_t *start, int *from) { gedict_t *next = (*from ? find_spc(start) : find_plr(start)); if (!next && !*from) { *from = 1; next = find_spc(world); } return next; } gedict_t* player_by_id(int id) { gedict_t *p; if (id < 1) { return NULL; } for (p = world; (p = find_plr(p));) { if (id == GetUserID(p)) { return p; } } return NULL; } gedict_t* player_by_name(const char *name) { gedict_t *p; if (strnull(name)) { return NULL; } for (p = world; (p = find_plr(p));) { if (streq(p->netname, name)) { return p; } } return NULL; } gedict_t* player_by_IDorName(const char *IDname) { gedict_t *p = player_by_id(atoi(IDname)); return (p ? p : player_by_name(IDname)); } gedict_t* spec_by_id(int id) { gedict_t *p; if (id < 1) { return NULL; } for (p = world; (p = find_spc(p));) { if (id == GetUserID(p)) { return p; } } return NULL; } gedict_t* spec_by_name(const char *name) { gedict_t *p; if (strnull(name)) { return NULL; } for (p = world; (p = find_spc(p));) { if (streq(p->netname, name)) { return p; } } return NULL; } gedict_t* spec_by_IDorName(const char *IDname) { gedict_t *p = spec_by_id(atoi(IDname)); return (p ? p : spec_by_name(IDname)); } gedict_t* SpecPlayer_by_IDorName(const char *IDname) { gedict_t *p = player_by_IDorName(IDname); return (p ? p : spec_by_IDorName(IDname)); } gedict_t* SpecPlayer_by_id(int id) { gedict_t *p = spec_by_id(id); return (p ? p : player_by_id(id)); } gedict_t* not_connected_by_id(int id) { char *statk; gedict_t *p; for (p = g_edicts + 1; p <= g_edicts + MAX_CLIENTS; p++) { if ((streq(statk = ezinfokey(p, "*state"), "preconnected") || streq(statk, "connected")) && iKey(p, "*userid") == id) // can't use GetUserID here { return p; } } return NULL; } gedict_t* not_connected_by_name(const char *name) { char *statk; gedict_t *p; for (p = g_edicts + 1; p <= g_edicts + MAX_CLIENTS; p++) { if ((streq(statk = ezinfokey(p, "*state"), "preconnected") || streq(statk, "connected")) && streq(p->netname, name)) { return p; } } return NULL; } gedict_t* not_connected_by_IDorName(const char *IDname) { gedict_t *p = not_connected_by_id(atoi(IDname)); return (p ? p : not_connected_by_name(IDname)); } char* armor_type(int items) { static char string[MAX_STRINGS][4]; static int index = 0; char *at; index %= MAX_STRINGS; if (items & IT_ARMOR1) { at = "ga"; } else if (items & IT_ARMOR2) { at = "ya"; } else if (items & IT_ARMOR3) { at = "ra"; } else { at = "0"; } string[index][0] = 0; strlcat(string[index], at, sizeof(string[0])); return string[index++]; } qbool isghost(gedict_t *ed) { return (streq(ed->classname, "ghost") ? true : false); } // gametype >>> qbool isDuel(void) { return ((k_mode == gtDuel) ? true : false); } qbool isTeam(void) { return ((k_mode == gtTeam) ? true : false); } int tp_num(void) { return ((isTeam() || isCTF() || coop) ? teamplay : 0); } qbool isFFA(void) { return ((k_mode == gtFFA) ? true : false); } qbool isCTF(void) { #ifdef CTF_RELOADMAP return k_ctf; // once setup at map load #else return ((k_mode == gtCTF) ? true : false); #endif } qbool isUnknown(void) { #ifdef CTF_RELOADMAP if (cvar("k_mode") == gtCTF) { return false; // zzzz, hack, let FixRules work less or more correctly } return ((!isDuel() && !isTeam() && !isFFA() && !isCTF()) ? true : false); #else return ((!isDuel() && !isTeam() && !isFFA() && !isCTF()) ? true : false); #endif } // <<< gametype int GetUserID(gedict_t *p) { if (!p || ((p->ct != ctPlayer) && (p->ct != ctSpec))) { return 0; } return iKey(p, "*userid"); } // get name of player whom spectator 'p' tracking // if something wrong returned value is "" char* TrackWhom(gedict_t *p) { static char string[MAX_STRINGS][32]; static int index = 0; char *name; gedict_t *goal = NULL; index %= MAX_STRINGS; if (p && (p->ct == ctSpec) && ((goal = PROG_TO_EDICT(p->s.v.goalentity)) != world) && (goal->ct == ctPlayer)) { name = getname(goal); } else { name = ""; } string[index][0] = 0; strlcat(string[index], name, sizeof(string[0])); return string[index++]; } int GetHandicap(gedict_t *p) { int hdc = p->ps.handicap < 1 ? 100 : bound(50, p->ps.handicap, 150); return (cvar("k_lock_hdp") ? 100 : hdc); } qbool SetHandicap(gedict_t *p, int nhdc) { int hdc = GetHandicap(p); // remember before change if (match_in_progress) { return false; } if (cvar("k_lock_hdp")) { G_sprint(self, 2, "%s changes are not allowed\n", redtext("handicap")); return false; } p->ps.handicap = nhdc; // set, unbound p->ps.handicap = nhdc = GetHandicap(p); // set, bounded // anonce if changed if (nhdc != hdc) { if (nhdc == 100) { G_bprint(2, "%s turns %s off\n", p->netname, redtext("handicap")); } else { G_bprint(2, "%s uses %s %d%%\n", p->netname, redtext("handicap"), nhdc); } return true; } return false; } void changelevel(const char *name) { const char *entityFileSep = NULL; if (strnull(name)) { G_Error("changelevel: null"); } if (isRACE() && race.race_recording) { race_stoprecord(true); } entityFileSep = strchr(name, K_ENTITYFILE_SEPARATOR); if (entityFileSep) { char mapName[128] = { 0 }; cvar_set("k_entityfile", name); strlcpy(mapName, (char*) name, min(entityFileSep - name + 1, sizeof(mapName) / sizeof(mapName[0]))); trap_changelevel(mapName, name); } else { cvar_set("k_entityfile", ""); trap_changelevel(name, ""); } } char* Get_PowerupsStr(void) { static char str[5]; str[0] = 0; // global off or all off if (!cvar("k_pow") || (!cvar("k_pow_q") && !cvar("k_pow_p") && !cvar("k_pow_r") && !cvar("k_pow_s"))) { strlcpy(str, "off", sizeof(str)); return str; } // all on if (cvar("k_pow_q") && cvar("k_pow_p") && cvar("k_pow_r") && cvar("k_pow_s")) { strlcpy(str, "on", sizeof(str)); return str; } if (cvar("k_pow_q")) { strlcat(str, "q", sizeof(str)); } if (cvar("k_pow_p")) { strlcat(str, "p", sizeof(str)); } if (cvar("k_pow_r")) { strlcat(str, "r", sizeof(str)); } if (cvar("k_pow_s")) { strlcat(str, "s", sizeof(str)); } return str; } int Get_Powerups(void) { static float k_pow_check = 0; static int k_pow = 0; int k_pow_new = k_killquad ? 1 : cvar("k_pow"); // sure - here we not using Get_Powerups int k_pow_min_players = bound(0, cvar("k_pow_min_players"), 999); int k_pow_check_time = bound(0, cvar("k_pow_check_time"), 999); k_pow_check_time = !k_pow_check_time ? 10 : k_pow_check_time; // default is 10 if (!k_pow_new || !k_matchLess || !k_pow_min_players || !deathmatch) { return (k_pow = k_pow_new); // no k_pow_min_players if server in normal match mode // no powerups if k_pow == 0 // return current value of key 'k_pow' if k_pow_min_players == 0 } if (k_pow_check > g_globalvars.time) { return k_pow; // too soon to re-check, so return result of last check } // ok, time to re-check if powerups is still actual, or we have lack of players // some work around because not all players may fully connected yet if (framecount == 1) { k_pow = cvar("_k_pow_last"); // restore k_pow from last level k_pow_new = WeirdCountPlayers() < k_pow_min_players ? 0 : k_pow_new; } else { k_pow_new = CountPlayers() < k_pow_min_players ? 0 : k_pow_new; } k_pow_check = g_globalvars.time + k_pow_check_time; if (k_pow != k_pow_new) { G_bprint(2, "Server decides to turn %s %s\n", redtext("powerups"), redtext(OnOff(k_pow_new))); } return (k_pow = k_pow_new); } char* count_s(int cnt) { return ((cnt == 1) ? "" : "s"); } char* Enables(float f) { return (f ? "enables" : "disables"); } char* Enabled(float f) { return (f ? "enabled" : "disabled"); } char* Allows(float f) { return (f ? "allows" : "disallows"); } char* Allowed(float f) { return (f ? "allowed" : "disallowed"); } char* OnOff(float f) { return (f ? "on" : "off"); } // { some scores stuff // for team games int k_scores1 = 0; int k_scores2 = 0; int k_scores3 = 0; // for ffa and duel gedict_t *ed_scores1 = NULL; gedict_t *ed_scores2 = NULL; void ReScores(void) { gedict_t *p; int from; char *team1; char *team2; char *team3; char *team; // DO this by checking if k_nochange is 0. // which is set in ClientObituary in client.c if (k_nochange) { return; } // ok - scores potentially changed, recalculate k_nochange = 1; k_scores1 = 0; k_scores2 = 0; k_scores3 = 0; if (k_showscores) { team1 = cvar_string("_k_team1"); team2 = cvar_string("_k_team2"); team3 = cvar_string("_k_team3"); for (from = 0, p = world; (p = find_plrghst(p, &from));) { team = getteam(p); if (streq(team1, team)) { k_scores1 += p->s.v.frags; } else if (streq(team2, team)) { k_scores2 += p->s.v.frags; } else if (streq(team3, team)) { k_scores3 += p->s.v.frags; } else { } } } ed_scores1 = NULL; ed_scores2 = NULL; if ((isDuel() || isFFA()) && CountPlayers() > 1) { // no ghost serving for (p = world; (p = find_plr(p));) { if (!ed_scores1) { // set some first player as best player ed_scores1 = p; continue; } if (ed_scores1->s.v.frags < p->s.v.frags) { // seems first player is must be second and player 'p' is must be first ed_scores2 = ed_scores1; ed_scores1 = p; continue; } if (!ed_scores2 || ed_scores2->s.v.frags < p->s.v.frags) { // seemd player 'p' must be second ed_scores2 = p; continue; } } if (!ed_scores1 || !ed_scores2) { ed_scores1 = NULL; ed_scores2 = NULL; } } } int get_scores1(void) { ReScores(); return k_scores1; } int get_scores2(void) { ReScores(); return k_scores2; } int get_scores3(void) { ReScores(); return k_scores3; } gedict_t* get_ed_scores1(void) { ReScores(); return ed_scores1; } gedict_t* get_ed_scores2(void) { ReScores(); return ed_scores2; } // } // { // autotrack stuff gedict_t *ed_best1 = NULL; gedict_t *ed_best2 = NULL; gedict_t *ed_bestPow = NULL; void CalculateBestPlayers(void) { gedict_t *p; int best, best1, best2; // ok - best povs potentially changed, recalculate best1 = 0; best2 = 0; ed_best1 = NULL; ed_best2 = NULL; if (isRACE()) { ed_best1 = race_get_racer(); return; } // autotrack stuff // no ghost serving for (p = world; (p = find_plr(p));) { if (ISDEAD(p)) { continue; } /* Pentagram of Protection 99999 Quad Damage 9000 any other Powerup 4000 Rocket Launcher with ammo 1500 Lightning Gun with ammo 500 Grenade Launcher with ammo 200 Super Nailgun with ammo 100 Super Shotgun with ammo 50 */ best = 0; best += (p->invincible_finished >= g_globalvars.time) ? 99999 : 0; // pent best += (p->super_damage_finished >= g_globalvars.time) ? 9000 : 0; // quad best += (p->invisible_finished >= g_globalvars.time || p->radsuit_finished >= g_globalvars.time) ? 4000 : 0; // ring or suit best += (((int)p->s.v.items & IT_ROCKET_LAUNCHER) && p->s.v.ammo_rockets > 0) ? 1500 : 0; // rl with ammo best += (((int)p->s.v.items & IT_LIGHTNING) && p->s.v.ammo_cells > 0) ? 500 : 0; // lg with ammo best += (((int)p->s.v.items & IT_GRENADE_LAUNCHER) && p->s.v.ammo_rockets > 0) ? 200 : 0; // gl with ammo best += (((int)p->s.v.items & IT_SUPER_NAILGUN) && p->s.v.ammo_nails > 0) ? 100 : 0; // sng with ammo best += (((int)p->s.v.items & IT_SUPER_SHOTGUN) && p->s.v.ammo_shells > 0) ? 50 : 0; // ssg with ammo best += p->s.v.frags; if (!ed_best1) { // select some first player as best ed_best1 = p; best1 = best; continue; } if (best1 < best) { // seems first player is must be second and player 'p' is must be first ed_best2 = ed_best1; ed_best1 = p; best2 = best1; best1 = best; continue; } if (!ed_best2 || best2 < best) { // seems player 'p' must be second ed_best2 = p; best2 = best; continue; } } } void CalculateBestPowPlayers(void) { gedict_t *p; int best, best1; // ok - best povs potentially changed, recalculate best1 = 0; ed_bestPow = NULL; if (isRACE()) { ed_bestPow = race_get_racer(); return; } // auto_pow stuff // no ghost serving for (p = world; (p = find_plr(p));) { if (ISDEAD(p)) { continue; } /* Pentagram of Protection 4000 Quad Damage 2000 Ring 1000 Suit 500 */ best = 0; best += (p->invincible_finished >= g_globalvars.time) ? 4000 : 0; // pent best += (p->super_damage_finished >= g_globalvars.time) ? 2000 : 0; // quad best += (p->invisible_finished >= g_globalvars.time) ? 1000 : 0; // ring // Disabled biosuit to trigger autotrack, as recent gameplays of new 2024 maps with // biosuit showed that this is unwanted // best += (p->radsuit_finished >= g_globalvars.time) ? 500 : 0; // suit best += p->s.v.frags; if (!ed_bestPow || best1 < best) { ed_bestPow = p; best1 = best; continue; } } } gedict_t* get_ed_best1(void) { CalculateBestPlayers(); return ed_best1; } gedict_t* get_ed_best2(void) { CalculateBestPlayers(); return ed_best2; } gedict_t* get_ed_bestPow(void) { CalculateBestPowPlayers(); return ed_bestPow; } // } char* str_noweapon(int k_disallow_weapons) { static char string[MAX_STRINGS][128]; static int index = 0; index %= MAX_STRINGS; string[index][0] = 0; if (k_disallow_weapons & IT_AXE) { strlcat(string[index], " axe", sizeof(string[0])); } if (k_disallow_weapons & IT_SHOTGUN) { strlcat(string[index], " sg", sizeof(string[0])); } if (k_disallow_weapons & IT_SUPER_SHOTGUN) { strlcat(string[index], " ssg", sizeof(string[0])); } if (k_disallow_weapons & IT_NAILGUN) { strlcat(string[index], " ng", sizeof(string[0])); } if (k_disallow_weapons & IT_SUPER_NAILGUN) { strlcat(string[index], " sng", sizeof(string[0])); } if (k_disallow_weapons & IT_GRENADE_LAUNCHER) { strlcat(string[index], " gl", sizeof(string[0])); } if (k_disallow_weapons & IT_ROCKET_LAUNCHER) { strlcat(string[index], " rl", sizeof(string[0])); } if (k_disallow_weapons & IT_LIGHTNING) { strlcat(string[index], " lg", sizeof(string[0])); } return string[index++]; } void cvar_toggle_msg(gedict_t *p, char *cvarName, char *msg) { int i; if (strnull(cvarName)) { return; } i = !cvar(cvarName); if (!strnull(msg)) { G_bprint(2, "%s %s %s\n", p->netname, Enables(i), msg); } trap_cvar_set_float(cvarName, (float) i); } // generally - this check if we can read file - but used for exec command qbool can_exec(char *name) { fileHandle_t handle; if (trap_FS_OpenFile(name, &handle, FS_READ_BIN) >= 0) { trap_FS_CloseFile(handle); return true; } return false; } // { ghosts stuff void ghostClearScores(gedict_t *g) { int to = MSG_ALL; int cl_slot = g->ghost_slot; if (cvar_string("k_no_scoreboard_ghosts")[0]) { return; // Scoreboard ghosts disabled, probably for QE compatibility. } if (strneq(g->classname, "ghost")) { return; } if ((cl_slot < 1) || (cl_slot > MAX_CLIENTS)) { return; } if (!strnull(g_edicts[cl_slot].netname)) { return; // slot is busy - does't clear } g_edicts[cl_slot].ghost_slot = 0; // mark it as free cl_slot--; WriteByte(to, SVC_UPDATEUSERINFO); // update userinfo WriteByte(to, cl_slot); // client number WriteLong(to, 0); // client userid WriteString(to, "\\name\\"); } void ghost2scores(gedict_t *g) { int to = MSG_ALL; int cl_slot; if (cvar_string("k_no_scoreboard_ghosts")[0]) { return; // Scoreboard ghosts disabled, probably for QE compatibility. } if (isRA()) { // Renzo: Disconnected player shouldn't be listed in the scoreboard in RA. // qqshka: Personally I'm not sure how it must be, but folloing Renzo's words atm. return; } if (isCA()) { // Don't show disconnected players in scoreboard in CA. return; } if (strneq(g->classname, "ghost")) { return; } cl_slot = g->ghost_slot; // try restore if ((cl_slot < 1) || (cl_slot > MAX_CLIENTS) || !strnull(g_edicts[cl_slot].netname)) { cl_slot = 0; // slot was occupied or wrong } // check is restore possible if (cl_slot < 1) { for (cl_slot = 1; cl_slot <= MAX_CLIENTS; cl_slot++) { if (g_edicts[cl_slot].ghost_slot) { continue; // some ghost is already uses this slot } if (strnull(g_edicts[cl_slot].netname)) { break; } } } if (cl_slot > MAX_CLIENTS) { return; // no free slot for ghost } g_edicts[cl_slot].ghost_slot = cl_slot; // mark it as not free g->ghost_slot = cl_slot; // save slot - so we can clear/restore it in future cl_slot--; WriteByte(to, SVC_UPDATEUSERINFO); // update userinfo WriteByte(to, cl_slot); // client number WriteLong(to, 0); // client userid WriteString( to, va("\\name\\\x83 %s\\team\\%s\\topcolor\\%d\\bottomcolor\\%d", getname(g), getteam(g), (int)bound(0, ((g->ghost_clr >> 8) & 0xF), 13), (int)bound(0, (g->ghost_clr & 0xF), 13))); WriteByte(to, SVC_UPDATEFRAGS); // update frags WriteByte(to, cl_slot); WriteShort(to, g->s.v.frags); WriteByte(to, SVC_UPDATEENTERTIME); // update time WriteByte(to, cl_slot); // client number // FIXME: !!! qqshka: - must be WriteFloat but API have not it - so use WriteLong - dunno is this ok WriteLong(to, (int)(g_globalvars.time - g->ghost_dt)); // client enter time - here time since player was dropped WriteByte(to, SVC_UPDATEPING); // update ping WriteByte(to, cl_slot); // client number WriteShort(to, 39); // client ping } void update_ghosts(void) { gedict_t *p; int from; for (from = 1, p = world; (p = find_plrghst(p, &from));) { ghost2scores(p); } } // } ghost stuff // { events void on_connect(void) { char *newteam; if (!(iKey(self, "ev") & EV_ON_CONNECT)) // client doesn't want on_connect { return; } if (self->ct == ctPlayer) { if (isFFA()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_connect_ffa\n"); } else if (isCTF()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_connect_ctf\n"); } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_connect\n"); } if (isCTF() && (streq(newteam = getteam(self), "red") || streq(newteam, "blue"))) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "auto%s\n", newteam); } } else { if (isFFA()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_observe_ffa\n"); } else if (isCTF()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_observe_ctf\n"); } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_observe\n"); } } } void on_enter(void) { if (iKey(self, "kf") & KF_ON_ENTER) // client doesn't want on_enter { return; } if (self->ct == ctPlayer) { if (isFFA()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_enter_ffa\n"); } else if (isCTF()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_enter_ctf\n"); } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_enter\n"); } } else { if (isFFA()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_spec_enter_ffa\n"); } else if (isCTF()) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_spec_enter_ctf\n"); } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "on_spec_enter\n"); } } } void on_match_start(gedict_t *p) { if (!(iKey(p, "ev") & EV_ON_MATCH_START)) { return; } if (p->ct == ctPlayer) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_matchstart\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_spec_matchstart\n"); } } void on_match_end(gedict_t *p) { if (!(iKey(p, "ev") & EV_ON_MATCH_END)) { return; } if (p->ct == ctPlayer) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_matchend\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_spec_matchend\n"); } } void on_match_break(gedict_t *p) { if (!(iKey(p, "ev") & EV_ON_MATCH_BREAK)) { return; } if (p->ct == ctPlayer) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_matchbreak\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_spec_matchbreak\n"); } } void on_admin(gedict_t *p) { if (!(iKey(p, "ev") & EV_ON_ADMIN)) { return; } stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_admin\n"); } void on_unadmin(gedict_t *p) { if (!(iKey(p, "ev") & EV_ON_UNADMIN)) { return; } stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "on_unadmin\n"); } void ev_print(gedict_t *p, int new_ev, int old_ev, int bit, char *msg) { int on; if ((on = (new_ev & bit)) != (old_ev & bit)) { G_sprint(p, 2, "%s%s\n", msg, OnOff(on)); } } void info_ev_update(gedict_t *p, char *from, char *to) { int new_ev = atoi(to); int old_ev = atoi(from); ev_print(p, new_ev, old_ev, EV_ON_CONNECT, "[on_connect] event: "); ev_print(p, new_ev, old_ev, EV_ON_MATCH_START, "[on_matchstart] event: "); ev_print(p, new_ev, old_ev, EV_ON_MATCH_END, "[on_matchend] event: "); ev_print(p, new_ev, old_ev, EV_ON_MATCH_BREAK, "[on_matchbreak] event: "); ev_print(p, new_ev, old_ev, EV_ON_ADMIN, "[on_admin] event: "); ev_print(p, new_ev, old_ev, EV_ON_UNADMIN, "[on_unadmin] event: "); } void info_kf_update(gedict_t *p, char *from, char *to) { int new_ev = atoi(to); int old_ev = atoi(from); ev_print(p, new_ev, old_ev, KF_KTSOUNDS, "KTSounds: "); ev_print(p, new_ev, old_ev, KF_SCREEN, "auto screenshot: "); ev_print(p, ~new_ev, ~old_ev, KF_ON_ENTER, "calling on_enter user alias: "); // heh ~ is ok ev_print(p, new_ev, old_ev, KF_SPEED, "showing speed in prewar: "); } // } void cl_refresh_plus_scores(gedict_t *p) { gedict_t *swp; if (((p->ct == ctPlayer) || (p->ct == ctSpec)) && p->sc_stats) { swp = self; // save self self = p; Sc_Stats(2); // force refresh self = swp; // restore self } } void refresh_plus_scores(void) { gedict_t *p; for (p = world; (p = find_client(p));) { cl_refresh_plus_scores(p); } } int only_digits(const char *s) { if (!s || *s == '\0') { return (0); } while (*s != '\0') { if (!isdigit(*s)) { return (0); } s++; } return (1); } // params_str( 0, -1 ) return all params char* params_str(int from, int to) { static char string[MAX_STRINGS][1024]; static int index = 0; char arg_x[1024]; int i, argc = trap_CmdArgc(); from = max(0, from); to = (to < 0 ? argc - 1 : min(argc - 1, to)); if (!argc || (from >= argc) || (from > to)) { return ""; } index %= MAX_STRINGS; for (string[index][0] = 0, i = from; i <= to; i++) { trap_CmdArgv(i, arg_x, sizeof(arg_x)); if (i != from) { strlcat(string[index], " ", sizeof(string[0])); } strlcat(string[index], arg_x, sizeof(string[0])); } return string[index++]; } char* SD_type_str(void) { switch ((int)k_sudden_death) { case 0: return "none"; case SD_NORMAL: return "Sudden death"; case SD_TIEBREAK: return "tie-break"; default: return "unknown"; } } char* respawn_model_name(int mdl_num) { switch (mdl_num) { // K_SPW_0_NONRANDOM changes "Normal QW respawns" to "pre-qtest nonrandom respawns" #ifdef K_SPW_0_NONRANDOM case 0: return "pre-qtest nonrandom respawns"; #else case 0: return "Normal QW respawns"; #endif case 1: return "KT SpawnSafety"; case 2: return "Kombat Teams respawns"; case 3: return "KTX respawns"; case 4: return "KTX2 respawns"; default: return "!Unknown!"; } } char* respawn_model_name_short(int mdl_num) { switch (mdl_num) { case 0: return "QW"; case 1: return "KTS"; case 2: return "KT"; case 3: return "KTX"; case 4: return "KT2"; default: return "???"; } } int get_fair_pack(void) { // Yawnmode: always 2 aka last weapon return bound(0, k_yawnmode ? 2 : cvar("k_frp"), 2); } int get_fallbunny(void) { // Yawnmode/race: no broken ankle return (k_yawnmode || isRACE() ? 1 : cvar("k_fallbunny")); } //====================================== void remove_projectiles(void) { gedict_t *p; for (p = world; (p = nextent(p));) { if (p->isMissile) { ent_remove(p); } } } //======================================= // WARNING: this trap uses Cmd_TokenizeString() in server, so use with care. void SetUserInfo(gedict_t *p, const char *varname, const char *value, int flags) { trap_SetUserInfo(NUM_FOR_EDICT(p), varname, value, flags); } //======================================= void safe_precache_model(char *name) { if (framecount > 1) { return; } trap_precache_model(name); } void safe_precache_sound(char *name) { if (framecount > 1) { return; } trap_precache_sound(name); } //======================================= char* cl_ip(gedict_t *p) { return ezinfokey(p, "ip"); } //======================================= // Replace special characters with underscore. char* clean_string(char *string) { char *s = string; for (; s && *s; s++) { int c = *s; if (((c >= 'a') && (c <= 'z')) // allow alpha || ((c >= 'A') && (c <= 'Z')) // allow alpha || ((c >= '0') && (c <= '9')) // allow numbers || (c == ' ') // allow space || (c == '-') // allow minus || (c == '+')) // allow plus { continue; } *s = '_'; } return string; } void visible_to(gedict_t *viewer, gedict_t *first, int len, byte *visible) { trap_VisibleTo(NUM_FOR_EDICT(viewer), NUM_FOR_EDICT(first), len, visible); } // Work around for the fact that QVM dos not support ".*s" in printf() family functions. // It retuns dots array filled with dots, amount of dots depends of how long cmd name and longest cmd name. char* make_dots(char *dots, size_t dots_len, int cmd_max_len, char *cmd) { int len = cmd_max_len - strlen(cmd); len = bound(0, len, dots_len - 1); memset((void*) dots, (int)'.', len); dots[len] = 0; return dots; } QW-Group-ktx-d05d6ca/src/globals.c000066400000000000000000000103151475442401000170060ustar00rootroot00000000000000/* * 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 * * * $Id$ */ #include "g_local.h" // WARNING: globals are cleared every map change int k_bloodfest; // blood fest mode float k_killquad; // killquad mode float framechecks; // if timedemo/uptime bugs are tolerated float k_attendees; // stores number of players on server - used in 'ready' checking float k_captains; // number of captains float k_captainturn; // which captain comes in line to pick float k_coaches; // number of coaches float k_checkx = 0; // global which set to true when some time spend after match start float k_force; // used in forcing matchstart float k_maxspeed; // used to store server maxspeed to allow switching by admins float k_oldmaxspeed; // used to store old value of maxspeed prior to freezing the map float k_showscores; // whether or not should print the scores or not // now k_showscores != 0 only in team mode exactly with two teams float k_nochange = 0; // used to indicate if frags changes somehow since last time 'scores' command was called float k_standby; // if server is in standy mode float k_sudden_death; // to mark if sudden death overtime is currently the case float k_teamid = 0; float k_userid = 0; // somethink like numbers of ghosts + 1 float k_whonottime; // NOT_SURE: float match_in_progress = 0; // if a match has begun float match_start_time; // time when match has been started float match_end_time; // time when match is expected to end float match_over; // boolean - whether or not the match stats have been printed at end of game int k_berzerk; // berzerk mode float k_berzerktime; // berzerk mode time left gedict_t *newcomer = g_edicts; // stores last player who joined int k_overtime = 0; // is overtime is going on float current_maxfps; // current value of maxfps // { yawn mode int k_yawnmode; // is server in yawn mode int k_teleport_cap = 24; // cap for keeping velocity through tele // } int k_practice; // is server in practice mode int k_matchLess; // is server in matchLess mode int k_matchLess_idle_time; int k_matchLess_idle_warn; gameType_t k_mode; // game type: DUEL, TP, FFA int k_lastvotedmap; // last voted map, used for agree command? // { CTF int k_ctf_custom_models; // if server has flag/grapple models you can enable them here // http://www.quakeworld.us/ult/ctf/pak0.pak (only 300kb) // if not we use old style keys and ax/voreball for grapple #ifdef CTF_RELOADMAP qbool k_ctf; // is ctf was active at map load #endif // } int k_allowed_free_modes; // reflect appropriate cvar - but changed only at map load // { cmd flood ptotect int k_cmd_fp_count; // 10 commands allowed .. float k_cmd_fp_per; // per 4 seconds float k_cmd_fp_for; // skip commands for 5 seconds int k_cmd_fp_kick; // kick after 4 warings int k_cmd_fp_dontkick; // if 1 - don't use kick int k_cmd_fp_disabled; // if 1 - don't use cmd floodprot // } qbool vw_available; // vwep extension available qbool vw_enabled; // vweps enabled float k_sv_locktime; // some time before non VIP players can't connect, spectators not affected // { rocket arena float time_to_start; // time to start match int ra_match_fight; // have winner and loser fighting // } // { clan arena int ca_round_pause; // } int jumpf_flag; // falling velocity criteria float f_check; // is we in state of some f_xxx check float lastTeamLocationTime; // next udate for CheckTeamStatus() qbool first_rl_taken; // true when some one alredy took rl int sv_minping; // used to broadcast changes QW-Group-ktx-d05d6ca/src/grapple.c000066400000000000000000000306071475442401000170230ustar00rootroot00000000000000/* * Original 'Morning Star' (Grapple Hook) by "Mike" * Quakeworld-friendly grapple by Wedge (Steve Bond) * PureCTF changes by Methabol * * * $Id$ */ #include "g_local.h" #define PULL_SPEED 800 #define THROW_SPEED 800 #define NEW_THROW_SPEED 1050 #define CR_THROW_SPEED 1200 #define HOOK_FIRE_RATE 0.192 void SpawnBlood(vec3_t dest, float damage); float IncreasePullSpeed(float currentSpeed, float incrAmount) { float newSpeed = PULL_SPEED; if (currentSpeed < (PULL_SPEED - incrAmount)) { newSpeed = currentSpeed + incrAmount; } return newSpeed; } float DecreasePullSpeed(float currentSpeed, float decrAmount) { float newSpeed = PULL_SPEED; if (currentSpeed > (PULL_SPEED - decrAmount)) { newSpeed = currentSpeed + decrAmount; } return newSpeed; } // // GrappleReset - Removes the hook and resets its owner's state. // expects a pointer to the hook // void GrappleReset(gedict_t *rhook) { gedict_t *owner = PROG_TO_EDICT(rhook->s.v.owner); if (owner == world) { return; } sound(owner, CHAN_NO_PHS_ADD + CHAN_WEAPON, "weapons/bounce2.wav", 1, ATTN_NORM); owner->on_hook = false; owner->hook_out = false; owner->s.v.weaponframe = 0; if (cvar("k_ctf_hookstyle") == 1) { owner->attack_finished = (self->ctf_flag & CTF_RUNE_HST) ? g_globalvars.time + ((HOOK_FIRE_RATE / 2) / cvar("k_ctf_rune_power_hst")) : g_globalvars.time + (HOOK_FIRE_RATE / 2); owner->hook_reset_time = (self->ctf_flag & CTF_RUNE_HST) ? g_globalvars.time + (HOOK_FIRE_RATE / cvar("k_ctf_rune_power_hst")) : g_globalvars.time + HOOK_FIRE_RATE; } else { owner->attack_finished = g_globalvars.time; owner->hook_reset_time = g_globalvars.time; } rhook->think = (func_t) SUB_Remove; rhook->s.v.nextthink = next_frame(); } // // GrappleTrack - Constantly updates the hook's position relative to // what it's hooked to. Inflicts damage if attached to // a player that is not on the same team as the hook's // owner. // void GrappleTrack(void) { gedict_t *enemy = PROG_TO_EDICT(self->s.v.enemy); gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); // Release dead targets if ((enemy->ct == ctPlayer) && ISDEAD(enemy)) { owner->on_hook = false; } // drop the hook if owner is dead or has released the button if (!owner->on_hook || (owner->s.v.health <= 0)) { GrappleReset(self); return; } if (enemy->ct == ctPlayer) { if (!CanDamage(enemy, owner)) { GrappleReset(self); return; } // move the hook along with the player. It's invisible, but // we need this to make the sound come from the right spot setorigin(self, PASSVEC3(enemy->s.v.origin)); // only deal damage every 100ms if (g_globalvars.time >= (owner->hook_damage_time + 0.1)) { owner->hook_damage_time = g_globalvars.time; sound(self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM); enemy->deathtype = dtHOOK; T_Damage(enemy, self, owner, 1); trap_makevectors(self->s.v.v_angle); SpawnBlood(enemy->s.v.origin, 1); } } // If the hook is not attached to the player, constantly copy // the target's velocity. Velocity copying DOES NOT work properly // for a hooked client. if (enemy->ct != ctPlayer) { VectorCopy(enemy->s.v.velocity, self->s.v.velocity); } self->s.v.nextthink = next_frame(); } // // MakeLink - spawns the chain link entities // gedict_t* MakeLink(void) { newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->s.v.movetype = MOVETYPE_FLYMISSILE; newmis->s.v.solid = SOLID_NOT; newmis->s.v.owner = EDICT_TO_PROG(self); if (k_ctf_custom_models) { setmodel(newmis, "progs/bit.mdl"); } else { setmodel(newmis, "progs/spike.mdl"); } setorigin(newmis, PASSVEC3(self->s.v.origin)); setsize(newmis, 0, 0, 0, 0, 0, 0); return newmis; } // // RemoveChain - Removes all chain link entities; this is a separate // function because CLIENT also needs to be able // to remove the chain. Only one function required to // remove all links. // void RemoveChain(void) { self->think = (func_t) SUB_Remove; self->s.v.nextthink = next_frame(); if (self->s.v.goalentity) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); goal->think = (func_t) SUB_Remove; goal->s.v.nextthink = next_frame(); if (goal->s.v.goalentity) { gedict_t *goal2 = PROG_TO_EDICT(goal->s.v.goalentity); goal2->think = (func_t) SUB_Remove; goal2->s.v.nextthink = next_frame(); } } } // // Update_Chain - Repositions the chain links each frame. This single function // maintains the positions of all of the links. Only one link // is thinking every frame. // void UpdateChain(void) { vec3_t t1, t2, t3; vec3_t temp; gedict_t *owner = PROG_TO_EDICT(self->s.v.owner), *goal, *goal2; if (!owner->hook_out) { self->think = (func_t) RemoveChain; self->s.v.nextthink = next_frame(); return; } if (cvar("k_ctf_hookstyle") != 3) { owner->hook_cancel_time += 1; // delay cancelling the hook until ~250ms (13 * 19) if `smooth hook` is enabled (prevent spam attacks) if (cvar("k_ctf_hookstyle") == 1 && owner->hook_cancel_time > 19) { CancelHook(owner); } if(cvar("k_ctf_hookstyle") == 2 && owner->hook_cancel_time > 6) { CancelHook(owner); } if (cvar("k_ctf_hookstyle") == 4) { CancelHook(owner); } } VectorSubtract(owner->hook->s.v.origin, owner->s.v.origin, temp); goal = PROG_TO_EDICT(self->s.v.goalentity); goal2 = PROG_TO_EDICT(goal->s.v.goalentity); if(vlen(temp) <= 100 && owner->on_hook) { // If there is a chain, ditch it now. We're close enough. // Having extra entities lying around is never a good idea. self->think = (func_t) RemoveChain; self->s.v.nextthink = next_frame(); return; } VectorScale(temp, 0.25, t1); VectorAdd(t1, owner->s.v.origin, t1); VectorScale(temp, 0.50, t2); VectorAdd(t2, owner->s.v.origin, t2); VectorScale(temp, 0.75, t3); VectorAdd(t3, owner->s.v.origin, t3); // These numbers are correct assuming 3 links. // 4 links would be *20 *40 *60 and *80 setorigin(self, PASSVEC3(t1)); setorigin(goal, PASSVEC3(t2)); setorigin(goal2, PASSVEC3(t3)); self->s.v.nextthink = next_frame(); } // // CancelHook - Allow the hook ro be reset mid-throw (smooth hook / hookstyle 1) // void CancelHook(gedict_t *owner) { if (!owner->s.v.button0 && (owner->s.v.weapon == IT_HOOK)) { GrappleReset(owner->hook); } } // // BuildChain - Builds the chain (linked list) // void BuildChain(void) { self->s.v.goalentity = EDICT_TO_PROG(MakeLink()); PROG_TO_EDICT(self->s.v.goalentity)->think = (func_t)UpdateChain; PROG_TO_EDICT(self->s.v.goalentity)->s.v.nextthink = next_frame(); PROG_TO_EDICT(self->s.v.goalentity)->s.v.owner = self->s.v.owner; PROG_TO_EDICT(self->s.v.goalentity)->s.v.goalentity = EDICT_TO_PROG(MakeLink()); PROG_TO_EDICT(PROG_TO_EDICT(self->s.v.goalentity)->s.v.goalentity)->s.v.goalentity = EDICT_TO_PROG(MakeLink()); } void GrappleAnchor(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); if (other == owner) { return; } // DO NOT allow the grapple to hook to any projectiles, no matter WHAT! // if you create new types of projectiles, make sure you use one of the // classnames below or write code to exclude your new classname so // grapples will not stick to them. if (streq(other->classname, "rocket") || streq(other->classname, "grenade") || streq(other->classname, "spike") || streq(other->classname, "hook")) { return; } if (other->ct == ctPlayer) { // grappling players in prewar is annoying if ((match_in_progress != 2) || ((tp_num() == 4) && streq(getteam(other), getteam(owner)))) { GrappleReset(self); return; } owner->hook_damage_time = g_globalvars.time; sound(self, CHAN_WEAPON, "player/axhit1.wav", 1, ATTN_NORM); other->deathtype = dtHOOK; T_Damage(other, self, owner, 10); // make hook invisible since we will be pulling directly // towards the player the hook hit. Quakeworld makes it // too quirky to try to match hook's velocity with that of // the client that it hit. setmodel(self, ""); } else { sound(self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); // One point of damage inflicted upon impact. Subsequent // damage will only be done to PLAYERS... this way secret // doors and triggers will only be damaged once. if (other->s.v.takedamage) { other->deathtype = dtHOOK; T_Damage(other, self, owner, 1); } SetVector(self->s.v.velocity, 0, 0, 0); SetVector(self->s.v.avelocity, 0, 0, 0); } if (!owner->s.v.button0) { GrappleReset(self); return; } if ((int)owner->s.v.flags & FL_ONGROUND) { owner->s.v.flags -= FL_ONGROUND; } owner->hook_pullspeed = max(vlen(owner->s.v.velocity), owner->maxspeed); owner->hook_pullspeed_accel = (PULL_SPEED - owner->hook_pullspeed) / 6; // accel/decel velocity over ~77ms (6 * 0.013) owner->on_hook = true; self->s.v.enemy = EDICT_TO_PROG(other); self->think = (func_t) GrappleTrack; self->s.v.nextthink = next_frame(); self->s.v.solid = SOLID_NOT; self->touch = (func_t) SUB_Null; } // Called from client.c void GrappleService(void) { vec3_t hookVector, hookVelocity; gedict_t *enemy; float hasteMultiplier = (cvar("k_ctf_rune_power_hst") / 16) + 1; // drop the hook if player lets go of fire if (!self->s.v.button0) { if (self->s.v.weapon == IT_HOOK) { GrappleReset(self->hook); return; } } enemy = PROG_TO_EDICT(self->hook->s.v.enemy); // If hooked to a player, track them directly! if (enemy->ct == ctPlayer) { VectorSubtract(enemy->s.v.origin, self->s.v.origin, hookVector); } else { VectorSubtract(self->hook->s.v.origin, self->s.v.origin, hookVector); } // No longer going to factor maxspeed into grapple velocity // purectf velocity = 2.35 * 320 or 360 * 1 = 750 or 846 VectorCopy(hookVector, hookVelocity); VectorNormalize(hookVelocity); if (cvar("k_ctf_hookstyle") == 1) { if (self->hook_pullspeed_accel > 0) // accelerate { self->hook_pullspeed = IncreasePullSpeed(self->hook_pullspeed, self->hook_pullspeed_accel); } else if (self->hook_pullspeed_accel < 0) // decelerate { self->hook_pullspeed = DecreasePullSpeed(self->hook_pullspeed, self->hook_pullspeed_accel); } } else { self->hook_pullspeed = PULL_SPEED; } if (self->ctf_flag & CTF_RUNE_HST) { VectorScale(hookVelocity, self->hook_pullspeed * hasteMultiplier, self->s.v.velocity); } else { VectorScale(hookVelocity, self->hook_pullspeed, self->s.v.velocity); } } // Called from weapons.c void GrappleThrow(void) { float hasteMultiplier, throwSpeed; if (self->hook_out || self->hook_reset_time > g_globalvars.time) // only throw once & wait for cooldown time to complete { return; } hasteMultiplier = (cvar("k_ctf_rune_power_hst") / 16) + 1; throwSpeed = NEW_THROW_SPEED; if (cvar("k_ctf_hookstyle") == 3) { throwSpeed = THROW_SPEED; } else if (cvar("k_ctf_hookstyle") == 4) { throwSpeed = CR_THROW_SPEED; } g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); sound(self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM); newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->s.v.movetype = MOVETYPE_FLYMISSILE; newmis->s.v.solid = SOLID_BBOX; newmis->s.v.owner = EDICT_TO_PROG(self); self->hook = newmis; newmis->classname = "hook"; if (cvar("k_ctf_hookstyle") != 3) { self->hook_cancel_time = 0; } trap_makevectors(self->s.v.v_angle); // Weapon velocitys should not be based on server maxspeed imo // Removing purectf velocity changes ( 2.5 * self->maxspeed ) if (self->ctf_flag & CTF_RUNE_HST) { HasteSound(self); VectorScale(g_globalvars.v_forward, throwSpeed * hasteMultiplier, newmis->s.v.velocity); // rotate/spin star model as hook flies SetVector(newmis->s.v.avelocity, 300 * hasteMultiplier, 300 * hasteMultiplier, 300 * hasteMultiplier); } else { VectorScale(g_globalvars.v_forward, throwSpeed, newmis->s.v.velocity); // rotate/spin star model as hook flies SetVector(newmis->s.v.avelocity, -250, -250, -250); } newmis->touch = (func_t) GrappleAnchor; newmis->think = (func_t) BuildChain; newmis->s.v.nextthink = next_frame(); if (k_ctf_custom_models) { setmodel(newmis, "progs/star.mdl"); } else { setmodel(newmis, "progs/v_spike.mdl"); } setorigin(newmis, self->s.v.origin[0] + g_globalvars.v_forward[0] * 16, self->s.v.origin[1] + g_globalvars.v_forward[1] * 16, self->s.v.origin[2] + g_globalvars.v_forward[2] * 16 + 16); setsize(newmis, 0, 0, 0, 0, 0, 0); self->hook_out = true; } QW-Group-ktx-d05d6ca/src/hiprot.c000066400000000000000000000665271475442401000167100ustar00rootroot00000000000000// This code is a line by line port of the re-release hiprot QuakeC code. // https://github.com/id-Software/quake-rerelease-qc/blob/main/quakec_hipnotic/hiprot.qc #include "g_local.h" #define STATE_ACTIVE 0 #define STATE_INACTIVE 1 #define STATE_SPEEDINGUP 2 #define STATE_SLOWINGDOWN 3 #define STATE_CLOSED 4 #define STATE_OPEN 5 #define STATE_OPENING 6 #define STATE_CLOSING 7 #define STATE_WAIT 0 #define STATE_MOVE 1 #define STATE_STOP 2 #define STATE_FIND 3 #define STATE_NEXT 4 #define OBJECT_ROTATE 0 #define OBJECT_MOVEWALL 1 #define OBJECT_SETORIGIN 2 #define TOGGLE 1 #define START_ON 2 #define ROTATION 1 #define ANGLES 2 #define STOP 4 #define NO_ROTATE 8 #define DAMAGE 16 #define MOVETIME 32 #define SET_DAMAGE 64 #define VISIBLE 1 #define TOUCH 2 #define NONBLOCKING 4 #define STAYOPEN 1 /*QUAKED info_rotate (0 0.5 0) (-4 -4 -4) (4 4 4) Used as the point of rotation for rotatable objects. */ void SP_info_rotate(void) { // remove self after a little while, to make sure that entities that // have targeted it have had a chance to spawn self->s.v.nextthink = g_globalvars.time + 2; self->think = (func_t) SUB_Remove; } static void RotateTargets(void) { gedict_t *ent; vec3_t vx, vy, vz, org; trap_makevectors(self->s.v.angles); ent = find(world, FOFS(targetname), self->target); while (ent) { VectorCopy(ent->s.v.oldorigin, org); VectorScale(g_globalvars.v_forward, org[0], vx); VectorScale(g_globalvars.v_right, org[1], vy); VectorScale(vy, -1, vy); VectorScale(g_globalvars.v_up, org[2], vz); VectorAdd(vx, vy, ent->neworigin); VectorAdd(ent->neworigin, vz, ent->neworigin); if (ent->rotate_type == OBJECT_SETORIGIN) { VectorAdd(ent->neworigin, self->s.v.origin, org); setorigin(ent, PASSVEC3(org)); } else if ( ent->rotate_type == OBJECT_ROTATE) { VectorCopy(self->s.v.angles, ent->s.v.angles); VectorAdd(ent->neworigin, self->s.v.origin, org); setorigin(ent, PASSVEC3(org)); } else { VectorSubtract(self->s.v.origin, self->s.v.oldorigin, org); VectorAdd(org, ent->neworigin, org); VectorSubtract(org, ent->s.v.oldorigin, ent->neworigin); VectorSubtract(ent->neworigin, ent->s.v.origin, org); VectorScale(org, 25, ent->s.v.velocity); } ent = find(ent, FOFS(targetname), self->target); } } static void RotateTargetsFinal(void) { gedict_t *ent; ent = find(world, FOFS(targetname), self->target); while (ent) { SetVector(ent->s.v.velocity, 0, 0, 0); if (ent->rotate_type == OBJECT_ROTATE) { VectorCopy(self->s.v.angles, ent->s.v.angles); } ent = find(ent, FOFS(targetname), self->target); } } static void SetTargetOrigin(void) { gedict_t *ent; vec3_t org; ent = find(world, FOFS(targetname), self->target); while (ent) { if (ent->rotate_type == OBJECT_MOVEWALL) { VectorSubtract(self->s.v.origin, self->s.v.oldorigin, org); VectorAdd(org, ent->neworigin, org); VectorSubtract(org, ent->s.v.oldorigin, org); setorigin(ent, PASSVEC3(org)); } else { VectorAdd(ent->neworigin, self->s.v.origin, org); setorigin(ent, PASSVEC3(org)); } ent = find(ent, FOFS(targetname), self->target); } } static void LinkRotateTargets(void) { gedict_t *ent; vec3_t tempvec; VectorCopy(self->s.v.origin, self->s.v.oldorigin); ent = find(world, FOFS(targetname), self->target); while (ent) { if (streq(ent->classname, "rotate_object")) { ent->rotate_type = OBJECT_ROTATE; VectorSubtract(ent->s.v.origin, self->s.v.oldorigin, ent->s.v.oldorigin); VectorSubtract(ent->s.v.origin, self->s.v.oldorigin, ent->neworigin); ent->s.v.owner = EDICT_TO_PROG(self); } else if (streq(ent->classname, "func_movewall")) { ent->rotate_type = OBJECT_MOVEWALL; VectorAdd(ent->s.v.absmin, ent->s.v.absmax, tempvec); VectorScale(tempvec, 0.5f, tempvec); VectorSubtract(tempvec, self->s.v.oldorigin, ent->s.v.oldorigin); VectorCopy(ent->s.v.oldorigin, ent->neworigin); ent->s.v.owner = EDICT_TO_PROG(self); } else { ent->rotate_type = OBJECT_SETORIGIN; VectorSubtract(ent->s.v.origin, self->s.v.oldorigin, ent->s.v.oldorigin); VectorSubtract(ent->s.v.origin, self->s.v.oldorigin, ent->neworigin); } ent = find(ent, FOFS(targetname), self->target); } } static void HurtSetDamage(gedict_t *ent, float amount) { ent->dmg = amount; if (!amount) { ent->s.v.solid = SOLID_NOT; } else { ent->s.v.solid = SOLID_TRIGGER; } ent->s.v.nextthink = -1; } static void SetDamageOnTargets(float amount) { gedict_t *ent; ent = find(world, FOFS(targetname), self->target); while (ent) { if (streq(ent->classname, "trigger_hurt")) { HurtSetDamage(ent, amount); } else if (streq(ent->classname, "func_movewall")) { ent->dmg = amount; } ent = find(ent, FOFS(targetname), self->target); } } //************************************************ // // Simple continual rotatation // //************************************************ static void SUB_NormalizeAngles(vec3_t v) { v[0] = (float) fmod(v[0], 360.0); v[1] = (float) fmod(v[1], 360.0); v[2] = (float) fmod(v[2], 360.0); } static void rotate_entity_think(void) { vec3_t delta; float t; t = g_globalvars.time - self->s.v.ltime; self->s.v.ltime = g_globalvars.time; if (self->state == STATE_SPEEDINGUP) { self->count = self->count + self->cnt * t; if (self->count > 1) { self->count = 1; } // get rate of rotation t = t * self->count; } else if (self->state == STATE_SLOWINGDOWN) { self->count = self->count - self->cnt * t; if (self->count < 0) { RotateTargetsFinal(); self->state = STATE_INACTIVE; self->think = (func_t) SUB_Null; return; } // get rate of rotation t = t * self->count; } VectorScale(self->rotate, t, delta); VectorAdd(self->s.v.angles, delta, self->s.v.angles); SUB_NormalizeAngles(self->s.v.angles); RotateTargets(); self->s.v.nextthink = g_globalvars.time + 0.02f; } static void rotate_entity_use(void) { // change to alternate textures self->s.v.frame = 1 - self->s.v.frame; if (self->state == STATE_ACTIVE) { if ((int) self->s.v.spawnflags & TOGGLE) { if (self->speed) { self->count = 1; self->state = STATE_SLOWINGDOWN; } else { self->state = STATE_INACTIVE; self->think = (func_t) SUB_Null; } } } else if (self->state == STATE_INACTIVE) { self->think = (func_t) rotate_entity_think; self->s.v.nextthink = g_globalvars.time + 0.02f; self->s.v.ltime = g_globalvars.time; if (self->speed) { self->count = 0; self->state = STATE_SPEEDINGUP; } else { self->state = STATE_ACTIVE; } } else if (self->state == STATE_SPEEDINGUP) { if ((int) self->s.v.spawnflags & TOGGLE) { self->state = STATE_SLOWINGDOWN; } } else { self->state = STATE_SPEEDINGUP; } } static void rotate_entity_firstthink(void) { LinkRotateTargets(); if ((int) self->s.v.spawnflags & START_ON ) { self->state = STATE_ACTIVE; self->think = (func_t) rotate_entity_think; self->s.v.nextthink = g_globalvars.time + 0.02f; self->s.v.ltime = g_globalvars.time; } else { self->state = STATE_INACTIVE; self->think = (func_t) SUB_Null; } self->use = (func_t) rotate_entity_use; } /*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON Creates an entity that continually rotates. Can be toggled on and off if targeted. TOGGLE = allows the rotation to be toggled on/off START_ON = wether the entity is spinning when spawned. If TOGGLE is 0, entity can be turned on, but not off. If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train. "rotate" is the rate to rotate. "target" is the center of rotation. "speed" is how long the entity takes to go from standing still to full speed and vice-versa. */ void SP_func_rotate_entity(void) { self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_NONE; setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); if (self->speed != 0 ) { self->cnt = 1 / self->speed; } self->think = (func_t) rotate_entity_firstthink; self->s.v.nextthink = g_globalvars.time + 0.1f; self->s.v.ltime = g_globalvars.time; } //************************************************ // // Train with rotation functionality // //************************************************ /*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE Path for rotate_train. ROTATION tells train to rotate at rate specified by "rotate". Use '0 0 0' to stop rotation. ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate. Use values < 0 or > 360 to guarantee that it turns in a certain direction. Having this flag set automatically clears any rotation. STOP tells the train to stop and wait to be retriggered. NO_ROTATE tells the train to stop rotating when waiting to be triggered. DAMAGE tells the train to cause damage based on "dmg". MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another. SET_DAMAGE tells the train to set all targets damage to "dmg" "noise" contains the name of the sound to play when train stops. "noise1" contains the name of the sound to play when train moves. "event" is a target to trigger when train arrives at path_rotate. */ void SP_path_rotate(void) { if (self->noise) { trap_precache_sound(self->noise); } if (self->noise1) { trap_precache_sound(self->noise1); } } static void rotate_train_next(void); static void rotate_train_find(void); static void rotate_train_think(void) { float t, timeelapsed; vec3_t delta; t = g_globalvars.time - self->s.v.ltime; self->s.v.ltime = g_globalvars.time; if (self->endtime && (g_globalvars.time >= self->endtime)) { self->endtime = 0; if (self->state == STATE_MOVE) { setorigin(self, PASSVEC3(self->finaldest)); SetVector(self->s.v.velocity, 0, 0, 0); } if (self->think1) { self->think1(); } } else { timeelapsed = (g_globalvars.time - self->cnt) * self->duration; if (timeelapsed > 1) { timeelapsed = 1; } VectorScale(self->dest2, timeelapsed, delta); VectorAdd(self->dest1, delta, delta); setorigin(self, PASSVEC3(delta)); } VectorScale(self->rotate, t, delta); VectorAdd(self->s.v.angles, delta, self->s.v.angles); SUB_NormalizeAngles(self->s.v.angles); RotateTargets(); self->s.v.nextthink = g_globalvars.time + 0.02f; } static void rotate_train_use(void) { if (self->think1 != rotate_train_find) { if (VectorLength(self->s.v.velocity)) { return; // already activated } if (self->think1) { self->think1(); } } } static void rotate_train_wait(void) { gedict_t *goalentity = PROG_TO_EDICT(self->s.v.goalentity); self->state = STATE_WAIT; if (!strnull(goalentity->noise)) { sound(self, CHAN_VOICE, goalentity->noise, 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); } if ((int) goalentity->s.v.spawnflags & ANGLES) { SetVector(self->rotate, 0, 0, 0); VectorCopy(self->finalangle, self->s.v.angles); } if ((int) goalentity->s.v.spawnflags & NO_ROTATE) { SetVector(self->rotate, 0, 0, 0); } self->endtime = self->s.v.ltime + goalentity->wait; self->think1 = rotate_train_next; } static void rotate_train_stop(void) { gedict_t *goalentity = PROG_TO_EDICT(self->s.v.goalentity); self->state = STATE_STOP; if (!strnull(goalentity->noise)) { sound(self, CHAN_VOICE, goalentity->noise, 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); } if ((int) goalentity->s.v.spawnflags & ANGLES) { SetVector(self->rotate, 0, 0, 0); VectorCopy(self->finalangle, self->s.v.angles); } if ((int) goalentity->s.v.spawnflags & NO_ROTATE) { SetVector(self->rotate, 0, 0, 0); } self->dmg = 0; self->think1 = rotate_train_next; } static void rotate_train_next(void) { gedict_t *targ, *current, *goalentity; vec3_t vdestdelta; float len, traintraveltime, div; char *temp; self->state = STATE_NEXT; goalentity = PROG_TO_EDICT(self->s.v.goalentity); current = goalentity; targ = find (world, FOFS(targetname), self->path); if (!streq(targ->classname, "path_rotate")) { G_Error( "Next target is not path_rotate"); } if (goalentity->noise1) { self->noise1 = goalentity->noise1; } sound(self, CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->s.v.goalentity = EDICT_TO_PROG(targ); self->path = targ->target; if (strnull(self->path)) G_Error("rotate_train_next: no next target"); if ((int) targ->s.v.spawnflags & STOP) { self->think1 = rotate_train_stop; } else if (targ->wait) { self->think1 = rotate_train_wait; } else { self->think1 = rotate_train_next; } if (current->event) { // Trigger any events that should happen at the corner. temp = self->target; self->target = current->event; self->message = current->message; SUB_UseTargets(); self->target = temp; self->message = NULL; } if ((int) current->s.v.spawnflags & ANGLES) { SetVector(self->rotate, 0, 0, 0); VectorCopy(self->finalangle, self->s.v.angles); } if ((int) current->s.v.spawnflags & ROTATION) { VectorCopy(current->rotate, self->rotate); } if ((int) current->s.v.spawnflags & DAMAGE) { self->dmg = current->dmg; } if ((int) current->s.v.spawnflags & SET_DAMAGE) { SetDamageOnTargets( current->dmg); } if (current->speed == -1 ) { // Warp to the next path_corner setorigin( self, PASSVEC3(targ->s.v.origin)); self->endtime = self->s.v.ltime + 0.01f; SetTargetOrigin(); if ((int) targ->s.v.spawnflags & ANGLES) { VectorCopy(targ->s.v.angles, self->s.v.angles); } self->duration = 1; // 1 / duration self->cnt = g_globalvars.time; // start time SetVector(self->dest2, 0, 0, 0); // delta VectorCopy(self->s.v.origin, self->dest1); // original position VectorCopy(self->s.v.origin, self->finaldest); } else { self->state = STATE_MOVE; VectorCopy(targ->s.v.origin, self->finaldest); if (VectorCompare(self->finaldest, self->s.v.origin)) { SetVector(self->s.v.velocity, 0, 0, 0); self->endtime = self->s.v.ltime + 0.1f; self->duration = 1; // 1 / duration self->cnt = g_globalvars.time; // start time SetVector(self->dest2, 0, 0, 0); // delta VectorCopy(self->s.v.origin, self->dest1); // original position VectorCopy(self->s.v.origin, self->finaldest); return; } // set destdelta to the vector needed to move VectorSubtract(self->finaldest, self->s.v.origin, vdestdelta); // calculate length of vector len = vlen (vdestdelta); if ((int) current->s.v.spawnflags & MOVETIME) { traintraveltime = current->speed; } else { // check if there's a speed change if (current->speed > 0) { self->speed = current->speed; } if (!self->speed) { G_Error("No speed is defined!"); } // divide by speed to get time to reach dest traintraveltime = len / self->speed; } if (traintraveltime < 0.1f) { SetVector(self->s.v.velocity, 0, 0, 0); self->endtime = self->s.v.ltime + 0.1f; if ((int) targ->s.v.spawnflags & ANGLES) { VectorCopy(targ->s.v.angles, self->s.v.angles); } return; } // qcc won't take vec/float div = 1.0f / traintraveltime; if ((int) targ->s.v.spawnflags & ANGLES) { VectorCopy(targ->s.v.angles, self->finalangle); SUB_NormalizeAngles(self->finalangle); VectorSubtract(targ->s.v.angles, self->s.v.angles, self->rotate); VectorScale(self->rotate, div, self->rotate); } // set endtime to trigger a think when dest is reached self->endtime = self->s.v.ltime + traintraveltime; // scale the destdelta vector by the time spent traveling to get velocity VectorScale(vdestdelta, div, self->s.v.velocity); self->duration = div; // 1 / duration self->cnt = g_globalvars.time; // start time VectorCopy(vdestdelta, self->dest2); // delta VectorCopy(self->s.v.origin, self->dest1); // original position } } static void rotate_train_find(void) { gedict_t *targ; self->state = STATE_FIND; LinkRotateTargets(); // the first target is the point of rotation. // the second target is the path. targ = find (world, FOFS(targetname), self->path); if (!streq(targ->classname, "path_rotate")) { G_Error("Next target is not path_rotate"); } // Save the current entity self->s.v.goalentity = EDICT_TO_PROG(targ); if ((int) targ->s.v.spawnflags & ANGLES) { VectorCopy(targ->s.v.angles, self->s.v.angles); SUB_NormalizeAngles(targ->s.v.angles); VectorCopy(targ->s.v.angles, self->finalangle); } self->path = targ->target; setorigin (self, PASSVEC3(targ->s.v.origin)); SetTargetOrigin(); RotateTargetsFinal(); self->think1 = rotate_train_next; if (strnull(self->targetname)) { // not triggered, so start immediately self->endtime = self->s.v.ltime + 0.1f; } else { self->endtime = 0; } self->duration = 1; // 1 / duration self->cnt = g_globalvars.time; // start time SetVector(self->dest2, 0, 0, 0); // delta VectorCopy(self->s.v.origin, self->dest1); // original position } /*QUAKED func_rotate_train (0 .5 .8) (-8 -8 -8) (8 8 8) In path_rotate, set speed to be the new speed of the train after it reaches the path change. If speed is -1, the train will warp directly to the next path change after the specified wait time. If MOVETIME is set on the path_rotate, the train to interprets "speed" as the length of time to take moving from one corner to another. "noise" contains the name of the sound to play when train stops. "noise1" contains the name of the sound to play when train moves. Both "noise" and "noise1" defaults depend upon "sounds" variable and can be overridden by the "noise" and "noise1" variable in path_rotate. Also in path_rotate, if STOP is set, the train will wait until it is retriggered before moving on to the next goal. Trains are moving platforms that players can ride. "path" specifies the first path_rotate and is the starting position. If the train is the target of a button or trigger, it will not begin moving until activated. The func_rotate_train entity is the center of rotation of all objects targeted by it. If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train. speed default 100 dmg default 0 sounds 1) ratchet metal */ void SP_func_rotate_train(void) { if (!self->speed) { self->speed = 100; } if (!self->target) { G_Error ("rotate_train without a target"); } if (!self->noise) { if (self->s.v.sounds == 0) { self->noise = ("misc/null.wav"); } if (self->s.v.sounds == 1) { self->noise = ("plats/train2.wav"); } } if (!self->noise1) { if (self->s.v.sounds == 0) { self->noise1 = ("misc/null.wav"); } if (self->s.v.sounds == 1) { self->noise1 = ("plats/train1.wav"); } } trap_precache_sound( self->noise ); trap_precache_sound( self->noise1 ); self->cnt = 1; self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_STEP; self->use = (func_t) rotate_train_use; setmodel (self, self->model); setsize (self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); setorigin (self, PASSVEC3(self->s.v.origin)); // start trains on the second frame, to make sure their targets have had // a chance to spawn self->s.v.ltime = g_globalvars.time; self->s.v.nextthink = self->s.v.ltime + 0.1f; self->endtime = self->s.v.ltime + 0.1f; self->think = (func_t) rotate_train_think; self->think1 = rotate_train_find; self->state = STATE_FIND; self->duration = 1; // 1 / duration self->cnt = 0.1f; // start time SetVector(self->dest2, 0, 0, 0); // delta VectorCopy(self->s.v.origin, self->dest1); // original position self->s.v.flags = (float)((int) self->s.v.flags | FL_ONGROUND); } //************************************************ // // Moving clip walls // //************************************************ static void rotate_door_reversedirection(void); static void rotate_door_group_reversedirection(void); static void movewall_touch(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); if (g_globalvars.time < owner->attack_finished) { return; } if (self->dmg) { T_Damage (other, self, owner, self->dmg); owner->attack_finished = g_globalvars.time + 0.5f; } else if (owner->dmg) { T_Damage (other, self, owner, owner->dmg); owner->attack_finished = g_globalvars.time + 0.5f; } } static void movewall_blocked(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); gedict_t *temp; if (g_globalvars.time < owner->attack_finished) { return; } owner->attack_finished = g_globalvars.time + 0.5f; if (streq(owner->classname, "func_rotate_door")) { temp = self; self = owner; rotate_door_group_reversedirection(); self = temp; } if ( self->dmg) { T_Damage (other, self, owner, self->dmg); owner->attack_finished = g_globalvars.time + 0.5f; } else if (owner->dmg) { T_Damage (other, self, owner, owner->dmg); owner->attack_finished = g_globalvars.time + 0.5f; } } static void movewall_think(void) { self->s.v.ltime = g_globalvars.time; self->s.v.nextthink = g_globalvars.time + 0.02f; } /*QUAKED func_movewall (0 .5 .8) ? VISIBLE TOUCH NONBLOCKING Used to emulate collision on rotating objects. VISIBLE causes brush to be displayed. TOUCH specifies whether to cause damage when touched by player. NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set. "dmg" specifies the damage to cause when touched or blocked. */ void SP_func_movewall(void) { SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_PUSH; if ((int) self->s.v.spawnflags & NONBLOCKING) { self->s.v.solid = SOLID_NOT; } else { self->s.v.solid = SOLID_BSP; self->blocked = (func_t) movewall_blocked; } if ((int) self->s.v.spawnflags & TOUCH) { self->touch = (func_t) movewall_touch; } setmodel(self, self->model); if (!((int) self->s.v.spawnflags & VISIBLE)) { self->model = NULL; } self->think = (func_t) movewall_think; self->s.v.nextthink = g_globalvars.time + 0.02f; self->s.v.ltime = g_globalvars.time; } /*QUAKED rotate_object (0 .5 .8) ? This defines an object to be rotated. Used as the target of func_rotate_door. */ void SP_rotate_object(void) { self->classname = "rotate_object"; self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_NONE; setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); self->think = (func_t) SUB_Null; }; //************************************************ // // Rotating doors // //************************************************ static void rotate_door_think2(void) { self->s.v.ltime = g_globalvars.time; // change to alternate textures self->s.v.frame = 1 - self->s.v.frame; VectorCopy(self->dest, self->s.v.angles); if (self->state == STATE_OPENING) { self->state = STATE_OPEN; } else { if ((int) self->s.v.spawnflags & STAYOPEN ) { rotate_door_group_reversedirection(); return; } self->state = STATE_CLOSED; } sound(self, CHAN_VOICE, self->noise3, 1, ATTN_NORM); self->think = (func_t) SUB_Null; RotateTargetsFinal(); } static void rotate_door_think(void) { float t; vec3_t delta; t = g_globalvars.time - self->s.v.ltime; self->s.v.ltime = g_globalvars.time; if (g_globalvars.time < self->endtime ) { VectorScale(self->rotate, t, delta); VectorAdd(self->s.v.angles, delta, self->s.v.angles); RotateTargets(); } else { VectorCopy(self->dest, self->s.v.angles); RotateTargets(); self->think = (func_t) rotate_door_think2; } self->s.v.nextthink = g_globalvars.time + 0.01f; } static void rotate_door_reversedirection(void) { vec3_t start; // change to alternate textures self->s.v.frame = 1 - self->s.v.frame; if (self->state == STATE_CLOSING) { VectorCopy(self->dest1, start); VectorCopy(self->dest2, self->dest); self->state = STATE_OPENING; } else { VectorCopy(self->dest2, start); VectorCopy(self->dest1, self->dest); self->state = STATE_CLOSING; } sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); VectorSubtract(self->dest, start, self->rotate); VectorScale(self->rotate, 1.0f / self->speed, self->rotate); self->think = (func_t) rotate_door_think; self->s.v.nextthink = g_globalvars.time + 0.02f; self->endtime = g_globalvars.time + self->speed - (self->endtime - g_globalvars.time); self->s.v.ltime = g_globalvars.time; } static void rotate_door_group_reversedirection(void) { char *name; // tell all associated rotaters to reverse direction if (self->group) { name = self->group; self = find(world, FOFS(group), name); while (self) { rotate_door_reversedirection(); self = find(self, FOFS(group), name); } } else { rotate_door_reversedirection(); } } static void rotate_door_use(void) { vec3_t start; if ((self->state != STATE_OPEN) && (self->state != STATE_CLOSED)) { return; } if (!self->cnt) { self->cnt = 1; LinkRotateTargets(); } // change to alternate textures self->s.v.frame = 1 - self->s.v.frame; if (self->state == STATE_CLOSED) { VectorCopy(self->dest1, start); VectorCopy(self->dest2, self->dest); self->state = STATE_OPENING; } else { VectorCopy(self->dest2, start); VectorCopy(self->dest1, self->dest); self->state = STATE_CLOSING; } sound(self, CHAN_VOICE, self->noise2, 1, ATTN_NORM); VectorSubtract(self->dest, start, self->rotate); VectorScale(self->rotate, 1.0f / self->speed, self->rotate); self->think = (func_t) rotate_door_think; self->s.v.nextthink = g_globalvars.time + 0.01f; self->endtime = g_globalvars.time + self->speed; self->s.v.ltime = g_globalvars.time; } /*QUAKED func_rotate_door (0 .5 .8) (-8 -8 -8) (8 8 8) STAYOPEN Creates a door that rotates between two positions around a point of rotation each time it's triggered. STAYOPEN tells the door to reopen after closing. This prevents a trigger- once door from closing again when it's blocked. "dmg" specifies the damage to cause when blocked. Defaults to 2. Negative numbers indicate no damage. "speed" specifies how the time it takes to rotate "sounds" 1) medieval (default) 2) metal 3) base */ void SP_func_rotate_door(void) { if (strnull(self->target)) { G_Error("rotate_door without target."); } SetVector(self->dest1, 0, 0, 0); VectorCopy(self->s.v.angles, self->dest2); VectorCopy(self->dest1, self->s.v.angles); // default to 2 seconds if (!self->speed) { self->speed = 2; } self->cnt = 0; if (!self->dmg) { self->dmg = 2; } else if (self->dmg < 0) { self->dmg = 0; } if (self->s.v.sounds == 0) { self->s.v.sounds = 1; } if (self->s.v.sounds == 1) { trap_precache_sound("doors/latch2.wav"); trap_precache_sound("doors/winch2.wav"); trap_precache_sound("doors/drclos4.wav"); self->noise1 = "doors/latch2.wav"; self->noise2 = "doors/winch2.wav"; self->noise3 = "doors/drclos4.wav"; } if (self->s.v.sounds == 2) { trap_precache_sound("doors/airdoor1.wav"); trap_precache_sound("doors/airdoor2.wav"); self->noise2 = "doors/airdoor1.wav"; self->noise1 = "doors/airdoor2.wav"; self->noise3 = "doors/airdoor2.wav"; } if (self->s.v.sounds == 3) { trap_precache_sound("doors/basesec1.wav"); trap_precache_sound("doors/basesec2.wav"); self->noise2 = "doors/basesec1.wav"; self->noise1 = "doors/basesec2.wav"; self->noise3 = "doors/basesec2.wav"; } self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_NONE; setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); setorigin(self, PASSVEC3(self->s.v.origin)); self->state = STATE_CLOSED; self->use = (func_t) rotate_door_use; self->think = (func_t) SUB_Null; } QW-Group-ktx-d05d6ca/src/hoonymode.c000066400000000000000000000710701475442401000173710ustar00rootroot00000000000000// HoonyMode implementation (thanks Richard 'Hoony' Sandlant for idea from cpma) // Thanks for help with code and testing: // #qw-dev, deurk, johnny_cz, vvd, timon, eternal, dr4ko, rusty, twitch, mushi, 23, m@tr!}{, helltiger, leopold, quark // 2012-03-02 - Initial code by phil // 2012-03-05 - Got stuck on cvar_set/fset not working, so using static int instead :D // 2012-03-06 - Got point-by-point play working (without map reload) // 2012-03-08 - Got spawn rigging to work // 2012-03-09 - Cleanup client and server console spamming // 2012-03-13 - Complete rewrite (now that I know how ktx works...) ready for testing // 2012-03-14 - Nicer looking lastscores // 2012-03-20 - Per-point player stats (was thinking about how to do this and had a sudden idea) // 2012-03-26 - Bugs fixed - hmstats health incorrectly computed as health+armor, // lava deaths (and others) not scored properly, and also ring/quad... (thx dr4k0 for testing) // 2016 - timelimits, scenarios based on .ent files, spawn nominations (meag) // 2017-05-13 - team-based hoonymode - multiple rounds // todo: fix lg door/dm2 floating/etc // todo: test drop/rejoin, and how it affects spawn memory // todo: test name change during game and how it affects lastscores // todo: reset more items on map (e.g. lg door on dm6) #include "g_local.h" static void HM_store_spawns(void); #define HM_RESULT_NOTPLAYED 0 #define HM_RESULT_WONROUND 1 #define HM_RESULT_LOSTROUND 2 #define HM_RESULT_SUICIDELOSS 3 #define HM_RESULT_SUICIDEWIN 4 #define HM_RESULT_DRAWWIN 5 const char hm_result_indicator[] = "\0WLswD"; #define HM_WINNING_DIFF 2 static qbool match_break = false; static int round_number = 0; // valid array index static int true_round_number = 0; // keeps increasing, for insane case of > HM_MAX_ROUNDS game static char round_explanation[128] = { 0 }; static char series_explanation[128] = { 0 }; static void EndRound(void) { ++true_round_number; if (round_number < HM_MAX_ROUNDS - 1) { ++round_number; } else { // Start over-writing last round to stop buffer over-run --round_number; } EndMatch(0); } const char* HM_round_results(gedict_t *player) { static char buffer[HM_MAX_ROUNDS * 4 + 1]; int i; if (isDuel()) { for (i = 0; i < round_number; ++i) { if ((player->hoony_results[i] >= 0) && (player->hoony_results[i] < sizeof(hm_result_indicator))) { buffer[i] = hm_result_indicator[player->hoony_results[i]]; } } buffer[i] = '\0'; return buffer; } return ""; } qbool isHoonyModeDuel(void) { return (isDuel() && cvar("k_hoonymode")); } qbool isHoonyModeAny(void) { return cvar("k_hoonymode"); } qbool isHoonyModeTDM(void) { return (isTeam() && cvar("k_hoonymode")); } int HM_rounds(void) { int rounds = cvar("k_hoonyrounds"); return (rounds ? rounds : 6); } void HM_initialise_rounds(void) { round_number = 0; } int HM_timelimit(void) { if (timelimit) { return (timelimit * 60); } return world->hoony_timelimit; } // duel: suicide, etc, count as a point for other players // in teamplay, dock the frag as normal void HM_suicide(gedict_t *player) { gedict_t *p; if (isDuel()) { player->hoony_results[round_number] = HM_RESULT_SUICIDELOSS; for (p = world; (p = find_plr(p));) { if (p != player) { p->s.v.frags += 1; p->hoony_results[round_number] = HM_RESULT_SUICIDEWIN; } } EndRound(); } } // Timelimit hit void HM_draw(void) { if (isHoonyModeDuel()) { gedict_t *p; int maxfrags = -9999, minfrags = 9999; for (p = world; (p = find_plr(p));) { // .ent file can dictate that one player wins by default if (!strnull(world->hoony_defaultwinner) && p->k_hoony_new_spawn && streq(p->k_hoony_new_spawn->targetname, world->hoony_defaultwinner)) { p->s.v.frags++; G_bprint(2, "%s wins the round on time.\n", p->netname); EndRound(); return; } maxfrags = max(p->s.v.frags, maxfrags); minfrags = min(p->s.v.frags, minfrags); } if (maxfrags < HM_rounds()) { // If in normal rounds, everyone gets a point, so we get closer to finishing. gedict_t *p; for (p = world; (p = find_plr(p));) { p->hoony_results[round_number] = HM_RESULT_DRAWWIN; p->s.v.frags++; for (p = world; (p = find_plr(p));) { p->hoony_results[round_number] = HM_RESULT_DRAWWIN; p->s.v.frags++; } } } // We go again... G_bprint(PRINT_HIGH, "This round ends in a draw\n"); } EndRound(); } qbool HM_is_game_over(void) { // If the round ended due to /break then game is over if (match_break) { return true; } // Game is over if we've hit frag limit and one player is in lead (HM_PT_FINAL), or // one player is one frag ahead at the start of a round of spawns and we're past the fraglimit if (HM_current_point_type() == HM_PT_FINAL) { return true; } // if (isHoonyModeDuel() && HM_current_point_type() == HM_PT_SET && true_round_number % 2 == 0) { gedict_t *p; int maxfrags = -999; int minfrags = 999; for (p = world; (p = find_plr(p));) { maxfrags = max(p->s.v.frags, maxfrags); minfrags = min(p->s.v.frags, minfrags); } return ((maxfrags != minfrags) && (maxfrags > (HM_rounds() / 2))); } return false; } void HM_next_point(gedict_t *winner, gedict_t *loser) { winner->hoony_results[round_number] = HM_RESULT_WONROUND; loser->hoony_results[round_number] = HM_RESULT_LOSTROUND; EndRound(); } int HM_current_point(void) { return round_number; } int HM_current_point_type(void) { if (!isHoonyModeDuel()) { int score1 = get_scores1(); int score2 = get_scores2(); int maxfrags = max(score1, score2), minfrags = min(score1, score2); int fragdiff = maxfrags - minfrags; // Must have even number of rounds if ((round_number >= (HM_rounds() - 1)) && ((round_number % 2) == 1)) { return HM_PT_SET; } // Finish as soon as possible, as long as there's a winner if ((round_number >= HM_rounds()) && fragdiff) { return HM_PT_FINAL; } } else { gedict_t *p; int maxfrags = -999, minfrags = 999; int fragdiff; for (p = world; (p = find_plr(p));) { maxfrags = max(maxfrags, p->s.v.frags); minfrags = min(minfrags, p->s.v.frags); } fragdiff = maxfrags - minfrags; if ((round_number >= HM_rounds()) && (fragdiff >= HM_WINNING_DIFF)) { return HM_PT_FINAL; } if ((maxfrags >= (HM_rounds() / 2)) && (fragdiff >= (HM_WINNING_DIFF - 1))) { return HM_PT_SET; } } return 0; } void SUB_regen(void); void remove_items(char *classname) { gedict_t *p; for (p = world; (p = find(p, FOFCLSN, classname)); /**/) { ent_remove(p); } } void respawn_items(char *classname, qbool enabled) { gedict_t *p; if (strnull(classname)) { G_Error("respawn_items"); } for (p = world; (p = find(p, FOFCLSN, classname)); /**/) { if (enabled) { if (p->initial_spawn_delay > 0) { // hide, but respawn at future point setmodel(p, ""); p->s.v.solid = (bots_enabled() ? SOLID_TRIGGER : SOLID_NOT); p->s.v.nextthink = g_globalvars.time + p->initial_spawn_delay; p->think = (func_t) SUB_regen; } else { // respawn now p->s.v.nextthink = g_globalvars.time; p->think = (func_t) SUB_regen; } #ifdef BOT_SUPPORT p->fb.goal_respawn_time = p->s.v.nextthink; #endif } else { // hide item setmodel(p, ""); p->s.v.solid = (bots_enabled() ? SOLID_TRIGGER : SOLID_NOT); p->s.v.nextthink = 0; #ifdef BOT_SUPPORT p->fb.goal_respawn_time = 0; #endif } } } void HM_reset_map(void) { // re-initialise items for every point respawn_items("item_shells", true); respawn_items("item_spikes", true); respawn_items("item_rockets", true); respawn_items("item_cells", true); respawn_items("item_health", true); respawn_items("item_armor1", true); respawn_items("item_armor2", true); respawn_items("item_armorInv", true); respawn_items("weapon_supershotgun", true); respawn_items("weapon_nailgun", true); respawn_items("weapon_supernailgun", true); respawn_items("weapon_grenadelauncher", true); respawn_items("weapon_rocketlauncher", true); respawn_items("weapon_lightning", true); respawn_items("item_artifact_invulnerability", Get_Powerups()); respawn_items("item_artifact_super_damage", Get_Powerups()); respawn_items("item_artifact_envirosuit", Get_Powerups()); respawn_items("item_artifact_invisibility", Get_Powerups()); // remove temporary objects remove_projectiles(); remove_items("backpack"); } static int HM_spawn_comparison(const void *lhs_, const void *rhs_) { const gedict_t *lhs = *(const gedict_t**) lhs_; const gedict_t *rhs = *(const gedict_t**) rhs_; if (lhs->hoony_spawn_order < rhs->hoony_spawn_order) { return -1; } else if (lhs->hoony_spawn_order > rhs->hoony_spawn_order) { return 1; } return 0; } static void HM_sort_spawns(gedict_t **spawns, int count) { #ifdef Q3_VM qbool any_changes = true; // bubble-sort, lovely while (any_changes) { int i; any_changes = false; for (i = 0; i < count - 1; ++i) { int comp = HM_spawn_comparison(&spawns[i], &spawns[i + 1]); if (comp > 0) { gedict_t* temp = spawns[i]; spawns[i] = spawns[i + 1]; spawns[i + 1] = temp; any_changes = true; } } } #else qsort(spawns, count, sizeof(spawns[0]), HM_spawn_comparison); #endif } static void HM_shuffle_spawns(gedict_t **spawns, int count) { int i = 0; int j = 0; for (i = 0; i < 6; ++i) { for (j = 0; j < count; ++j) { spawns[j]->hoony_spawn_order = (spawns[j]->hoony_nomination ? -1 : 1) * i_rnd(1, 100); } HM_sort_spawns(spawns, count); } } static gedict_t *red_spawns[MAX_CLIENTS] = { 0 }; static gedict_t *blue_spawns[MAX_CLIENTS] = { 0 }; static int red_spawncount = 0; static int blue_spawncount = 0; // This is called at the start of each round void HM_all_ready(void) { gedict_t *p; qbool debug = cvar("developer"); for (p = world; (p = find_plr(p)); /**/) { // Clear allocated spawns for the current round p->k_hoony_new_spawn = NULL; } // Shuffle spawn order, then assign to players if (HM_current_point() % 2 == 0) { // randomise order if (isTeam()) { int red_assigned_spawn = 0; int blue_assigned_spawn = 0; int red_players = 0; int blue_players = 0; qbool red_wrapped = false; qbool blue_wrapped = false; qbool alternate = i_rnd(1, 10) <= 5; // Allocate specific red/blue spawns accordingly red_spawncount = blue_spawncount = 0; // Allocate assigned deathmatch spawns for (p = world; (p = ez_find(p, "info_player_deathmatch"));) { if ((red_spawncount < MAX_CLIENTS) && (p->hoony_nomination == (alternate ? 2 : 1))) { red_spawns[red_spawncount++] = p; } else if ((blue_spawncount < MAX_CLIENTS) && (p->hoony_nomination == (alternate ? 1 : 2))) { blue_spawns[blue_spawncount++] = p; } } // Allocate standard deathmatch spawns for (p = world; (p = ez_find(p, "info_player_deathmatch")) && (red_spawncount < MAX_CLIENTS || blue_spawncount < MAX_CLIENTS);) { if (p->hoony_nomination) { continue; } if ((red_spawncount < MAX_CLIENTS) && (red_spawncount < blue_spawncount)) { red_spawns[red_spawncount++] = p; } else if (blue_spawncount < MAX_CLIENTS) { blue_spawns[blue_spawncount++] = p; } } // Shuffle HM_shuffle_spawns(red_spawns, red_spawncount); HM_shuffle_spawns(blue_spawns, blue_spawncount); // Assign based on team for (p = world; (p = find_plr(p)); /**/) { if (red_assigned_spawn == (int)min(red_spawncount, MAX_CLIENTS)) { red_assigned_spawn = 0; red_wrapped = true; } if (blue_assigned_spawn == (int)min(blue_spawncount, MAX_CLIENTS)) { blue_assigned_spawn = 0; blue_wrapped = true; } if (streq(getteam(p), "red")) { p->k_hoony_new_spawn = p->k_hoonyspawn = red_spawns[red_assigned_spawn++]; ++red_players; } else { p->k_hoony_new_spawn = p->k_hoonyspawn = blue_spawns[blue_assigned_spawn++]; ++blue_players; } if (debug) { G_bprint(PRINT_HIGH, "Assigned '%s' to %s (%s)\n", p->k_hoony_new_spawn->targetname, p->netname, getteam(p)); } } if (!red_wrapped) { red_spawncount = min(red_spawncount, max(red_assigned_spawn, blue_players)); } if (!blue_wrapped) { blue_spawncount = min(blue_spawncount, max(blue_assigned_spawn, red_players)); } } else { gedict_t *spawns[MAX_CLIENTS] = { 0 }; int spawncount = 0; int assigned_spawn = 0; for (p = world; (p = ez_find(p, "info_player_deathmatch")) && spawncount < MAX_CLIENTS;) { spawns[spawncount++] = p; } HM_shuffle_spawns(spawns, spawncount); if (debug) { G_bprint(PRINT_HIGH, "Shuffling spawn points...\n"); } // assign as standard for (p = world; (p = find_plr(p)); /**/) { if (assigned_spawn == (int)min(spawncount, MAX_CLIENTS)) { assigned_spawn = 0; } p->k_hoony_new_spawn = p->k_hoonyspawn = spawns[assigned_spawn++]; if (debug) { G_bprint(PRINT_HIGH, "Assigned '%s' to %s\n", p->k_hoony_new_spawn->targetname, p->netname); } } } } else { // on odd-numbered rounds, swap spawn points with opponents if (isTeam()) { int red_assigned_spawn = 0; int blue_assigned_spawn = 0; // Shuffle again HM_shuffle_spawns(red_spawns, red_spawncount); HM_shuffle_spawns(blue_spawns, blue_spawncount); // Assign based on team for (p = world; (p = find_plr(p)); /**/) { if (red_assigned_spawn == (int)min(red_spawncount, MAX_CLIENTS)) { red_assigned_spawn = 0; } if (blue_assigned_spawn == (int)min(blue_spawncount, MAX_CLIENTS)) { blue_assigned_spawn = 0; } if (!streq(getteam(p), "red")) { p->k_hoony_new_spawn = p->k_hoonyspawn = red_spawns[red_assigned_spawn++]; } else { p->k_hoony_new_spawn = p->k_hoonyspawn = blue_spawns[blue_assigned_spawn++]; } if (debug) { G_bprint(PRINT_HIGH, "Assigned '%s' to %s (%s)\n", p->k_hoony_new_spawn->targetname, p->netname, getteam(p)); } } } else { for (p = world; (p = find_plr(p)); /**/) { gedict_t *next = find_plr(p); if (next == NULL) { next = find_plr(world); } p->k_hoony_new_spawn = next->k_hoonyspawn; if (debug) { G_bprint(PRINT_HIGH, "Assigned '%s' to %s\n", p->k_hoony_new_spawn->targetname, p->netname); } } } } } char* HM_lastscores_extra(void) { //extra[0] = 0; //strlcat(extra, va("\n%s\n%s", extra1, extra2), sizeof(extra)); //return extra; return ""; } // Naming spawns // - Spawns can have name set in map or .ent file // Hardcoded names for TB3/TB5 - could go away in future typedef struct hm_spawn_name_t { vec3_t origin; char *name; } hm_spawn_name; static void HM_name_spawn(gedict_t *spawn, hm_spawn_name *spawns, int spawncount) { if (strnull(spawn->targetname)) { int i = 0; for (i = 0; i < spawncount; ++i) { if (VectorCompare(spawn->s.v.origin, spawns[i].origin)) { spawn->targetname = spawns[i].name; break; } } } } void HM_name_map_spawn(gedict_t *spawn) { if (streq(mapname, "dm2")) { hm_spawn_name spawns[] = { { { 2560, -192, 32 }, "nailgun" }, { { 2544, -32, -64 }, "low tele" }, { { 2624, -488, 32 }, "water" }, { { 2176, -2176, 88 }, "low-btn" }, { { 2576, -1328, 24 }, "low-rl" }, { { 2704, -2048, 128 }, "ra-mega" }, { { 1712, -504, 24 }, "quad" }, { { 2048, -1352, 136 }, "big" }, { { 2248, -16, -136 }, "tele-btn" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "dm3")) { hm_spawn_name spawns[] = { { { -880, -232, -16 }, "tele/sng" }, { { 192, -208, -176 }, "big>ra" }, { { 1472, -928, -24 }, "ya box" }, { { 1520, 432, -88 }, "rl" }, { { -632, -680, -16 }, "tele/ra" }, { { 512, 768, 216 }, "lifts" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "dm4")) { hm_spawn_name spawns[] = { { { -64, 512, -296 }, "mh room" }, { { -64, -232, -72 }, "quad" }, { { 272, -952, 24 }, "high" }, { { 112, -1136, -104 }, "ssg" }, { { 776, -808, -232 }, "ra" }, { { 784, -176, 24 }, "ya-entry" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "dm6")) { hm_spawn_name spawns[] = { { { 232, -1512, 40 }, "ga tele" }, { { 1016, -416, 40 }, "low rl" }, { { 0, -1088, 264 }, "high rl" }, { { 456, -1504, 256 }, "sng" }, { { 408, -1088, 256 }, "gl>sng" }, { { 896, -1464, 256 }, "gl room" }, { { 1892, -160, 168 }, "ra" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "e1m2")) { hm_spawn_name spawns[] = { { { -416, -144, 320 }, "mh room" }, { { 168, -480, 320 }, "mh door" }, { { 1496, 1328, 200 }, "start" }, { { 1936, -136, 312 }, "traps>ya" }, { { 936, -1216, 432 }, "quad>gl" }, { { 792, -992, 440 }, "gl>quad" }, { { 1080, -720, 312 }, "ya" }, { { 408, -752, 432 }, "quad" }, { { 792, -208, 320 }, "doors" }, { { 784, 808, 206 }, "rl" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "ztndm3")) { hm_spawn_name spawns[] = { { { -432, 128, 32 }, "ra/nails" }, { { -1056, -544, 224 }, "grenade" }, { { -208, -400, 224 }, "ya room" }, { { -320, 576, 224 }, "quad" }, { { -176, -112, 288 }, "ra/ssg" }, { { -96, 224, 32 }, "lg" }, { { -800, 0, -32 }, "ra/mega" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } else if (streq(mapname, "aerowalk")) { hm_spawn_name spawns[] = { { { -224, -720, 256 }, "grenade" }, { { -488, 624, 264 }, "low rl" }, { { -224, -704, 456 }, "high rl" }, { { -272, 24, 40 }, "floor" }, { { -320, 480, 456 }, "ra" }, { { 160, 128, 256 }, "under lg" } }; HM_name_spawn(spawn, spawns, sizeof(spawns) / sizeof(spawns[0])); } } // Picking spawns // - In pregame, allow players to pick spawn points to use during the game // If player doesn't nominate a spawn point, 'their' spawn will be randomly chosen each round gedict_t* Spawn_OnePoint(gedict_t *spawn_point, vec3_t org, int effects); static void HM_deselect_spawn(gedict_t *spawn) { int effects = (EF_GREEN | EF_RED | EF_BLUE); if (!spawn->wizard) { return; } // If showing all spawns, just remove the glow. otherwise remove the marker. if (cvar("k_spm_show")) { spawn->wizard->s.v.effects = (int)spawn->wizard->s.v.effects & ~effects; } else { ent_remove(spawn->wizard); spawn->wizard = 0; } if (spawn->hoony_nomination && isHoonyModeDuel()) { g_edicts[spawn->hoony_nomination].hoony_nomination = 0; } spawn->hoony_nomination = 0; } static void HM_select_spawn(gedict_t *spawn, gedict_t *player, int effects) { if (spawn->wizard) { spawn->wizard->s.v.effects = (int)spawn->wizard->s.v.effects | effects; } else { Spawn_OnePoint(spawn, spawn->s.v.origin, effects); } if (isHoonyModeDuel()) { if (player) { spawn->hoony_nomination = NUM_FOR_EDICT(player); player->hoony_nomination = NUM_FOR_EDICT(spawn); } } else { spawn->hoony_nomination = (effects == EF_RED ? 1 : 2); } } void HM_pick_spawn(void) { gedict_t *spawn = world; gedict_t *closest = world; gedict_t *old_nomination = world; int spawn_count = 0; int closest_spawn_num = 0; // count spawns and use when spawns are unnamed int self_num = NUM_FOR_EDICT(self); float closest_distance = 9999999.9f; int teamflag = 0; int red_spawns = 0, blue_spawns = 0; if (!isHoonyModeDuel()) { char *team = getteam(self); if (streq(team, "red")) { teamflag = 1; } else if (streq(team, "blue")) { teamflag = 2; } else { G_sprint(self, 2, "Command only available in %s duel mode.\n", redtext("hoonymode")); return; } } if (match_in_progress || intermission_running) { G_sprint(self, 2, "Command not available during game.\n"); return; } for (spawn = world; (spawn = ez_find(spawn, "info_player_deathmatch"));) { vec3_t difference; float distance = 0.0f; ++spawn_count; VectorSubtract(spawn->s.v.origin, self->s.v.origin, difference); distance = VectorLength(difference); if ((closest == world) || (distance < closest_distance)) { closest = spawn; closest_distance = distance; closest_spawn_num = spawn_count; } if (isHoonyModeDuel()) { // Picking spawn for this individual if (spawn->hoony_nomination == self_num) { old_nomination = spawn; } } else { // Picking spawn for this team - don't allow too many if (spawn->hoony_nomination == 1) { ++red_spawns; } else if (spawn->hoony_nomination == 2) { ++blue_spawns; } } } if (closest == world) { G_sprint(self, 2, "No closest spawn found\n"); return; } if ((closest == old_nomination) || (isHoonyModeTDM() && (closest->hoony_nomination == teamflag))) { // Duel only: we're picking for ourselves, so this unpicks the current option if (isHoonyModeDuel()) { G_bprint(2, "%s opts for %s spawns\n", self->netname, redtext("random")); } else if (!strnull(closest->targetname)) { G_bprint(2, "%s unpicks spawn %s for team \20%s\21\n", self->netname, redtext(closest->targetname), teamflag == 1 ? "red" : "blue"); } else { G_bprint(2, "%s unpicks spawn #%d for team \20%s\21\n", self->netname, closest_spawn_num, teamflag == 1 ? "red" : "blue"); } HM_deselect_spawn(closest); } else if (closest->hoony_nomination) { char *current = isHoonyModeDuel() ? g_edicts[closest->hoony_nomination].netname : closest->hoony_nomination == 1 ? "red" : "blue"; if (!strnull(closest->targetname)) { G_sprint(self, 2, "%s has already been picked by team \20%s\21\n", redtext(closest->targetname), current); } else { G_sprint(self, 2, "spawn #%d has already been picked by \20%s\21\n", closest_spawn_num, current); } } else { if ((teamflag == 1 ? red_spawns : blue_spawns) >= (cvar("maxclients") / 2)) { G_sprint(self, PRINT_HIGH, "Team already has %d spawns allocated\n", (teamflag == 1 ? red_spawns : blue_spawns)); return; } else { if (old_nomination != 0) { HM_deselect_spawn(old_nomination); } if (isHoonyModeDuel()) { if (!strnull(closest->targetname)) { G_bprint(2, "%s picks spawn %s\n", self->netname, redtext(closest->targetname)); } else { G_bprint(2, "%s picks spawn #%d\n", self->netname, closest_spawn_num); } } else if (!strnull(closest->targetname)) { G_bprint(2, "%s picks spawn %s for team \20%s\21\n", self->netname, redtext(closest->targetname), teamflag == 1 ? "red" : "blue"); } else { G_bprint(2, "%s picks spawn #%d for team \20%s\21\n", self->netname, closest_spawn_num, teamflag == 1 ? "red" : "blue"); } HM_select_spawn(closest, self, isHoonyModeDuel() ? EF_GREEN : teamflag == 1 ? EF_RED : EF_BLUE); } } HM_store_spawns(); } void HM_unpick_all_spawns(void) { gedict_t *spawn; for (spawn = world; (spawn = ez_find(spawn, "info_player_deathmatch"));) { HM_deselect_spawn(spawn); } HM_store_spawns(); } // If this returns NULL, standard ktx spawn-picking rules will be applied gedict_t* HM_choose_spawn_point(gedict_t *self) { if (self->k_hoony_new_spawn) { if ((match_in_progress == 2) && isHoonyModeDuel()) { return self->k_hoony_new_spawn; } else if (match_in_progress == 2) { // tdm: return selected spawn on initial spawn, then default behaviour if (match_start_time == g_globalvars.time) { return self->k_hoony_new_spawn; } return NULL; } else { // Go through spawns sequentially when pre-game gedict_t *spot = ez_find(self->k_hoony_new_spawn, "info_player_deathmatch"); if (spot == NULL) { spot = ez_find(world, "info_player_deathmatch"); } return spot; } } // We haven't allocated a spawnpoint, so just act normal return NULL; } // The player was spawned at a particular point, update if necessary void HM_log_spawn_point(gedict_t *player, gedict_t *spawn) { if (match_in_progress == 0) { player->k_hoony_new_spawn = spawn; } } void HM_rounds_adjust(int change) { int rounds = HM_rounds(); int new_rounds = bound(2, HM_rounds() + change * 2, 20); cvar_fset("k_hoonyrounds", new_rounds); if (new_rounds == rounds) { G_sprint(self, 2, "%s still %s\n", redtext("roundlimit"), dig3(new_rounds)); } else { G_bprint(2, "%s %s\n", redtext("Roundlimit set to"), dig3(new_rounds)); } } void HM_point_stats(void) { gedict_t *p; int red_frags = 0; int blue_frags = 0; int prev_red_frags = 0; int prev_blue_frags = 0; int red_last_round = 0; int blue_last_round = 0; if (!isTeam()) { // In duels, HM_next_point stores point data as death occurs return; } for (p = world; (p = find_plr(p));) { char *team = getteam(p); if (streq(team, "red")) { prev_red_frags += p->hoony_prevfrags; red_frags += p->s.v.frags; } else if (streq(team, "blue")) { prev_blue_frags += p->hoony_prevfrags; blue_frags += p->s.v.frags; } if (round_number) { p->hoony_results[round_number - 1] = p->s.v.frags - p->hoony_prevfrags; } p->hoony_prevfrags = p->s.v.frags; } red_last_round = red_frags - prev_red_frags; blue_last_round = blue_frags - prev_blue_frags; if (red_last_round == blue_last_round) { strlcpy(round_explanation, "Round was a draw!\n", sizeof(round_explanation)); } else if (red_last_round > blue_last_round) { snprintf(round_explanation, sizeof(round_explanation), "\20%s\21 won round by %d frag%s\n", redtext("red"), red_last_round - blue_last_round, red_last_round - blue_last_round > 1 ? "s" : ""); } else { snprintf(round_explanation, sizeof(round_explanation), "\20%s\21 won round by %d frag%s\n", redtext("blue"), blue_last_round - red_last_round, blue_last_round - red_last_round > 1 ? "s" : ""); } if (red_frags == blue_frags) { strlcpy(series_explanation, "Series is currently tied.\n", sizeof(series_explanation)); } else if (red_frags > blue_frags) { snprintf(series_explanation, sizeof(series_explanation), "\20%s\21 leads series by %d frag%s\n", redtext("red"), red_frags - blue_frags, red_frags - blue_frags > 1 ? "s" : ""); } else { snprintf(series_explanation, sizeof(series_explanation), "\20%s\21 leads series by %d frag%s\n", redtext("blue"), blue_frags - red_frags, blue_frags - red_frags > 1 ? "s" : ""); } G_bprint(PRINT_HIGH, "%s", round_explanation); G_bprint(PRINT_HIGH, "%s", series_explanation); } const char* HM_round_explanation(void) { return round_explanation; } const char* HM_series_explanation(void) { return series_explanation; } void HM_roundsup(void) { if (!isHoonyModeAny()) { G_sprint(self, PRINT_HIGH, "Command only available in hoonymode\n"); } else if (!match_in_progress) { HM_rounds_adjust(1); } } void HM_roundsdown(void) { if (!isHoonyModeAny()) { G_sprint(self, PRINT_HIGH, "Command only available in hoonymode\n"); } else if (!match_in_progress) { HM_rounds_adjust(-1); } } void HM_restore_spawns(void) { char *entityFile = cvar_string("k_entityfile"); // Leave remembering spawn for individual players for now... // re-establish as the player re-joins server if (!isHoonyModeTDM()) { return; } if (streq(cvar_string("k_hoonymode_prevmap"), strnull(entityFile) ? mapname : entityFile)) { char *spawns = cvar_string("k_hoonymode_prevspawns"); int spawn_count = 0; gedict_t *spawn; for (spawn = world; (spawn = ez_find(spawn, "info_player_deathmatch"));) { ++spawn_count; } if (strlen(spawns) == spawn_count) { spawn_count = 0; for (spawn = world; (spawn = ez_find(spawn, "info_player_deathmatch")); spawn_count++) { if (spawns[spawn_count] == '1') { HM_select_spawn(spawn, NULL, EF_RED); } else if (spawns[spawn_count] == '2') { HM_select_spawn(spawn, NULL, EF_BLUE); } else { HM_deselect_spawn(spawn); } } } else { cvar_set("k_hoonymode_prevspawns", ""); } } else { cvar_set("k_hoonymode_prevspawns", ""); } } static void HM_store_spawns(void) { char *entityFile = cvar_string("k_entityfile"); char buffer[128]; gedict_t *spawn; char *next; next = buffer; for (spawn = world; (spawn = ez_find(spawn, "info_player_deathmatch"));) { *next++ = '0' + spawn->hoony_nomination; } *next = '\0'; cvar_set("k_hoonymode_prevmap", strnull(entityFile) ? mapname : entityFile); cvar_set("k_hoonymode_prevspawns", buffer); } void HM_match_break(void) { match_break = true; } QW-Group-ktx-d05d6ca/src/items.c000066400000000000000000001777071475442401000165270ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void SP_item_artifact_invisibility(void); void SP_item_artifact_super_damage(void); void SP_item_artifact_invulnerability(void); void TookWeaponHandler(gedict_t *p, int new_wp, qbool from_backpack); void BotsBackpackTouchedNonPlayer(gedict_t *backpack, gedict_t *entity); void BotsBackpackDropped(gedict_t *self, gedict_t *pack); void BotsPowerupTouchedNonPlayer(gedict_t *powerup, gedict_t *touch_ent); void BotsPowerupDropped(gedict_t *player, gedict_t *powerup); static qbool ItemTouched(gedict_t *item, gedict_t *player) { #ifdef BOT_SUPPORT return (self->fb.item_touch && self->fb.item_touch(item, player)); #else return false; #endif } static void ItemTaken(gedict_t *item, gedict_t *player) { TeamplayEventItemTaken(player, item); #ifdef BOT_SUPPORT if (self->fb.item_taken) { self->fb.item_taken(item, player); } #endif } void SUB_regen(void) { if (!deathmatch && (skill < 3)) { return; // do not respawn items in deathmatch 0 except on nightmare skill } self->model = self->mdl; // restore original model self->s.v.solid = SOLID_TRIGGER; // allow it to be touched again sound(self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM); // play respawn sound setorigin(self, PASSVEC3(self->s.v.origin)); #ifdef BOT_SUPPORT if (self->fb.item_respawned) { self->fb.item_respawned(self); } #endif } void SUB_regen_powerups(void) { extern void ktpro_autotrack_predict_powerup(void); // attempt to predict player which awating such powerup ktpro_autotrack_predict_powerup(); self->think = (func_t) SUB_regen; self->s.v.nextthink = g_globalvars.time + AUTOTRACK_POWERUPS_PREDICT_TIME; } void PlaceItem(void) { self->s.v.solid = SOLID_TRIGGER; self->s.v.movetype = MOVETYPE_TOSS; self->s.v.flags = FL_ITEM; self->mdl = strnull(self->model) ? self->mdl : self->model; // save .mdl if .model is not init self->mdl = strnull(self->mdl) ? "" : self->mdl; // init .mdl with empty string if not set SetVector(self->s.v.velocity, 0, 0, 0); self->s.v.origin[2] += 6; if (!droptofloor(self)) { G_Printf("Bonus item fell out of level at '%f %f %f'\n", self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2]); ent_remove(self); } // if powerups disabled - hide if ((int)self->s.v.items & (IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD)) { if (!Get_Powerups() || (((int)self->s.v.items & IT_INVISIBILITY) && !cvar("k_pow_r")) || (((int)self->s.v.items & IT_INVULNERABILITY) && !cvar("k_pow_p")) || (((int)self->s.v.items & IT_SUIT) && !cvar("k_pow_s")) || (((int)self->s.v.items & IT_QUAD) && !cvar("k_pow_q"))) { self->model = ""; self->s.v.solid = SOLID_NOT; } } } /* ============ PlaceItemIngame It is StartItem + PlaceItem, set some required fields for an item and drop it with random velocity, used for dropable powerups. ============ */ void PlaceItemIngame(void) { self->s.v.solid = SOLID_TRIGGER; self->s.v.movetype = MOVETYPE_TOSS; self->s.v.flags = FL_ITEM; self->mdl = self->model; // qqshka - save model ASAP self->s.v.velocity[2] = 300; self->s.v.velocity[0] = -100 + (g_random() * 200); self->s.v.velocity[1] = -100 + (g_random() * 200); self->s.v.nextthink = self->cnt; // remove it with the time left on it self->think = (func_t) SUB_Remove; } /* ============ StartItem Sets the clipping size and plants the object on the floor ============ */ void StartItem(void) { // G_bprint(2, "StartItem: %s\n", self->classname); self->mdl = self->model; // qqshka - save model ASAP self->s.v.nextthink = g_globalvars.time + 0.2; // items start after other solids self->think = (func_t) PlaceItem; } /* ========================================================================= HEALTH BOX ========================================================================= */ // // T_Heal: add health to an gedict_t*, limiting health to max_health // "ignore" will ignore max_health limit // float T_Heal(gedict_t *e, float healamount, float ignore) { float real_healamount; char *playername; if (ISDEAD(e)) { return 0; } if ((!ignore) && (e->s.v.health >= other->s.v.max_health)) { return 0; } real_healamount = e->s.v.health; // save health healamount = ceil(healamount); e->s.v.health = e->s.v.health + healamount; if ((!ignore) && (e->s.v.health >= other->s.v.max_health)) { e->s.v.health = other->s.v.max_health; } if (e->s.v.health > 250) { e->s.v.health = 250; } real_healamount = e->s.v.health - real_healamount; // so heal amount is current - old health playername = e->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, (int)healamount, cleantext(playername), (int)real_healamount ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\thealth_%d\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, (int)healamount, cleantext(playername), (int)real_healamount); return 1; } void health_touch(void); void item_megahealth_rot(void); /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth Health box. Normally gives 25 points. Rotten box heals 15 points, megahealth will add 100 health, then rot you down to your maximum health limit, one point per second. */ void SP_item_health(void) { self->touch = (func_t) health_touch; self->tp_flags = it_health; if ((int)self->s.v.spawnflags & H_ROTTEN) { setmodel(self, "maps/b_bh10.bsp"); self->noise = "items/r_item1.wav"; self->healamount = 15; self->healtype = 0; } else if ((int)self->s.v.spawnflags & H_MEGA) { setmodel(self, "maps/b_bh100.bsp"); self->noise = "items/r_item2.wav"; self->healamount = 100; self->healtype = 2; self->tp_flags = it_mh; } else { setmodel(self, "maps/b_bh25.bsp"); self->noise = "items/health1.wav"; self->healamount = 25; self->healtype = 1; } setsize(self, 0, 0, 0, 32, 32, 56); StartItem(); } void health_touch(void) { if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } if (ItemTouched(self, other)) { return; } if (deathmatch == 4) { if (other->invincible_time > 0) { return; } } if ((match_in_progress != 2) || !readytostart()) { return; } if (self->healtype == 2) // Megahealth? Ignore max_health... { if (other->s.v.health >= 250) { return; } if (!T_Heal(other, self->healamount, 1)) { return; } other->ps.itm[itHEALTH_100].tooks++; mi_print(other, IT_SUPERHEALTH, va("%s got Megahealth", getname(other))); } else { if (!T_Heal(other, self->healamount, 0)) { return; } switch ((int)self->healamount) { case 15: other->ps.itm[itHEALTH_15].tooks++; break; case 25: other->ps.itm[itHEALTH_25].tooks++; break; } } G_sprint(other, PRINT_LOW, "You receive %.0f health\n", self->healamount); // health touch sound sound(other, CHAN_ITEM, self->noise, 1, ATTN_NORM); stuffcmd(other, "bf\n"); self->model = ""; self->s.v.solid = SOLID_NOT; // Megahealth = rot down the player's super health if (self->healtype == 2) { other->s.v.items = (int)other->s.v.items | IT_SUPERHEALTH; if (deathmatch != 4) { self->s.v.nextthink = g_globalvars.time + 5; self->think = (func_t) item_megahealth_rot; stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx took %d %d %d\n", NUM_FOR_EDICT(self), 0, NUM_FOR_EDICT(other)); } self->s.v.owner = EDICT_TO_PROG(other); } else { if (deathmatch != 2) { // deathmatch 2 is the silly old rules self->s.v.nextthink = g_globalvars.time + 20; self->think = (func_t) SUB_regen; } } ItemTaken(self, other); activator = other; SUB_UseTargets(); // fire all targets / killtargets } void item_megahealth_rot(void) { other = PROG_TO_EDICT(self->s.v.owner); if (other->s.v.health > other->s.v.max_health) { if (!(other->ctf_flag & CTF_RUNE_RGN)) { other->s.v.health -= 1; } self->s.v.nextthink = g_globalvars.time + 1; #ifdef BOT_SUPPORT if (self->fb.item_affect) { self->fb.item_affect(self, other); } #endif return; } // it is possible for a player to die and respawn between rots, so don't // just blindly subtract the flag off other->s.v.items -= (int)other->s.v.items & IT_SUPERHEALTH; if (deathmatch != 2) // deathmatch 2 is silly old rules { self->s.v.nextthink = g_globalvars.time + 20; stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx timer %d %d\n", NUM_FOR_EDICT(self), 20); self->think = (func_t) SUB_regen; } #ifdef BOT_SUPPORT if (self->fb.item_affect) { self->fb.item_affect(self, other); } #endif } /* =============================================================================== ARMOR =============================================================================== */ void armor_touch(void) { float type = 0; float value = 0; float real_value = 0; int bit = 0; char *playername; itemName_t armorType = itNONE; if (ISDEAD(other)) { return; } if (lgc_enabled()) { return; } if (other->ct != ctPlayer) { return; } if (ItemTouched(self, other)) { return; } if ((match_in_progress != 2) || !readytostart()) { return; } if (deathmatch == 4) { if (other->invincible_time > 0) { return; } } if (!strcmp(self->classname, "item_armor1")) { armorType = itGA; type = (k_yawnmode ? 0.4 : 0.3); // Yawnmode: changed armor protection value = 100; bit = IT_ARMOR1; } else if (!strcmp(self->classname, "item_armor2")) { armorType = itYA; type = (k_yawnmode ? 0.6 : 0.6); // Yawnmode: changed armor protection value = 150; bit = IT_ARMOR2; } else if (!strcmp(self->classname, "item_armorInv")) { armorType = itRA; type = (k_yawnmode ? 0.8 : 0.8); // Yawnmode: changed armor protection value = 200; bit = IT_ARMOR3; } else { return; } // check if we have more armor than we trying to pick up. // We add 1.0e-6 so floaing point comparision is happy, // not all systems require it but on some this bugs in your face. if ((other->s.v.armortype * other->s.v.armorvalue + 1.0e-6) >= (type * value)) { return; } mi_print(other, bit, va("%s got %s", getname(other), self->netname)); if (armorType != itNONE) { adjust_pickup_time(&other->it_pickup_time[armorType], &other->ps.itm[armorType].time); other->it_pickup_time[armorType] = g_globalvars.time; other->ps.itm[armorType].tooks++; switch (armorType) { case itGA: adjust_pickup_time(&other->it_pickup_time[itYA], &other->ps.itm[itYA].time); adjust_pickup_time(&other->it_pickup_time[itRA], &other->ps.itm[itRA].time); break; case itYA: adjust_pickup_time(&other->it_pickup_time[itGA], &other->ps.itm[itGA].time); adjust_pickup_time(&other->it_pickup_time[itRA], &other->ps.itm[itRA].time); break; case itRA: adjust_pickup_time(&other->it_pickup_time[itGA], &other->ps.itm[itGA].time); adjust_pickup_time(&other->it_pickup_time[itYA], &other->ps.itm[itYA].time); break; default: break; } } real_value = other->s.v.armorvalue; other->s.v.armortype = type; other->s.v.armorvalue = value; other->s.v.items += -((int)other->s.v.items & ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit; self->s.v.solid = SOLID_NOT; self->model = ""; if (deathmatch != 2) { self->s.v.nextthink = g_globalvars.time + 20; stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx took %d %d %d\n", NUM_FOR_EDICT(self), 20, NUM_FOR_EDICT(other)); } self->think = (func_t) SUB_regen; real_value = value - real_value; playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), (int)real_value ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), (int)real_value); G_sprint(other, PRINT_LOW, "You got the %s\n", self->netname); // armor touch sound sound(other, CHAN_AUTO, "items/armor1.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); activator = other; SUB_UseTargets(); // fire all targets / killtargets ItemTaken(self, other); } /*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_item_armor1(void) { self->touch = (func_t) armor_touch; setmodel(self, "progs/armor.mdl"); self->netname = "Green Armor"; self->s.v.skin = 0; self->tp_flags = it_ga; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_item_armor2(void) { self->touch = (func_t) armor_touch; setmodel(self, "progs/armor.mdl"); self->netname = "Yellow Armor"; self->s.v.skin = 1; self->tp_flags = it_ya; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_item_armorInv(void) { self->touch = (func_t) armor_touch; setmodel(self, "progs/armor.mdl"); self->netname = "Red Armor"; self->s.v.skin = 2; self->tp_flags = it_ra; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /* =============================================================================== WEAPONS =============================================================================== */ void bound_other_ammo(void) { if (other->s.v.ammo_shells > 100) { other->s.v.ammo_shells = 100; } if (other->s.v.ammo_nails > 200) { other->s.v.ammo_nails = 200; } if (other->s.v.ammo_rockets > 100) { other->s.v.ammo_rockets = 100; } if (other->s.v.ammo_cells > 100) { other->s.v.ammo_cells = 100; } } float RankForWeapon(float w) { if (w == IT_LIGHTNING) { return 1; } if (w == IT_ROCKET_LAUNCHER) { return 2; } if (w == IT_SUPER_NAILGUN) { return 3; } if (w == IT_GRENADE_LAUNCHER) { return 4; } if (w == IT_SUPER_SHOTGUN) { return 5; } if (w == IT_NAILGUN) { return 6; } return 7; } float WeaponCode(float w) { if (w == IT_SHOTGUN) { return 2; } if (w == IT_SUPER_SHOTGUN) { return 3; } if (w == IT_NAILGUN) { return 4; } if (w == IT_SUPER_NAILGUN) { return 5; } if (w == IT_GRENADE_LAUNCHER) { return 6; } if (w == IT_ROCKET_LAUNCHER) { return 7; } if (w == IT_LIGHTNING) { return 8; } return 1; } /* ============= Deathmatch_Weapon Deathmatch weapon change rules for picking up a weapon .float ammo_shells, ammo_nails, ammo_rockets, ammo_cells; ============= */ void Deathmatch_Weapon(int new) { int or, nr; if ((self->s.v.weapon == IT_HOOK) && self->s.v.button0) { return; } // change self.weapon if desired or = RankForWeapon(self->s.v.weapon); nr = RankForWeapon(new); if (nr < or) { self->s.v.weapon = new; } } void DoWeaponChange(int new, qbool backpack) { int w_switch = iKey(self, backpack ? "b_switch" : "w_switch"); if (self->isBot) { return; } if (!w_switch) { if (iKey(self, "w_rank")) { w_switch = W_BestWeapon(); } else { w_switch = 8; } } if (WeaponCode(new) <= w_switch) { if (((int)(self->s.v.flags)) & FL_INWATER) { if (new != IT_LIGHTNING) { Deathmatch_Weapon(new); } } else { Deathmatch_Weapon(new); } } W_SetCurrentAmmo(); } /* ============= weapon_touch ============= */ float W_BestWeapon(void); void weapon_touch(void) { int hadammo = 0, new = 0; gedict_t *stemp; int leave; int real_ammo = 0; int k_freshteams = cvar("k_freshteams"); int limit_sweep_ammo = cvar("k_freshteams_limit_sweep_ammo"); int k_nosweep = cvar("k_nosweep"); int weapon_time = k_freshteams ? cvar("k_freshteams_weapon_time") : 30; char *playername; if (ISDEAD(other)) { return; } if (other->ct != ctPlayer) { return; } if (ItemTouched(self, other)) { return; } if ((match_in_progress != 2) || !readytostart()) { return; } if ((deathmatch == 2) || (deathmatch == 3) || (deathmatch == 5) || coop) { leave = 1; } else { leave = 0; } if (!strcmp(self->classname, "weapon_nailgun")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_NAILGUN)) { return; } hadammo = other->s.v.ammo_nails; new = IT_NAILGUN; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_NAILGUN)) { other->s.v.ammo_nails += cvar("k_freshteams_sweep_ng_ammo"); } else { other->s.v.ammo_nails += 30; } } else if (!strcmp(self->classname, "weapon_supernailgun")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_SUPER_NAILGUN)) { return; } hadammo = other->s.v.ammo_nails; new = IT_SUPER_NAILGUN; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_SUPER_NAILGUN)) { other->s.v.ammo_nails += cvar("k_freshteams_sweep_sng_ammo"); } else { other->s.v.ammo_nails += 30; } } else if (!strcmp(self->classname, "weapon_supershotgun")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_SUPER_SHOTGUN)) { return; } hadammo = other->s.v.ammo_shells; new = IT_SUPER_SHOTGUN; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_SUPER_SHOTGUN)) { other->s.v.ammo_shells += cvar("k_freshteams_sweep_ssg_ammo"); } else { other->s.v.ammo_shells += 5; } } else if (!strcmp(self->classname, "weapon_rocketlauncher")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_ROCKET_LAUNCHER)) { return; } hadammo = other->s.v.ammo_rockets; new = IT_ROCKET_LAUNCHER; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_ROCKET_LAUNCHER)) { other->s.v.ammo_rockets += cvar("k_freshteams_sweep_rl_ammo"); } else { other->s.v.ammo_rockets += 5; } if (!first_rl_taken) { extern void ktpro_autotrack_on_first_rl(gedict_t *dude); ktpro_autotrack_on_first_rl(other); first_rl_taken = true; } } else if (!strcmp(self->classname, "weapon_grenadelauncher")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_GRENADE_LAUNCHER)) { return; } hadammo = other->s.v.ammo_rockets; new = IT_GRENADE_LAUNCHER; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_GRENADE_LAUNCHER)) { other->s.v.ammo_rockets += cvar("k_freshteams_sweep_gl_ammo"); } else { other->s.v.ammo_rockets += 5; } } else if (!strcmp(self->classname, "weapon_lightning")) { if ((leave || k_nosweep) && ((int)other->s.v.items & IT_LIGHTNING)) { return; } hadammo = other->s.v.ammo_cells; new = IT_LIGHTNING; if (k_freshteams && limit_sweep_ammo && ((int)other->s.v.items & IT_LIGHTNING)) { other->s.v.ammo_cells += cvar("k_freshteams_sweep_lg_ammo"); } else { other->s.v.ammo_cells += 15; } } else { G_Error("weapon_touch: unknown classname"); } TookWeaponHandler(other, new, false); mi_print(other, new, va("%s got %s", getname(other), self->netname)); G_sprint(other, PRINT_LOW, "You got the %s\n", self->netname); // weapon touch sound sound(other, CHAN_AUTO, "weapons/pkup.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); bound_other_ammo(); if (!strcmp(self->classname, "weapon_nailgun")) { real_ammo = other->s.v.ammo_nails - hadammo; } else if (!strcmp(self->classname, "weapon_supernailgun")) { real_ammo = other->s.v.ammo_nails - hadammo; } else if (!strcmp(self->classname, "weapon_supershotgun")) { real_ammo = other->s.v.ammo_shells - hadammo; } else if (!strcmp(self->classname, "weapon_rocketlauncher")) { real_ammo = other->s.v.ammo_rockets - hadammo; } else if (!strcmp(self->classname, "weapon_grenadelauncher")) { real_ammo = other->s.v.ammo_rockets - hadammo; } else if (!strcmp(self->classname, "weapon_lightning")) { real_ammo = other->s.v.ammo_cells - hadammo; } playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), real_ammo ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), real_ammo); // change to the weapon other->s.v.items = (int)other->s.v.items | new; stemp = self; self = other; DoWeaponChange(new, false); // change to the weapon self = stemp; // If dmm2 or dmm3 or dmm5 or coop. if (leave) { ItemTaken(self, other); return; } // remove it in single player, or setup for respawning in deathmatch self->model = ""; self->s.v.solid = SOLID_NOT; // At this point it is either dmm0 (singleplayer) or dmm1 or perhaps dmm4 (if for some reason weapon was not removed at match start), // we still try to use SUB_regen and do final decision there if we should regen item. if (deathmatch != 2) { self->s.v.nextthink = g_globalvars.time + weapon_time; stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx took %d %d %d\n", NUM_FOR_EDICT(self), weapon_time, NUM_FOR_EDICT(other)); } self->think = (func_t) SUB_regen; activator = other; SUB_UseTargets(); // fire all targets / killtargets ItemTaken(self, other); } /*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_supershotgun(void) { setmodel(self, "progs/g_shot.mdl"); self->s.v.weapon = IT_SUPER_SHOTGUN; self->netname = "Double-barrelled Shotgun"; self->touch = (func_t) weapon_touch; self->tp_flags = it_ssg; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_nailgun(void) { setmodel(self, "progs/g_nail.mdl"); self->s.v.weapon = IT_NAILGUN; self->netname = "nailgun"; self->touch = (func_t) weapon_touch; self->tp_flags = it_ng; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_supernailgun(void) { setmodel(self, "progs/g_nail2.mdl"); self->s.v.weapon = IT_SUPER_NAILGUN; self->netname = "Super Nailgun"; self->touch = (func_t) weapon_touch; self->tp_flags = it_sng; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_grenadelauncher(void) { setmodel(self, "progs/g_rock.mdl"); self->s.v.weapon = 3; self->netname = "Grenade Launcher"; self->touch = (func_t) weapon_touch; self->tp_flags = it_gl; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_rocketlauncher(void) { setmodel(self, "progs/g_rock2.mdl"); self->s.v.weapon = 3; self->netname = "Rocket Launcher"; self->touch = (func_t) weapon_touch; self->tp_flags = it_rl; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32) */ void SP_weapon_lightning(void) { setmodel(self, "progs/g_light.mdl"); self->s.v.weapon = 3; self->netname = "Thunderbolt"; self->touch = (func_t) weapon_touch; self->tp_flags = it_lg; setsize(self, -16, -16, 0, 16, 16, 56); StartItem(); } /* =============================================================================== AMMO =============================================================================== */ void ammo_touch(void) { int ammo, weapon, best; int real_ammo = 0; qbool freshteams_fast_ammo = (cvar("k_freshteams") && cvar("k_freshteams_fast_ammo")); gedict_t *stemp; char *playername; if (ISDEAD(other)) { return; } if (other->ct != ctPlayer) { return; } if (ItemTouched(self, other)) { return; } if ((match_in_progress != 2) || !readytostart()) { return; } // if the player was using his best weapon, change up to the new one if better stemp = self; self = other; best = W_BestWeapon(); // save best weapon before update ammo self = stemp; ammo = self->aflag; weapon = self->s.v.weapon; if (weapon == 1) // shotgun { if (other->s.v.ammo_shells >= 100) { return; } real_ammo = other->s.v.ammo_shells; other->s.v.ammo_shells += ammo; } else if (weapon == 2) // spikes { if (other->s.v.ammo_nails >= 200) { return; } real_ammo = other->s.v.ammo_nails; other->s.v.ammo_nails += ammo; } else if (weapon == 3) // rockets { if (other->s.v.ammo_rockets >= 100) { return; } real_ammo = other->s.v.ammo_rockets; other->s.v.ammo_rockets += ammo; } else if (weapon == 4) // cells { if (other->s.v.ammo_cells >= 100) { return; } real_ammo = other->s.v.ammo_cells; other->s.v.ammo_cells += ammo; } bound_other_ammo(); if (weapon == 1) { real_ammo = other->s.v.ammo_shells - real_ammo; } else if (weapon == 2) { real_ammo = other->s.v.ammo_nails - real_ammo; } else if (weapon == 3) { real_ammo = other->s.v.ammo_rockets - real_ammo; } else if (weapon == 4) { real_ammo = other->s.v.ammo_cells - real_ammo; } playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), real_ammo ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), real_ammo); G_sprint(other, PRINT_LOW, "You got the %s\n", self->netname); // ammo touch sound sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); // change to a better weapon if appropriate // before we got ammo we use best weapon - best weapon may change due to ammo, so check this if (other->s.v.weapon == best) { stemp = self; self = other; DoWeaponChange(W_BestWeapon(), false); // change to the weapon self = stemp; } // if changed current ammo, update it stemp = self; self = other; W_SetCurrentAmmo(); self = stemp; // remove it in single player, or setup for respawning in deathmatch self->model = ""; self->s.v.solid = SOLID_NOT; if (deathmatch != 2) { self->s.v.nextthink = g_globalvars.time + 30; } // Xian -- If playing in DM 3.0 mode, halve the time ammo respawns if ((deathmatch == 3) || (deathmatch == 5)) { self->s.v.nextthink = g_globalvars.time + 15; } // If playing freshteams and fast_ammo is enabled, set ammo respawn time same as weapons if (freshteams_fast_ammo) { self->s.v.nextthink = g_globalvars.time + cvar("k_freshteams_weapon_time"); } self->think = (func_t) SUB_regen; ItemTaken(self, other); activator = other; SUB_UseTargets(); // fire all targets / killtargets } #define WEAPON_BIG2 1 /*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big */ void SP_item_shells(void) { self->touch = (func_t) ammo_touch; if ((int)(self->s.v.spawnflags) & WEAPON_BIG2) { setmodel(self, "maps/b_shell1.bsp"); self->aflag = 40; } else { setmodel(self, "maps/b_shell0.bsp"); self->aflag = 20; } self->s.v.weapon = 1; self->netname = "shells"; self->classname = "item_shells"; self->tp_flags = it_shells; setsize(self, 0, 0, 0, 32, 32, 56); StartItem(); } /*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big */ void SP_item_spikes(void) { qbool old_style = streq(self->classname, "item_weapon"); self->touch = (func_t) ammo_touch; if ((int)(self->s.v.spawnflags) & WEAPON_BIG2) { setmodel(self, "maps/b_nail1.bsp"); self->aflag = (old_style ? 40 : 50); } else { setmodel(self, "maps/b_nail0.bsp"); self->aflag = (old_style ? 20 : 25); } self->s.v.weapon = 2; self->netname = (old_style ? "spikes" : "nails"); // hehe, different message when u pick different nails ammo self->classname = "item_spikes"; self->tp_flags = it_nails; setsize(self, 0, 0, 0, 32, 32, 56); StartItem(); } /*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big */ void SP_item_rockets(void) { self->touch = (func_t) ammo_touch; if ((int)(self->s.v.spawnflags) & WEAPON_BIG2) { setmodel(self, "maps/b_rock1.bsp"); self->aflag = 10; } else { setmodel(self, "maps/b_rock0.bsp"); self->aflag = 5; } self->s.v.weapon = 3; self->netname = "rockets"; self->classname = "item_rockets"; self->tp_flags = it_rockets; setsize(self, 0, 0, 0, 32, 32, 56); StartItem(); } /*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big */ void SP_item_cells(void) { self->touch = (func_t) ammo_touch; if ((int)(self->s.v.spawnflags) & WEAPON_BIG2) { setmodel(self, "maps/b_batt1.bsp"); self->aflag = 12; } else { setmodel(self, "maps/b_batt0.bsp"); self->aflag = 6; } self->s.v.weapon = 4; self->netname = "cells"; self->classname = "item_cells"; self->tp_flags = it_cells; setsize(self, 0, 0, 0, 32, 32, 56); StartItem(); } /*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big DO NOT USE THIS!!!! IT WILL BE REMOVED! */ #define WEAPON_SHOTGUN 1 #define WEAPON_ROCKET 2 #define WEAPON_SPIKES 4 #define WEAPON_BIG 8 void SP_item_weapon(void) { if ((int)(self->s.v.spawnflags) & WEAPON_SHOTGUN) { self->s.v.spawnflags = (((int)(self->s.v.spawnflags) & WEAPON_BIG) ? WEAPON_BIG2 : 0); SP_item_shells(); return; } if ((int)(self->s.v.spawnflags) & WEAPON_SPIKES) { self->s.v.spawnflags = (((int)(self->s.v.spawnflags) & WEAPON_BIG) ? WEAPON_BIG2 : 0); SP_item_spikes(); return; } if ((int)(self->s.v.spawnflags) & WEAPON_ROCKET) { self->s.v.spawnflags = (((int)(self->s.v.spawnflags) & WEAPON_BIG) ? WEAPON_BIG2 : 0); SP_item_rockets(); return; } SUB_Remove(); // was unknown item, remove it } /* =============================================================================== KEYS =============================================================================== */ void key_touch(void) { //gedict_t* stemp; //float best; char *playername; if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } if ((int)other->s.v.items & (int)self->s.v.items) { return; } if ((match_in_progress != 2) || !readytostart()) { return; } playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), 0 ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), 0); G_sprint(other, PRINT_LOW, "You got the %s\n", self->netname); sound(other, CHAN_ITEM, self->noise, 1, ATTN_NORM); stuffcmd(other, "bf\n"); other->s.v.items = (int)other->s.v.items | (int)self->s.v.items; if (!coop) { self->s.v.solid = SOLID_NOT; self->model = ""; } activator = other; SUB_UseTargets(); // fire all targets / killtargets } void key_setsounds(void) { if (world->worldtype == 0) { trap_precache_sound("misc/medkey.wav"); self->noise = "misc/medkey.wav"; } if (world->worldtype == 1) { trap_precache_sound("misc/runekey.wav"); self->noise = "misc/runekey.wav"; } if (world->worldtype == 2) { trap_precache_sound("misc/basekey.wav"); self->noise = "misc/basekey.wav"; } } /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) SILVER key In order for keys to work you MUST set your maps worldtype to one of the following: 0: medieval 1: metal 2: base */ void SP_item_key1(void) { if (world->worldtype == 0) { trap_precache_model("progs/w_s_key.mdl"); setmodel(self, "progs/w_s_key.mdl"); self->netname = "silver key"; } else if (world->worldtype == 1) { trap_precache_model("progs/m_s_key.mdl"); setmodel(self, "progs/m_s_key.mdl"); self->netname = "silver runekey"; } else if (world->worldtype == 2) { trap_precache_model("progs/b_s_key.mdl"); setmodel(self, "progs/b_s_key.mdl"); self->netname = "silver keycard"; } key_setsounds(); self->touch = (func_t) key_touch; self->s.v.items = IT_KEY1; setsize(self, -16, -16, -24, 16, 16, 32); StartItem(); } /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) GOLD key In order for keys to work you MUST set your maps worldtype to one of the following: 0: medieval 1: metal 2: base */ void SP_item_key2(void) { if (world->worldtype == 0) { trap_precache_model("progs/w_g_key.mdl"); setmodel(self, "progs/w_g_key.mdl"); self->netname = "gold key"; } if (world->worldtype == 1) { trap_precache_model("progs/m_g_key.mdl"); setmodel(self, "progs/m_g_key.mdl"); self->netname = "gold runekey"; } if (world->worldtype == 2) { trap_precache_model("progs/b_g_key.mdl"); setmodel(self, "progs/b_g_key.mdl"); self->netname = "gold keycard"; } key_setsounds(); self->touch = (func_t) key_touch; self->s.v.items = IT_KEY2; setsize(self, -16, -16, -24, 16, 16, 32); StartItem(); } /* =============================================================================== END OF LEVEL RUNES =============================================================================== */ void sigil_touch(void) { //gedict_t* stemp; //float best; char *playername; if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } if ((match_in_progress != 2) || !readytostart()) { return; } playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), 0 ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), 0); G_centerprint(other, "You got the rune!"); sound(other, CHAN_ITEM, self->noise, 1, ATTN_NORM); stuffcmd(other, "bf\n"); self->s.v.solid = SOLID_NOT; self->model = ""; g_globalvars.serverflags = (int)(g_globalvars.serverflags) | ((int)(self->s.v.spawnflags) & 15); self->classname = ""; // so rune doors won't find it activator = other; SUB_UseTargets(); // fire all targets / killtargets } /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4 End of level sigil, pick up to end episode and return to jrstart. */ void SP_item_sigil(void) { if (!(int)(self->s.v.spawnflags)) { G_Error("item_sigil no spawnflags"); } trap_precache_sound("misc/runekey.wav"); self->noise = "misc/runekey.wav"; if ((int)(self->s.v.spawnflags) & 1) { trap_precache_model("progs/end1.mdl"); setmodel(self, "progs/end1.mdl"); } if ((int)(self->s.v.spawnflags) & 2) { trap_precache_model("progs/end2.mdl"); setmodel(self, "progs/end2.mdl"); } if ((int)(self->s.v.spawnflags) & 4) { trap_precache_model("progs/end3.mdl"); setmodel(self, "progs/end3.mdl"); } if ((int)(self->s.v.spawnflags) & 8) { trap_precache_model("progs/end4.mdl"); setmodel(self, "progs/end4.mdl"); } self->touch = (func_t) sigil_touch; setsize(self, -16, -16, -24, 16, 16, 32); StartItem(); self->tp_flags = it_rune1; } /* =============================================================================== POWERUPS =============================================================================== */ void ktpro_autotrack_on_powerup_take(gedict_t *dude); void adjust_pickup_time(float *current, float *total) { if (!current || !*current || !total) { return; } *total += (g_globalvars.time - *current); *current = 0; } void hide_powerups(char *classname) { gedict_t *p; if (strnull(classname)) { G_Error("hide_items"); } for (p = world; (p = find(p, FOFCLSN, classname));) { // simply remove dropable powerups if (p->cnt) { ent_remove(p); continue; } p->s.v.solid = SOLID_NOT; p->model = ""; p->s.v.nextthink = 0; // disable next think } } void show_powerups(char *classname) { gedict_t *p; if (strnull(classname)) { G_Error("show_items"); } for (p = world; (p = find(p, FOFCLSN, classname));) { // spawn item if needed if (strnull(p->model) || (p->s.v.solid != SOLID_TRIGGER)) { if (match_in_progress == 2) { // spawn item in 30 seconds if game already running p->s.v.nextthink = g_globalvars.time + 30; p->s.v.nextthink -= AUTOTRACK_POWERUPS_PREDICT_TIME; p->think = (func_t) SUB_regen_powerups; } else { // spawn item instantly if game is not running p->s.v.nextthink = g_globalvars.time; p->think = (func_t) SUB_regen; } } } } static void KillQuadThink(void) { ent_remove(self); } void DropPowerup(float timeleft, int powerup) { gedict_t *swp = self; // save self char *playername; if ((timeleft <= 0) || (match_in_progress != 2)) { return; } if ((powerup != IT_QUAD) && (powerup != IT_INVISIBILITY) && (powerup != IT_INVULNERABILITY)) // only this supported { return; } self = spawn(); // WARNING! setorigin(self, PASSVEC3(swp->s.v.origin)); self->cnt = g_globalvars.time + timeleft; if (powerup == IT_QUAD) { SP_item_artifact_super_damage(); if (k_killquad) { self->s.v.nextthink = g_globalvars.time + 10; self->think = (func_t) KillQuadThink; // ATM just remove self. } } else if (powerup == IT_INVISIBILITY) { SP_item_artifact_invisibility(); } else if (powerup == IT_INVULNERABILITY) { SP_item_artifact_invulnerability(); } else { G_Error("DropPowerup"); } if (k_bloodfest) { // limit amount of dropped powerups of particular class. if (find_cnt( FOFCLSN, self->classname) > 3) { ent_remove(self); self = swp; // restore self!!! return; } } playername = swp->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%f\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), timeleft); if (swp->ct == ctPlayer) { mi_print( swp, powerup, va("%s dropped a %s with %.0f seconds left", swp->netname, self->netname, timeleft)); } #ifdef BOT_SUPPORT BotsPowerupDropped(swp, self); #endif self = swp; // restore self!!! } static qbool NeedDropQuad(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { if (ISDEAD(p)) { continue; // ignore dead } if (p->super_damage_finished > 0) { return false; // one have quad, so we do not need drop new. } } return !ez_find(world, "item_artifact_super_damage"); } void DropPowerups(void) { if ((k_killquad || (cvar("dq") && Get_Powerups() && cvar("k_pow_q"))) && !k_berzerk) { if (k_killquad) { if (NeedDropQuad()) { DropPowerup(666, IT_QUAD); } } else if (self->super_damage_finished > 0) { DropPowerup(self->super_damage_finished - g_globalvars.time, IT_QUAD); } } if (cvar("dr") && Get_Powerups() && cvar("k_pow_r")) { if (self->invisible_finished > 0) { DropPowerup(self->invisible_finished - g_globalvars.time, IT_INVISIBILITY); } } } void powerup_touch(void) { float *p_cnt = NULL; float real_time = 30; float old_pu_time = 0; char *playername; if (strnull(self->classname)) { G_Error("powerup_touch: null classname"); } if (other->ct != ctPlayer) { #ifdef BOT_SUPPORT BotsPowerupTouchedNonPlayer(self, other); #endif return; } if (ISDEAD(other)) { return; } if (ItemTouched(self, other)) { return; } if (!k_practice) // #practice mode# { if ((match_in_progress != 2) || !readytostart()) { return; } } if (!Get_Powerups() || (((int)self->s.v.items & IT_INVISIBILITY) && !cvar("k_pow_r")) || (((int)self->s.v.items & IT_INVULNERABILITY) && !cvar("k_pow_p")) || (((int)self->s.v.items & IT_SUIT) && !cvar("k_pow_s")) || (((int)self->s.v.items & IT_QUAD) && !cvar("k_pow_q"))) { return; } // if "fair" powerups pickup is activated, don't allow one to pickup // powerup if he already has one of the same kind (ie 2 quads) if (cvar("k_pow_pickup")) { if (streq(self->classname, "item_artifact_envirosuit") && other->radsuit_finished > g_globalvars.time) { return; } if (streq(self->classname, "item_artifact_invulnerability") && other->invincible_finished > g_globalvars.time) { return; } if (streq(self->classname, "item_artifact_invisibility") && other->invisible_finished > g_globalvars.time) { return; } if (streq(self->classname, "item_artifact_super_damage") && other->super_damage_finished > g_globalvars.time) { return; } } G_sprint(other, PRINT_LOW, "You got the %s\n", self->netname); self->mdl = self->model; if (streq(self->classname, "item_artifact_invulnerability") || streq(self->classname, "item_artifact_invisibility")) { self->s.v.nextthink = g_globalvars.time + 60 * 5; if (isHoonyModeTDM()) { // 5 minute rounds => respawn at 3 minutes // 10 minute rounds => respawn at 4 minutes // otherwise => default if (HM_timelimit() <= 300) { self->s.v.nextthink = g_globalvars.time + 60 * 3; } else if (HM_timelimit() <= 600) { self->s.v.nextthink = g_globalvars.time + 60 * 4; } } if (!k_practice) { stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx took %d %d %d\n", NUM_FOR_EDICT(self), 300, NUM_FOR_EDICT(other)); } } else { self->s.v.nextthink = g_globalvars.time + 60; if (!k_practice) { stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx took %d %d %d\n", NUM_FOR_EDICT(self), 60, NUM_FOR_EDICT(other)); } } // all powerups respawn after 30 seconds in practice mode if (k_practice) // #practice mode# { self->s.v.nextthink = g_globalvars.time + 30; } self->s.v.nextthink -= AUTOTRACK_POWERUPS_PREDICT_TIME; self->think = (func_t) SUB_regen_powerups; // like ktpro // sound( other, CHAN_VOICE, self->noise, 1, ATTN_NORM ); sound(other, CHAN_ITEM, self->noise, 1, ATTN_NORM); stuffcmd(other, "bf\n"); self->s.v.solid = SOLID_NOT; setorigin(self, PASSVEC3(self->s.v.origin)); other->s.v.items = ((int)other->s.v.items) | ((int)self->s.v.items); self->model = ""; // do the apropriate action if (streq(self->classname, "item_artifact_envirosuit")) { old_pu_time = other->radsuit_finished; other->rad_time = 1; other->radsuit_finished = g_globalvars.time + 30; if (self->cnt > g_globalvars.time) // is this was a dropped powerup { p_cnt = &(other->radsuit_finished); } } else if (streq(self->classname, "item_artifact_invulnerability")) { old_pu_time = other->invincible_finished; adjust_pickup_time(&other->it_pickup_time[itPENT], &other->ps.itm[itPENT].time); other->it_pickup_time[itPENT] = g_globalvars.time; other->ps.itm[itPENT].tooks++; other->invincible_time = 1; other->invincible_finished = g_globalvars.time + 30; if (self->cnt > g_globalvars.time) // is this was a dropped powerup { p_cnt = &(other->invincible_finished); } } else if (streq(self->classname, "item_artifact_invisibility")) { old_pu_time = other->invisible_finished; adjust_pickup_time(&other->it_pickup_time[itRING], &other->ps.itm[itRING].time); other->it_pickup_time[itRING] = g_globalvars.time; other->ps.itm[itRING].tooks++; other->invisible_time = 1; other->invisible_finished = g_globalvars.time + 30; if (self->cnt > g_globalvars.time) // is this was a dropped powerup { p_cnt = &(other->invisible_finished); } } else if (streq(self->classname, "item_artifact_super_damage")) { old_pu_time = other->super_damage_finished; adjust_pickup_time(&other->it_pickup_time[itQUAD], &other->ps.itm[itQUAD].time); other->it_pickup_time[itQUAD] = g_globalvars.time; other->ps.itm[itQUAD].tooks++; other->ps.spree_max_q = max(other->ps.spree_current_q, other->ps.spree_max_q); other->ps.spree_current_q = 0; if (deathmatch == 4 && !tot_mode_enabled()) { other->s.v.armortype = 0; other->s.v.armorvalue = 0; other->s.v.ammo_cells = 0; } other->super_time = 1; other->super_damage_finished = g_globalvars.time + 30; if (self->cnt > g_globalvars.time) // is this was a dropped powerup { p_cnt = &(other->super_damage_finished); } } else { return; } if (p_cnt) // is this was a dropped powerup { float seconds_left = self->cnt - g_globalvars.time; // seconds left on quad. // sum up seconds player alredy have and seconds on quad left. p_cnt[0] = max(g_globalvars.time, old_pu_time) + seconds_left; // do not allow more than 30 seconds of quad anyway. p_cnt[0] = min(g_globalvars.time + 30, p_cnt[0]); seconds_left = p_cnt[0] - g_globalvars.time; real_time = seconds_left; // if ( k_bloodfest ) // G_sprint( other, 2, "Your %s have %d seconds left\n", self->netname, ( int )seconds_left ); mi_print( other, self->s.v.items, va("%s got a %s with %d seconds left", other->netname, self->netname, (int)seconds_left)); SUB_RM_01(self); // remove later } else { mi_print(other, self->s.v.items, va("%s got %s", getname(other), self->netname)); } playername = other->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%s\n" "\t\t\t\t%f\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, self->classname, cleantext(playername), real_time); ktpro_autotrack_on_powerup_take(other); ItemTaken(self, other); activator = other; SUB_UseTargets(); // fire all targets / killtargets } /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32) Player is invulnerable for 30 seconds */ void SP_item_artifact_invulnerability(void) { qbool b_dp = self->cnt > g_globalvars.time; // dropped powerup by player, not normal spawn self->touch = (func_t) powerup_touch; self->noise = "items/protect.wav"; setmodel(self, "progs/invulner.mdl"); self->netname = "Pentagram of Protection"; self->classname = "item_artifact_invulnerability"; self->s.v.effects = (int)self->s.v.effects | EF_RED; self->s.v.items = IT_INVULNERABILITY; self->tp_flags = it_pent; setsize(self, -16, -16, -24, 16, 16, 32); if (b_dp) { PlaceItemIngame(); } else { StartItem(); } } /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32) Player takes no damage from water or slime for 30 seconds */ void SP_item_artifact_envirosuit(void) { self->touch = (func_t) powerup_touch; self->noise = "items/suit.wav"; setmodel(self, "progs/suit.mdl"); self->netname = "Biosuit"; self->classname = "item_artifact_envirosuit"; self->s.v.effects = (int)self->s.v.effects | EF_GREEN; self->s.v.items = IT_SUIT; self->tp_flags = it_suit; setsize(self, -16, -16, -24, 16, 16, 32); StartItem(); } /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32) Player is invisible for 30 seconds */ void SP_item_artifact_invisibility(void) { qbool b_dp = self->cnt > g_globalvars.time; // dropped powerup by player, not normal spawn self->touch = (func_t) powerup_touch; self->noise = "items/inv1.wav"; setmodel(self, "progs/invisibl.mdl"); self->netname = "Ring of Shadows"; self->classname = "item_artifact_invisibility"; self->s.v.items = IT_INVISIBILITY; self->tp_flags = it_ring; setsize(self, -16, -16, -24, 16, 16, 32); if (b_dp) { PlaceItemIngame(); } else { StartItem(); } } /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32) The next attack from the player will do 4x damage */ void SP_item_artifact_super_damage(void) { qbool b_dp = self->cnt > g_globalvars.time; // dropped powerup by player, not normal spawn self->touch = (func_t) powerup_touch; self->noise = "items/damage.wav"; setmodel(self, "progs/quaddama.mdl"); self->classname = "item_artifact_super_damage"; self->netname = deathmatch == 4 ? "OctaPower" : "Quad Damage"; self->s.v.items = IT_QUAD; self->tp_flags = it_quad; self->s.v.effects = (int)self->s.v.effects | EF_BLUE; setsize(self, -16, -16, -24, 16, 16, 32); if (b_dp) { PlaceItemIngame(); } else { StartItem(); } } /* =============================================================================== PLAYER BACKPACKS =============================================================================== */ void BackpackTouch(void) { int new; gedict_t *stemp, *p; float acount, new_shells, new_nails, new_rockets, new_cells; char *new_wp = ""; char *playername; if (other->ct != ctPlayer) { #ifdef BOT_SUPPORT BotsBackpackTouchedNonPlayer(self, other); #endif return; } if (ISDEAD(other)) { return; } if (ItemTouched(self, other)) { return; } if (match_in_progress != 2) { return; } if (deathmatch == 4) { if (other->invincible_finished) { return; // we have pent, ignore pack } } //crt -- no backpacks in waiting area if (isRA() && !isWinner(other) && !isLoser(other)) { return; } if (cvar("k_midair") && other->super_damage_finished) { return; // we have quad, ignore pack } if (cvar("k_instagib") && other->invisible_finished) { return; // we have ring, ignore pack } if ((deathmatch == 4) && lgc_enabled() && (other->s.v.health >= 300)) { return; // don't allow bonus powers, leave pack hanging around } acount = 0; G_sprint(other, PRINT_LOW, "You get "); if (deathmatch == 4) { other->s.v.health += 10; G_sprint(other, PRINT_LOW, "10 additional health\n"); if ((other->s.v.health > 250) && (other->s.v.health < 300)) { sound(other, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM); } else { sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM); } stuffcmd(other, "bf\n"); if ((lgc_enabled() || tot_mode_enabled()) && (other->s.v.health > 299)) { // cap & don't allow bonus powers other->s.v.health = 300; } else if (other->s.v.health > 299) { if (cvar("k_instagib")) { other->invisible_time = 1; other->invisible_finished = g_globalvars.time + 30; other->s.v.items = (int)other->s.v.items | IT_INVISIBILITY; } else { if (!cvar("k_midair")) { other->invincible_time = 1; other->invincible_finished = g_globalvars.time + 30; other->s.v.items = (int)other->s.v.items | IT_INVULNERABILITY; } other->super_time = 1; other->super_damage_finished = g_globalvars.time + 30; other->s.v.items = (int)other->s.v.items | IT_QUAD; other->ps.mid_bonus++; } other->s.v.ammo_cells = 0; sound(other, CHAN_AUTO, "boss1/sight1.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); ktpro_autotrack_on_powerup_take(other); G_bprint( PRINT_HIGH, "%s gained bonus powers!!!\n", other->netname); other->ps.i_rings++; } ent_remove(self); return; } new = self->s.v.items; if (new) { if ((new & IT_ROCKET_LAUNCHER) || (new & IT_LIGHTNING)) { stuffcmd_flags(other, STUFFCMD_DEMOONLY, "//ktx bp %d %d\n", NUM_FOR_EDICT(self), NUM_FOR_EDICT(other)); } TookWeaponHandler(other, new, true); if (!((int)other->s.v.items & new)) { // new weapon - so print u got it acount = 1; G_sprint(other, PRINT_LOW, "the %s", self->netname); new_wp = self->netname; // FIXME: so specs does't seen this message if player alredy have such weapon, is this BUG? mi_print(other, new, va("%s got backpack with %s", getname(other), self->netname)); } } // change weapons new_shells = other->s.v.ammo_shells; new_nails = other->s.v.ammo_nails; new_rockets = other->s.v.ammo_rockets; new_cells = other->s.v.ammo_cells; other->s.v.ammo_shells = other->s.v.ammo_shells + self->s.v.ammo_shells; other->s.v.ammo_nails = other->s.v.ammo_nails + self->s.v.ammo_nails; other->s.v.ammo_rockets = other->s.v.ammo_rockets + self->s.v.ammo_rockets; other->s.v.ammo_cells = other->s.v.ammo_cells + self->s.v.ammo_cells; other->s.v.items = (int)other->s.v.items | new; bound_other_ammo(); new_shells = other->s.v.ammo_shells - new_shells; new_nails = other->s.v.ammo_nails - new_nails; new_rockets = other->s.v.ammo_rockets - new_rockets; new_cells = other->s.v.ammo_cells - new_cells; playername = other->netname; /* log_printf( "\t\t\t\n", g_globalvars.time - match_start_time, new_wp, (int)self->s.v.ammo_shells, (int)self->s.v.ammo_nails, (int)self->s.v.ammo_rockets, (int)self->s.v.ammo_cells, cleantext(playername) ); */ log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%s\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, new_wp, (int)self->s.v.ammo_shells, (int)self->s.v.ammo_nails, (int)self->s.v.ammo_rockets, (int)self->s.v.ammo_cells, cleantext(playername)); if (self->s.v.ammo_shells) { if (acount) { G_sprint(other, PRINT_LOW, ", "); } acount = 1; G_sprint(other, PRINT_LOW, "%.0f shells", self->s.v.ammo_shells); } if (self->s.v.ammo_nails) { if (acount) { G_sprint(other, PRINT_LOW, ", "); } acount = 1; G_sprint(other, PRINT_LOW, "%.0f nails", self->s.v.ammo_nails); } if (self->s.v.ammo_rockets) { if (acount) { G_sprint(other, PRINT_LOW, ", "); } acount = 1; G_sprint(other, PRINT_LOW, "%.0f rockets", self->s.v.ammo_rockets); } if (self->s.v.ammo_cells) { if (acount) { G_sprint(other, PRINT_LOW, ", "); } acount = 1; G_sprint(other, PRINT_LOW, "%.0f cells", self->s.v.ammo_cells); } if (((deathmatch == 3) || (deathmatch == 5)) && ((WeaponCode(new) == 6) || (WeaponCode(new) == 7)) && (other->s.v.ammo_rockets < 5)) { other->s.v.ammo_rockets = 5; } // detect transferred RL packs, credit the player who dropped the pack with the transfer if (isTeam() && (self->s.v.items == IT_ROCKET_LAUNCHER)) { if (streq(self->backpack_team_name, getteam(other))) { for (p = world; (p = find_plr(p));) { if (streq(getname(p), self->backpack_player_name)) { p->ps.transferred_RLpacks++; break; } } } } // detect transferred LG packs, credit the player who dropped the pack with the transfer if (isTeam() && (self->s.v.items == IT_LIGHTNING)) { if (streq(self->backpack_team_name, getteam(other))) { for (p = world; (p = find_plr(p));) { if (streq(getname(p), self->backpack_player_name)) { p->ps.transferred_LGpacks++; break; } } } } G_sprint(other, PRINT_LOW, "\n"); // backpack touch sound sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); ItemTaken(self, other); ent_remove(self); stemp = self; self = other; DoWeaponChange(new, true); // change to the weapon self = stemp; } /* =============== DropBackpack =============== */ #define IT_DROPPABLE_WEAPONS (IT_SUPER_SHOTGUN|IT_NAILGUN|IT_SUPER_NAILGUN|IT_GRENADE_LAUNCHER|IT_ROCKET_LAUNCHER|IT_LIGHTNING) void DropBackpack(void) { gedict_t *item; float f1; char *playername; qbool fresh_packs = (cvar("k_freshteams") && cvar("k_freshteams_limit_packs")); if (k_bloodfest) { return; } f1 = get_fair_pack(); if ((match_in_progress != 2) || !cvar("dp")) { return; } if (!k_yawnmode) // Yawnmode: pack dropped in yawn mode independantly from death type { if (dtSUICIDE == self->deathtype) { return; } } if (!(self->s.v.ammo_shells + self->s.v.ammo_nails + self->s.v.ammo_rockets + self->s.v.ammo_cells) && !((int)self->s.v.weapon & IT_DROPPABLE_WEAPONS) && !(f1 == 2 && ((int)self->lastwepfired & IT_DROPPABLE_WEAPONS))) { return; // nothing in it } item = spawn(); VectorCopy(self->s.v.origin, item->s.v.origin); item->s.v.origin[2] -= 24; item->s.v.items = self->s.v.weapon; item->tp_flags = it_pack; // drop best weapon in case of fairpacks 1 (KTEAMS) if (f1 == 1) { if (((int)self->s.v.items & IT_NAILGUN) && self->s.v.ammo_nails > 0) { item->s.v.items = IT_NAILGUN; } if (((int)self->s.v.items & IT_SUPER_SHOTGUN) && self->s.v.ammo_shells > 0) { item->s.v.items = IT_SUPER_SHOTGUN; } if (((int)self->s.v.items & IT_SUPER_NAILGUN) && self->s.v.ammo_nails > 0) { item->s.v.items = IT_SUPER_NAILGUN; } if (((int)self->s.v.items & IT_GRENADE_LAUNCHER) && self->s.v.ammo_rockets > 0) { item->s.v.items = IT_GRENADE_LAUNCHER; } if (((int)self->s.v.items & IT_LIGHTNING) && self->s.v.ammo_cells > 0) { item->s.v.items = IT_LIGHTNING; } if (((int)self->s.v.items & IT_ROCKET_LAUNCHER) && self->s.v.ammo_rockets > 0) { item->s.v.items = IT_ROCKET_LAUNCHER; } } // drop lastfired even if no ammo in case of fairpacks 2 (KTEAMS) if (f1 == 2) { if ((int)self->lastwepfired & IT_DROPPABLE_WEAPONS) { item->s.v.items = self->lastwepfired; } } // Yawnmode: unfairpacks in DMM1, only drop current weapon if the player was shooting (idea from Tonik) // - Molgrum if (k_yawnmode && (deathmatch == 1) && (self->attack_finished < g_globalvars.time)) { item->s.v.items = IT_SHOTGUN; } //item->mdl = "progs/backpack.mdl"; setmodel(item, "progs/backpack.mdl"); if ((item->s.v.items == IT_ROCKET_LAUNCHER) || (item->s.v.items == IT_LIGHTNING)) { stuffcmd_flags(self, STUFFCMD_DEMOONLY, "//ktx drop %d %d %d\n", NUM_FOR_EDICT(item), (int)item->s.v.items, NUM_FOR_EDICT(self)); } if (item->s.v.items == IT_AXE) { item->netname = "Axe"; self->ps.wpn[wpAXE].drops++; } else if (item->s.v.items == IT_SHOTGUN) { item->netname = "Shotgun"; self->ps.wpn[wpSG].drops++; } else if (item->s.v.items == IT_SUPER_SHOTGUN) { item->netname = "Double-barrelled Shotgun"; //item->mdl = "progs/g_shot.mdl"; self->ps.wpn[wpSSG].drops++; } else if (item->s.v.items == IT_NAILGUN) { item->netname = "Nailgun"; //item->mdl = "progs/g_nail.mdl"; self->ps.wpn[wpNG].drops++; } else if (item->s.v.items == IT_SUPER_NAILGUN) { item->netname = "Super Nailgun"; //item->mdl = "progs/g_nail2.mdl"; self->ps.wpn[wpSNG].drops++; } else if (item->s.v.items == IT_GRENADE_LAUNCHER) { item->netname = "Grenade Launcher"; //item->mdl = "progs/g_rock.mdl"; self->ps.wpn[wpGL].drops++; } else if (item->s.v.items == IT_ROCKET_LAUNCHER) { item->netname = "Rocket Launcher"; //item->mdl = "progs/g_rock2.mdl"; self->ps.wpn[wpRL].drops++; } else if (item->s.v.items == IT_LIGHTNING) { item->netname = "Thunderbolt"; //item->mdl = "progs/g_light.mdl"; self->ps.wpn[wpLG].drops++; } else { item->netname = ""; } item->s.v.ammo_shells = self->s.v.ammo_shells; item->s.v.ammo_nails = self->s.v.ammo_nails; item->s.v.ammo_rockets = self->s.v.ammo_rockets; item->s.v.ammo_cells = self->s.v.ammo_cells; // Yawnmode: maximum backpack-capacity is 1/4 of player-capacity // - Molgrum if (k_yawnmode) { item->s.v.ammo_shells = min(25, item->s.v.ammo_shells); item->s.v.ammo_nails = min(50, item->s.v.ammo_nails); item->s.v.ammo_rockets = min(25, item->s.v.ammo_rockets); item->s.v.ammo_cells = min(25, item->s.v.ammo_cells); } if (fresh_packs) { item->s.v.ammo_shells = bound(0, item->s.v.ammo_shells, cvar("k_freshteams_pack_shells")); item->s.v.ammo_nails = bound(0, item->s.v.ammo_nails, cvar("k_freshteams_pack_nails")); item->s.v.ammo_rockets = bound(0, item->s.v.ammo_rockets, cvar("k_freshteams_pack_rockets")); item->s.v.ammo_cells = bound(0, item->s.v.ammo_cells, cvar("k_freshteams_pack_cells")); } playername = self->netname; log_printf("\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t%s\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%d\n" "\t\t\t\t%s\n" "\t\t\t\n" "\t\t\n", g_globalvars.time - match_start_time, item->netname, (int)item->s.v.ammo_shells, (int)item->s.v.ammo_nails, (int)item->s.v.ammo_rockets, (int)item->s.v.ammo_cells, cleantext(playername)); item->s.v.velocity[2] = 300; item->s.v.velocity[0] = -100 + (g_random() * 200); item->s.v.velocity[1] = -100 + (g_random() * 200); item->s.v.flags = FL_ITEM; item->s.v.solid = SOLID_TRIGGER; item->s.v.movetype = MOVETYPE_TOSS; //setmodel( item, k_yawnmode ? item->mdl : "progs/backpack.mdl" ); setsize(item, -16, -16, 0, 16, 16, 56); item->touch = (func_t) BackpackTouch; // remove after 2 minutes, and after 30 seconds if backpack dropped by monster item->s.v.nextthink = g_globalvars.time + (self->ct == ctPlayer ? 120 : 30); item->think = (func_t) SUB_Remove; item->classname = "backpack"; // we do need to be able to get rid of these things between points (hoony mode) if (isTeam()) { item->backpack_player_name = playername; strlcpy(item->backpack_team_name, getteam(self), MAX_TEAM_NAME); } #ifdef BOT_SUPPORT BotsBackpackDropped(self, item); #endif } /* =============================================================================== SPAWN POINT MARKERS =============================================================================== */ char *Spawn_GetModel(void) { // Can't rely on cvar_string response for setmodel/precache_model so caching here static char spawn_model[128]; if (!spawn_model[0]) { char *mdl = cvar_string("k_spm_custom_model"); if (only_digits(mdl)) { strlcpy(spawn_model, atoi(mdl) ? "progs/wizard.mdl" : "progs/w_g_key.mdl", sizeof(spawn_model)); } else { strlcpy(spawn_model, mdl, sizeof(spawn_model)); } } return spawn_model; } gedict_t* Spawn_OnePoint(gedict_t *spawn_point, vec3_t org, int effects) { unsigned int nargs; char *color_tint; gedict_t *p; p = spawn(); p->s.v.flags = FL_ITEM; p->s.v.solid = SOLID_NOT; p->s.v.movetype = MOVETYPE_NONE; setmodel(p, Spawn_GetModel()); p->netname = "Spawn Point"; p->classname = "spawnpoint"; p->k_lastspawn = spawn_point; p->s.v.effects = (int)p->s.v.effects | effects; color_tint = cvar_string("k_spm_color_rgba"); trap_CmdTokenize(color_tint); nargs = trap_CmdArgc(); if (nargs >= 3) { char argument[128]; float r, g, b; trap_CmdArgv(0, argument, sizeof(argument)); r = max(0.0f, atof(argument)); trap_CmdArgv(1, argument, sizeof(argument)); g = max(0.0f, atof(argument)); trap_CmdArgv(2, argument, sizeof(argument)); b = max(0.0f, atof(argument)); ExtFieldSetColorMod(p, r, g, b); if (nargs == 4) { trap_CmdArgv(3, argument, sizeof(argument)); ExtFieldSetAlpha(p, atof(argument)); } } // store references for changing selections in hoonymode spawn_point->wizard = p; p->wizard = spawn_point; setorigin(p, PASSVEC3(org)); VectorCopy(spawn_point->s.v.angles, p->s.v.angles); trap_makevectors(p->s.v.angles); return p; } void Spawn_SpawnPoints(char *classname, int effects) { gedict_t *e; vec3_t org; for (e = world; (e = ez_find(e, classname));) { VectorCopy(e->s.v.origin, org); org[2] += 0; // qqshka: it was 16, but I like more how it looks when it more close to ground if (isHoonyModeDuel()) { effects = (e->hoony_nomination ? (EF_GREEN | EF_RED) : 0); } Spawn_OnePoint(e, org, effects); } } void ShowSpawnPoints(void) { Spawn_SpawnPoints("info_player_deathmatch", cvar("k_spm_glow") ? ( EF_GREEN | EF_RED) : 0); if (isCTF()) { Spawn_SpawnPoints("info_player_team1", cvar("k_spm_glow") ? EF_RED : 0); Spawn_SpawnPoints("info_player_team2", cvar("k_spm_glow") ? EF_BLUE : 0); } } void HideSpawnPoints(void) { gedict_t *e; for (e = world; (e = ez_find(e, "spawnpoint"));) { if (e->wizard) { e->wizard->wizard = 0; } ent_remove(e); } } QW-Group-ktx-d05d6ca/src/logs.c000066400000000000000000000055261475442401000163370ustar00rootroot00000000000000/* * 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 * * * $Id$ */ #include "g_local.h" #include "stats.h" fileHandle_t log_handle = -1; void log_close(void) { if (log_handle < 0) { return; } trap_FS_CloseFile(log_handle); log_handle = -1; } void log_open(const char *fmt, ...) { va_list argptr; char text[1024] = { 0 }; if (!cvar("k_extralog")) { return; } log_close(); va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; if (!text[0]) { return; // name not specified } if (trap_FS_OpenFile(text, &log_handle, FS_APPEND_BIN) < 0) { log_handle = -1; return; } } void log_printf(const char *fmt, ...) { va_list argptr; char text[1024] = { 0 }; if (log_handle < 0) { return; } if (!cvar("k_extralog")) { return; } va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_FS_WriteFile(text, strlen(text), log_handle); } void StartLogs(void) { char date[64] = { 0 }, date_c[64] = { 0 }, *ip, *port; int i = 0; if (strnull(ip = cvar_string("sv_local_addr")) || strnull(port = strchr(ip, ':')) || !(i = atoi(port + 1))) { return; } port[0] = 0; port++; if (!QVMstrftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %Z", 0)) { date[0] = 0; // bad date } if (!QVMstrftime(date_c, sizeof(date_c), "%Y%m%d-%H%M%S-%Z", 0)) { date_c[0] = 0; // bad date } log_open("%s", cvar_string("extralogname")); log_printf("%s", "\n"); log_printf( "\n", cvar_string("k_extralog_xsd_uri")); log_printf("\t0.1\n"); log_printf("\t\n" "\t\t%s\n" "\t\t%s\n" "\t\t%s\n" "\t\t%d\n" "\t\t%s\n" "\t\t%s\n" "\t\n", date, cleantext(cvar_string("_k_host")), ip, i, mapname, GetMode()); log_printf("\t\n"); } void StopLogs(void) { log_printf("\t\n"); log_printf("\n"); log_close(); } QW-Group-ktx-d05d6ca/src/maps.c000066400000000000000000000325401475442401000163270ustar00rootroot00000000000000/* * 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 * * * $Id$ */ #include "g_local.h" qbool isSupport_Params(gedict_t *p); static char *fixed_maps_list[] = { // episode 1 "e1m1", "e1m2", "e1m3", "e1m4", "e1m5", "e1m6", "e1m7", "e1m8", // episode 2 "e2m1", "e2m2", "e2m3", "e2m4", "e2m5", "e2m6", "e2m7", // episode 3 "e3m1", "e3m2", "e3m3", "e3m4", "e3m5", "e3m6", "e3m7", // episode 4 "e4m1", "e4m2", "e4m3", "e4m4", "e4m5", "e4m6", "e4m7", "e4m8", // "start", "end", // DM maps "dm1", "dm2", "dm3", "dm4", "dm5", "dm6" }; static int fixed_maps_cnt = sizeof(fixed_maps_list) / sizeof(fixed_maps_list[0]); //=============================================== #define MAX_MAPS 4096 static char *mapslist[MAX_MAPS] = { 0 }; static int maps_cnt = 0; static char ml_buf[MAX_MAPS * 32] = { 0 }; // OUCH OUCH!!! btw, 32 is some average len of map name here, with path // NOTE: we did not check is this map alredy in list or not... static void Map_AddMapToList(char *name) { int l; if (strnull(name)) { return; // fu! } if ((maps_cnt < 0) || (maps_cnt >= MAX_MAPS)) { return; // too many } l = strlen(name) + 1; // + nul mapslist[maps_cnt] = G_Alloc(l); // alloc mem strlcpy(mapslist[maps_cnt], name, l); // copy maps_cnt++; } // Extension to allow multiple .ent files for individual maps. // We check all *.ent files we can find, and look for format mapName#description.ent, where mapName is a // standard map we already have in list. void GetCustomEntityMapsForDirectory(char *directory) { char *s, name[32], *sep; int i, cnt, l, m; ml_buf[0] = 0; // Find all entity files in the maps directory cnt = trap_FS_GetFileList(directory, (FTE_sv ? ".ent" : "\\.ent$"), ml_buf, sizeof(ml_buf), 0); ml_buf[sizeof(ml_buf) - 1] = 0; for (i = 0, s = ml_buf; i < cnt && s < ml_buf + sizeof(ml_buf); ++i) { l = strlen(s); if (FTE_sv) { l -= 4; // skip extension } if (l <= 0) { break; } l++; // + nul sep = strchr(s, K_ENTITYFILE_SEPARATOR); if (sep) { int baseMapFound = 0, duplicateFound = 0; int mapNameLength; // copy strlcpy(name, s, min(sizeof(name), l)); // The server could have mapName#entName.ent in more than one directory, so check here for duplicates mapNameLength = sep - s; if (mapNameLength > 0) { for (m = 0; m < maps_cnt; ++m) { baseMapFound |= (strlen(mapslist[m]) == mapNameLength && !strncmp(mapslist[m], s, mapNameLength)); duplicateFound |= !strcmp(mapslist[m], s); } if (baseMapFound && !duplicateFound) { Map_AddMapToList(name); } } } // find next map name s = strchr(s, 0); if (!s) { G_Error("GetMapList: strchr returns NULL"); } s++; } return; } void GetCustomEntityMaps(void) { char path[1024] = { 0 }; char *entityDir = cvar_string("sv_loadentfiles_dir"); if (entityDir && *entityDir) { snprintf(path, sizeof(path) - 1, "maps/%s", entityDir); GetCustomEntityMapsForDirectory(path); } GetCustomEntityMapsForDirectory("maps"); } void AddFixedMaps(void) { int i; if (mapslist[0] || maps_cnt) { G_Error("AddFixedMaps: can't do it twice"); } for (i = 0; i < MAX_MAPS && i < fixed_maps_cnt; i++) Map_AddMapToList(fixed_maps_list[i]); } void GetMapList(void) { char *s, name[32]; int i, cnt, l; ml_buf[0] = 0; if (mapslist[0] || maps_cnt) { G_Error("GetMapList: can't do it twice"); } if (!FTE_sv) { AddFixedMaps(); // add maps like dm3 dm2 e1m2 etc from paks, FTE doesn't need it. } // this is reg exp search, so we escape . with \. in extension, however \ must be escaped in C string too so its \\. cnt = trap_FS_GetFileList("maps", (FTE_sv ? ".bsp" : "\\.bsp$"), ml_buf, sizeof(ml_buf), 0); cnt = bound(0, cnt, MAX_MAPS); ml_buf[sizeof(ml_buf) - 1] = 0; // well, this is optional, just sanity for (i = 0, s = ml_buf; i < cnt && s < ml_buf + sizeof(ml_buf); i++) { l = strlen(s); if (FTE_sv) { l -= 4; // skip extension } if (l <= 0) { break; } l++; // + nul // because of FTE we can't use 's' as is, we need skip extension with this weird strlcpy() strlcpy(name, s, min(sizeof(name), l)); // copy Map_AddMapToList(name); // find next map name s = strchr(s, 0); if (!s) { G_Error("GetMapList: strchr returns NULL"); } s++; } GetCustomEntityMaps(); #if 0 // debug G_cprint("Maps list\n"); for (i = 0; i < maps_cnt; i++) { G_cprint( "%4d: %s\n", i, mapslist[i] ); } #endif } void mapslist_dl(void) { char arg_2[32]; char nomaps[32]; qbool skip_maps; int i, from, to; skip_maps = atoi(infokey(self, "nomaps", nomaps, sizeof(nomaps))) > 0; if (skip_maps) { goto skip_map_stuffing; } // seems we alredy done that if (self->k_stuff & STUFF_MAPS) { G_sprint(self, 2, "mapslist already stuffed\n"); return; } // no arguments if (trap_CmdArgc() == 1) { G_sprint(self, 2, "mapslist without arguments\n"); return; } trap_CmdArgv(1, arg_2, sizeof(arg_2)); from = bound(0, atoi(arg_2), maps_cnt); if (isSupport_Params(self)) { to = bound(from, from + MAX_STUFFED_QUICKMAPS_PER_FRAME, maps_cnt); for (i = from - 1; i < to; i++) { if (to - i >= 8) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "ktx_am8 %s %s %s %s %s %s %s %s\n", mapslist[i], mapslist[i + 1], mapslist[i + 2], mapslist[i + 3], mapslist[i + 4], mapslist[i + 5], mapslist[i + 6], mapslist[i + 7]); i += 7; } else if (to - i >= 4) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "ktx_am4 %s %s %s %s\n", mapslist[i], mapslist[i + 1], mapslist[i + 2], mapslist[i + 3]); i += 3; } else { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "alias %s \"cmd votemap %s\"\n", mapslist[i], mapslist[i]); } } } else { to = bound(from, from + MAX_STUFFED_ALIASES_PER_FRAME, maps_cnt); // stuff portion of aliases for (i = from; i < to; i++) { if (i == 0) { G_sprint(self, 2, "Loading maps list...\n"); } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "alias %s cmd cm %d\n", mapslist[i], i + 1); } } if (i < maps_cnt) { // request next stuffing stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "cmd mapslist_dl %d\n", i); return; } G_sprint(self, 2, "Maps loaded\n"); skip_map_stuffing: // we done self->k_stuff = self->k_stuff | STUFF_MAPS; // add flag // request commands if (!(self->k_stuff & STUFF_COMMANDS)) { StuffModCommands(self); } } void StuffMaps(gedict_t *p) { p->k_stuff = p->k_stuff & ~STUFF_MAPS; // remove flag if (isSupport_Params(p)) { stuffcmd_flags( p, STUFFCMD_IGNOREINDEMO, "alias ktx_am4 \"tempalias %%1 cmd votemap %%1;tempalias %%2 cmd votemap %%2;tempalias %%3 cmd votemap %%3;tempalias %%4 cmd votemap %%4\"\n"); stuffcmd_flags( p, STUFFCMD_IGNOREINDEMO, "alias ktx_am8 \"tempalias %%1 cmd votemap %%1;tempalias %%2 cmd votemap %%2;tempalias %%3 cmd votemap %%3;tempalias %%4 cmd votemap %%4;tempalias %%5 cmd votemap %%5;tempalias %%6 cmd votemap %%6;tempalias %%7 cmd votemap %%7;tempalias %%8 cmd votemap %%8\n"); } stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "cmd mapslist_dl %d\n", 0); } char* GetMapName(int imp) { int i; if (imp > 0) { i = imp - 1; if ((i >= 0) && (i < maps_cnt)) { return mapslist[i]; } } return ""; } int GetMapNum(char *map) { int i; if (strnull(map)) { return 0; } for (i = 0; i < maps_cnt; i++) { if (streq(mapslist[i], map)) { return (i + 1); } } return 0; } void DoSelectMap(int iMap) { char *m; gedict_t *p; int till; qbool isVoted = false; if ((till = Q_rint((k_matchLess ? 15 : 7) - g_globalvars.time)) > 0) { G_sprint(self, 2, "Wait %d second%s!\n", till, count_s(till)); return; } if (k_matchLess && !k_bloodfest) { if (cvar("k_no_vote_map")) { G_sprint(self, 2, "Voting map is %s allowed\n", redtext("not")); return; } // you can select map in matchLess mode, but not in countdown. if (match_in_progress != 2) return; } else if (match_in_progress) { return; } if ((self->ct == ctSpec) && !is_adm(self)) // only admined specs can select map { return; } if (strnull(m = GetMapName(iMap))) { return; } if (cvar("k_lockmap") && !is_adm(self)) { G_sprint(self, 2, "MAP IS LOCKED!\n" "You are NOT allowed to change!\n"); return; } if (self->v.map == iMap) { G_sprint(self, 2, "--- your vote is still good ---\n"); return; } for (p = world; (p = find_plr(p));) { if (p->v.map == iMap) { isVoted = true; break; } } if (!get_votes( OV_MAP)) { G_bprint(2, "%s %s %s\n", self->netname, redtext("suggests map"), m); } else if (isVoted) { G_bprint(2, "%s %s %s %s %s\n", self->netname, redtext("agrees"), (CountPlayers() < 3 ? redtext("to") : redtext("on")), redtext("map"), m); } else { G_bprint(2, "%s %s %s\n", self->netname, redtext("would rather play on"), m); } self->v.map = k_lastvotedmap = iMap; vote_check_map(); } void SelectMap(void) { char arg_1[1024]; trap_CmdArgv(1, arg_1, sizeof(arg_1)); DoSelectMap(atoi(arg_1)); } qbool VoteMapSpecific(char *map) { int map_num = GetMapNum(map); if (map_num == 0) { G_sprint(self, 2, "Map '%s' not available on this server\n", map); return false; } // Perform vote DoSelectMap(map_num); return true; } void VoteMap(void) { char arg_1[1024]; if (trap_CmdArgc() < 2) { G_sprint(self, 2, "Usage: %s \n", redtext("votemap")); return; } // Convert map to index in list trap_CmdArgv(1, arg_1, sizeof(arg_1)); VoteMapSpecific(arg_1); } void ShowMaps(void) { int i, cnt; char arg_1[1024]; trap_CmdArgv(1, arg_1, sizeof(arg_1)); G_sprint(self, 2, "Vote for maps by typing the mapname,\n" "for example \"%s\" or use \"%s\".\n", redtext("dm6"), redtext("votemap dm6")); for (cnt = i = 0; i < maps_cnt; i++) { if (arg_1[0] && !strstr(mapslist[i], arg_1)) { continue; } if (!cnt) { G_sprint(self, 2, "\n---List of maps\n"); } G_sprint(self, 2, ((cnt & 1) ? "%s\n" : "%-17s "), mapslist[i]); cnt++; } if (cnt) { G_sprint(self, 2, "%s---End of list (%d/%d maps)\n", (cnt & 1) ? "\n" : "", cnt, maps_cnt); } } int IsMapInCycle(char *map) { char newmap[128] = { 0 }, mapid[128] = { 0 }; int i; if (strnull(map)) { return 0; } for (i = 0; i < 1000; i++) { snprintf(mapid, sizeof(mapid), "k_ml_%d", i); // huge for(), so using trap version instead of lazy but unsafe cvar_string() trap_cvar_string(mapid, newmap, sizeof(newmap)); if (strnull(newmap)) // end of list { return 0; } if (streq(map, newmap)) // ok map found in map list { return (i + 1); // i may be 0, so returning i + 1 } } return 0; } char* SelectRandomMap(char *buf, int buf_size) { char newmap[128] = { 0 }, mapid[128] = { 0 }; int cnt, c; buf[0] = 0; // find how much maps in pool. for (cnt = 0; cnt < 1000; cnt++) { snprintf(mapid, sizeof(mapid), "k_ml_%d", cnt); // huge for(), so using trap version instead of lazy but unsafe cvar_string() trap_cvar_string(mapid, newmap, sizeof(newmap)); if (strnull(newmap)) // end of list { break; } } // few attempts, to minimize selecting current map. for (c = 0; c < 5; c++) { int id = i_rnd(0, cnt - 1); // generate random id // get map. snprintf(mapid, sizeof(mapid), "k_ml_%d", id); trap_cvar_string(mapid, newmap, sizeof(newmap)); if (streq(mapname, newmap)) { continue; // same map, lets try again then. } // ok, we found it. strlcpy(buf, newmap, buf_size); break; } return buf; } // map list have now next syntax: // set k_ml_0 dm6 // set k_ml_1 dm4 // set k_ml_2 dm2 // so this mean we have rotation of maps dm6 dm4 dm2 dm6 dm4 dm2 ... char* SelectMapInCycle(char *buf, int buf_size) { char newmap[128] = { 0 }, mapid[128] = { 0 }; int player_count = CountPlayers(), maxp = 0, minp = 0, i; buf[0] = 0; if (cvar("k_random_maplist")) { if (*SelectRandomMap(buf, buf_size)) { return buf; } } if (!(i = cvar("_k_last_cycle_map"))) { if (!(i = IsMapInCycle(mapname))) { // ok map found in map list, select next map i = 0; } } while (i < 1000) { maxp = cvar(va("k_ml_maxp_%d", i >= 1000 ? 0 : i)); maxp = maxp == 0 ? MAX_CLIENTS : maxp; minp = cvar(va("k_ml_minp_%d", i >= 1000 ? 0 : i)); if ((maxp >= player_count) && (player_count >= minp)) { snprintf(mapid, sizeof(mapid), "k_ml_%d", i >= 1000 ? 0 : i); trap_cvar_string(mapid, newmap, sizeof(newmap)); break; } else { G_bprint( 2, "Player requirements not met for map #%d in the map cycle, continuing to next map. (Minimum: %d, Maximum: %d)\n", (i + 1), minp, maxp); } i++; } if (strnull(newmap)) // last resort, trying get first entry in map list { trap_cvar_string("k_ml_0", newmap, sizeof(newmap)); } strlcpy(buf, newmap, buf_size); if ((i = IsMapInCycle(buf))) { cvar_fset("_k_last_cycle_map", i); } return buf; } QW-Group-ktx-d05d6ca/src/maps_map_amphi2.c000066400000000000000000000017471475442401000204310ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void AMPHI2BotInLava(void) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; // TODO: rewrite... essentially if in lava and enemy isn't shafting, jump to target instead of walk // this is probably true of all lava-burn situations, as long as we're not lava-rjing to escape? if (self->isBot && streq(mapname, "amphi2")) { if (g_globalvars.time > self->fb.arrow_time) { if (self->s.v.waterlevel == 1) { vec3_t point; VectorSet(point, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] - 24); if (trap_pointcontents(PASSVEC3(point)) == CONTENT_LAVA) { if ((int)self->s.v.flags & FL_ONGROUND) { if (!enemy_shaft_attack(self, enemy)) { if (!self->fb.rocketJumping) { NewVelocityForArrow(self, self->fb.dir_move_, "amphi2"); SetJumpFlag(self, true, "AMPHI2 logic"); } } } } } } } } #endif QW-Group-ktx-d05d6ca/src/maps_map_dm3.c000066400000000000000000000021641475442401000177260ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void DM3CampLogic(void) { if (NumberOfClients() > 1) { if (teamplay && deathmatch <= 3) { if (((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) && !self->fb.bot_evade) { if ((self->s.v.health > 60) && (self->s.v.armorvalue > 80)) { if ((self->s.v.ammo_cells > 15) || (self->s.v.ammo_rockets > 3)) { gedict_t *search_entity = ez_find(world, "item_artifact_super_damage"); if (search_entity) { if (g_random() < 0.5) { if (search_entity->s.v.origin[2] <= (self->s.v.origin[2] + 18)) { vec3_t diff; VectorSubtract(search_entity->s.v.origin, self->s.v.origin, diff); if (vlen(diff) < 200) { if (g_random() < 0.9) { self->fb.camp_state |= CAMPBOT; SetLinkedMarker(self, self->fb.touch_marker, "dm3-camp"); } } else { self->fb.camp_state &= ~CAMPBOT; } } } } } } } } } } #endif QW-Group-ktx-d05d6ca/src/maps_map_dm4.c000066400000000000000000000021331475442401000177230ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" void DM4CampLogic(void) { gedict_t *enemy_ = &g_edicts[self->s.v.enemy]; if (isDuel()) { if (((int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING)) && !self->fb.bot_evade) { if ((self->s.v.health > 50) && (self->s.v.armorvalue > 30)) { if ((self->s.v.ammo_cells > 15) || (self->s.v.ammo_rockets > 3)) { if (g_random() < 0.985) { vec3_t above_lg = { 448, -176, 60 }; vec3_t on_quad_stairs = { 280, -330, 60 }; if ((enemy_->s.v.origin[0] < 700) && (VectorDistance(above_lg, self->s.v.origin) < 200)) { self->fb.camp_state |= CAMPBOT; SetLinkedMarker(self, self->fb.touch_marker, "dm4-camp1"); } else if ((enemy_->s.v.origin[0] >= 700) && (VectorDistance(on_quad_stairs, self->s.v.origin) < 200)) { self->fb.camp_state |= CAMPBOT; SetLinkedMarker(self, self->fb.touch_marker, "dm4-camp2"); } else { self->fb.camp_state &= ~CAMPBOT; } } } } } } } #endif QW-Group-ktx-d05d6ca/src/maps_map_dm6.c000066400000000000000000000125541475442401000177350ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" gedict_t *dm6_door = 0; qbool CheckNewWeapon(int weapon); // FIXME: Globals extern gedict_t *markers[]; void DM6CampLogic(void) { qbool has_weapon = (int)self->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING); // Camp the red armor... if (NumberOfClients() > 1) { if (has_weapon && !self->fb.bot_evade) { if ((self->s.v.health > 80) && (self->s.v.armorvalue > 100)) { if ((self->s.v.ammo_cells > 15) || (self->s.v.ammo_rockets > 3)) { gedict_t *search_entity = ez_find(world, "item_armorInv"); if (search_entity) { if (search_entity->s.v.origin[2] <= (self->s.v.origin[2] + 18)) { if (VectorDistance(search_entity->s.v.origin, self->s.v.origin) < 200) { if (g_random() < 0.9) { self->fb.camp_state |= CAMPBOT; SetLinkedMarker(self, self->fb.touch_marker, "dm6-camp"); } } else { self->fb.camp_state &= ~CAMPBOT; } } } } } } } } void DM6SelectWeaponToOpenDoor(gedict_t *self) { if (dm6_door && (self->fb.path_state & DM6_DOOR)) { int items_ = (int)self->s.v.items; int desired_weapon = 0; if (self->s.v.ammo_shells) { desired_weapon = IT_SHOTGUN; } else if ((items_ & IT_NAILGUN) && (self->s.v.ammo_nails)) { desired_weapon = IT_NAILGUN; } else if ((items_ & IT_SUPER_NAILGUN) && (self->s.v.ammo_nails)) { desired_weapon = IT_SUPER_NAILGUN; } else if ((items_ & IT_LIGHTNING) && (self->s.v.ammo_cells)) { desired_weapon = IT_LIGHTNING; } self->fb.firing |= CheckNewWeapon(desired_weapon); } } qbool DM6DoorLogic(gedict_t *self, gedict_t *goal_entity) { if (dm6_door && (goal_entity->fb.Z_ == 1)) { if (self->fb.touch_marker->fb.zones[0].task & DM6_DOOR) { if (dm6_door->fb.door_entity && dm6_door->fb.door_entity->s.v.takedamage) { gedict_t *enemy = &g_edicts[self->s.v.enemy]; if (enemy == self->fb.look_object) { if (!self->invincible_time) { // on dm6?... if (enemy->fb.firepower >= 50) { goal_entity->fb.saved_goal_desire = 0; return true; } } } } } } return false; } qbool DM6DoorClosed(fb_path_eval_t *eval) { if (!dm6_door) { return false; } return ((eval->test_marker == dm6_door) && !dm6_door->fb.door_entity->s.v.takedamage) || ((eval->description & DM6_DOOR) && (dm6_door->fb.door_entity->s.v.origin[0] > -64)); } void DM6MarkerTouchLogic(gedict_t *self, gedict_t *goalentity_marker) { if (dm6_door && goalentity_marker && (goalentity_marker->fb.Z_ == 1)) { if (self->fb.touch_marker->fb.zones[0].task & DM6_DOOR) { if (dm6_door->fb.door_entity->s.v.takedamage) { vec3_t temp, src, direction; VectorAdd(dm6_door->fb.door_entity->s.v.absmin, dm6_door->fb.door_entity->s.v.view_ofs, temp); VectorSubtract(temp, self->s.v.origin, temp); temp[2] -= 40; normalize(temp, direction); VectorCopy(self->s.v.origin, src); src[2] += 16; traceline(src[0], src[1], src[2], src[0] + direction[0] * 2048, src[1] + direction[1] * 2048, src[2] + direction[2] * 2048, false, self); if (PROG_TO_EDICT(g_globalvars.trace_ent) == dm6_door->fb.door_entity) { if (self->fb.debug_path) { G_bprint(PRINT_HIGH, "**** TRACED TO DOOR ****\n"); } self->fb.path_state |= DM6_DOOR; } } else { self->fb.path_state &= ~DM6_DOOR; } } } } qbool DM6LookAtDoor(gedict_t *self) { if (dm6_door && (self->fb.path_state & DM6_DOOR)) { self->fb.state |= NOTARGET_ENEMY; self->fb.look_object = dm6_door->fb.door_entity; if (self->fb.debug_path) { G_bprint(PRINT_HIGH, "looking at door\n"); } return true; } return false; } qbool DM6FireAtDoor(gedict_t *self, vec3_t rel_pos) { if (dm6_door && (self->fb.path_state & DM6_DOOR)) { if (dm6_door->fb.door_entity->s.v.takedamage) { rel_pos[2] -= 38; } else { self->fb.path_state &= ~DM6_DOOR; self->fb.state &= ~NOTARGET_ENEMY; } if (self->fb.debug_path) { G_bprint(PRINT_HIGH, "Shooting at door\n"); } return true; } return false; } void DM6Debug(gedict_t *self) { int i, j; if (dm6_door) { G_sprint(self, PRINT_HIGH, "DM6 Door is marker #%3d\n", dm6_door->fb.index + 1); } else { G_sprint(self, PRINT_HIGH, "DM6 Door not set...\n"); } G_sprint(self, PRINT_HIGH, "Paths with DM6_DOOR set:\n"); for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *s = markers[i]; if (s) { for (j = 0; j < NUMBER_PATHS; ++j) { gedict_t *t = markers[i]->fb.paths[j].next_marker; if (t && (s->fb.paths[j].flags & DM6_DOOR)) { G_sprint(self, PRINT_HIGH, " > %3d (%s) to %3d (%s)\n", s->fb.index + 1, s->classname, t->fb.index + 1, t->classname); } } } } G_sprint(self, PRINT_HIGH, "Markers with DM6_DOOR task set:\n"); for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *s = markers[i]; if (s && (s->fb.zones[0].task & DM6_DOOR)) { G_sprint(self, PRINT_HIGH, " > %3d (%s)\n", s->fb.index + 1, s->classname); } } if (dm6_door) { G_sprint(self, PRINT_HIGH, "dm6_door->takedamage = %s\n", dm6_door->s.v.takedamage ? "true" : "false"); if (dm6_door->fb.door_entity) { G_sprint(self, PRINT_HIGH, "dm6_door->door->takedamage = %s\n", dm6_door->fb.door_entity->s.v.takedamage ? "true" : "false"); } } } #endif QW-Group-ktx-d05d6ca/src/maps_map_povdmm4.c000066400000000000000000000016561475442401000206360ustar00rootroot00000000000000// Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" qbool BotDoorIsClosed(gedict_t *door); // FIXME: saved_goal_desire set to 0 for both yellow armour if door is closed // should know that the path is blocked, rather than thinking "bot doesn't want yellow armour" qbool POVDMM4DontWalkThroughDoor(gedict_t *goal_entity) { if (!streq(mapname, "povdmm4")) { return false; } if (cvar("k_midair") || cvar("k_instagib")) { goal_entity->fb.saved_goal_desire = 0; return true; } if (streq(goal_entity->classname, "item_armor2")) { // Find linked door entity - if closed, set desire to 0 int i = 0; for (i = 0; i < sizeof(goal_entity->fb.paths) / sizeof(goal_entity->fb.paths[0]); ++i) { gedict_t *next = goal_entity->fb.paths[i].next_marker; if (next && BotDoorIsClosed(next)) { goal_entity->fb.saved_goal_desire = 0; return true; } } } return false; } #endif QW-Group-ktx-d05d6ca/src/marker_load.c000066400000000000000000000255251475442401000176540ustar00rootroot00000000000000/* marker_load.qc Copyright (C) 1997-1999 Robert 'Frog' Field */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" static int marker_index = 0; static int mapDeathHeight = FB_MAPDEATHHEIGHT_DEFAULT; void InitialiseMarkerRoutes(void); // FIXME: globals extern gedict_t *markers[]; void AddToQue(gedict_t *ent) { markers[marker_index] = ent; ent->fb.index = marker_index++; } int MapDeathHeight(void) { return mapDeathHeight; } void SetMapDeathHeight(int height) { mapDeathHeight = max(height, FB_MAPDEATHHEIGHT_DEFAULT); } const char* EncodeMarkerFlags(int marker_flags) { static char buffer[10]; char *s = buffer; if (marker_flags & UNREACHABLE) { *s++ = 'u'; } if (marker_flags & MARKER_IS_DM6_DOOR) { *s++ = '6'; } if (marker_flags & MARKER_BLOCKED_ON_STATE_TOP) { *s++ = 'b'; } if (marker_flags & MARKER_DOOR_TOUCHABLE) { *s++ = 't'; } if (marker_flags & MARKER_ESCAPE_ROUTE) { *s++ = 'e'; } if (marker_flags & MARKER_FIRE_ON_MATCH_START) { *s++ = 'f'; } if (marker_flags & MARKER_NOTOUCH) { *s++ = 'n'; } if (s == buffer) { return "(none)"; } *s = 0; return buffer; } int DecodeMarkerFlagString(const char *s) { size_t i; int marker_flags = 0; for (i = 0; i < strlen(s); ++i) { switch (s[i]) { case 'u': marker_flags |= UNREACHABLE; break; case '6': marker_flags |= MARKER_IS_DM6_DOOR; break; case 'f': marker_flags |= MARKER_FIRE_ON_MATCH_START; break; case 'b': marker_flags |= MARKER_BLOCKED_ON_STATE_TOP; break; case 't': marker_flags |= MARKER_DOOR_TOUCHABLE; break; case 'e': marker_flags |= MARKER_ESCAPE_ROUTE; break; case 'n': marker_flags |= MARKER_NOTOUCH; break; } } return marker_flags; } const char* EncodeMarkerPathFlags(int path_flags) { static char buffer[10]; char *s = buffer; if (path_flags & WATERJUMP_) { *s++ = 'w'; } if (path_flags & DM6_DOOR) { *s++ = '6'; } if (path_flags & ROCKET_JUMP) { *s++ = 'r'; } if (path_flags & JUMP_LEDGE) { *s++ = 'j'; } if (path_flags & VERTICAL_PLATFORM) { *s++ = 'v'; } if (path_flags & BOTPATH_CURLJUMP_HINT) { *s++ = 'a'; } if (s == buffer) { return "(none)"; } *s = 0; return buffer; } int DecodeMarkerPathFlagString(const char *s) { size_t i = 0; int path_flags = 0; for (i = 0; i < strlen(s); ++i) { switch (s[i]) { case 'w': path_flags |= WATERJUMP_; break; case '6': path_flags |= DM6_DOOR; break; case 'r': path_flags |= ROCKET_JUMP; break; case 'j': path_flags |= JUMP_LEDGE; break; case 'v': path_flags |= VERTICAL_PLATFORM; break; case 'a': path_flags |= BOTPATH_CURLJUMP_HINT; break; } } return path_flags; } void BotSetRocketJumpFields(int marker_number, int path_index, float pitch, float yaw, int delay) { --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } if ((path_index < 0) || (path_index >= NUMBER_PATHS)) { return; } markers[marker_number]->fb.paths[path_index].rj_pitch = pitch; markers[marker_number]->fb.paths[path_index].rj_yaw = yaw; markers[marker_number]->fb.paths[path_index].rj_delay = delay; } qbool FrogbotShowMarkerIndicators(void) { return FrogbotOptionEnabled(FB_OPTION_SHOW_MARKERS | FB_OPTION_EDITOR_MODE); } gedict_t* spawn_marker(float x, float y, float z) { gedict_t *marker_ = spawn(); marker_->classname = "marker"; marker_->s.v.flags = FL_ITEM; BecomeMarker(marker_); marker_->s.v.origin[0] = pr1_rint(x); marker_->s.v.origin[1] = pr1_rint(y); marker_->s.v.origin[2] = pr1_rint(z); marker_->s.v.solid = SOLID_TRIGGER; marker_->touch = (func_t) marker_touch; if (FrogbotShowMarkerIndicators()) { setmodel(marker_, "progs/w_g_key.mdl"); } VectorSet(marker_->s.v.view_ofs, 80, 80, 24); setsize(marker_, -65, -65, -24, 65, 65, 32); return marker_; } gedict_t* CreateMarker(float x, float y, float z) { gedict_t *marker = spawn_marker(x, y, z); AddToQue(marker); return marker; } void AllMarkersLoaded(void) { self = NULL; path_normal = true; InitialiseMarkerRoutes(); } void SetMarkerAngleHint(int marker_number, int path_index, int hint) { --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } if ((path_index < 0) || (path_index >= NUMBER_PATHS)) { return; } markers[marker_number]->fb.paths[path_index].angle_hint = hint; if (hint) { markers[marker_number]->fb.paths[path_index].flags |= BOTPATH_CURLJUMP_HINT; } else { markers[marker_number]->fb.paths[path_index].flags &= ~BOTPATH_CURLJUMP_HINT; } } void SetMarkerPathFlags(int marker_number, int path_index, int flags) { --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } if ((path_index < 0) || (path_index >= NUMBER_PATHS)) { return; } markers[marker_number]->fb.paths[path_index].flags = flags; if (flags & ROCKET_JUMP) { markers[marker_number]->fb.paths[path_index].rj_pitch = 78.25; markers[marker_number]->fb.paths[path_index].rj_yaw = -1; } } void SetMarkerPath(int source_marker, int path_index, int next_marker) { --source_marker; --next_marker; if ((source_marker < 0) || (source_marker >= NUMBER_MARKERS)) { return; } if ((next_marker < 0) || (next_marker >= NUMBER_MARKERS)) { return; } if ((path_index < 0) || (path_index >= NUMBER_PATHS)) { return; } if ((markers[source_marker] == NULL) || (markers[next_marker] == NULL)) { G_Printf("Invalid path: %d to %d\n", source_marker, next_marker); return; } markers[source_marker]->fb.paths[path_index].next_marker = markers[next_marker]; } void SetMarkerViewOffset(int marker, float zOffset) { --marker; if ((marker < 0) || (marker >= NUMBER_MARKERS) || (markers[marker] == 0)) { return; } markers[marker]->fb.T |= MARKER_EXPLICIT_VIEWOFFSET; markers[marker]->s.v.view_ofs[2] = zOffset; } qbool LoadBotRoutingFromFile(void) { fileHandle_t file = -1; char lineData[128]; char argument[128]; // Load bot definition file: frogbots rely on objects spawning // markers, so be aware of alternative .ent files char *entityFile = cvar_string("k_entityfile"); if (!strnull(entityFile)) { file = std_fropen("maps/%s.bot", entityFile); if (file == -1) { file = std_fropen("bots/maps/%s.bot", entityFile); } } if (file == -1) { file = std_fropen("maps/%s.bot", mapname); if (file == -1) { file = std_fropen("bots/maps/%s.bot", mapname); } } if (file == -1) { return false; } while (std_fgets(file, lineData, sizeof(lineData))) { trap_CmdTokenize(lineData); trap_CmdArgv(0, argument, sizeof(argument)); if (strnull(argument) || ((argument[0] == '/') && (argument[1] == '/'))) { continue; } if (streq(argument, "CreateMarker")) { // CreateMarker %f %f %f float x, y, z; if (trap_CmdArgc() != 4) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); x = atof(argument); trap_CmdArgv(2, argument, sizeof(argument)); y = atof(argument); trap_CmdArgv(3, argument, sizeof(argument)); z = atof(argument); CreateMarker(x, y, z); } else if (streq(argument, "SetGoal")) { // SetGoal %d %d int marker, goal; if (trap_CmdArgc() != 3) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); goal = atoi(argument); SetGoal(goal, marker); } else if (streq(argument, "SetZone")) { // SetZone %d %d int marker, zone; if (trap_CmdArgc() != 3) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); zone = atoi(argument); SetZone(zone, marker); } else if (streq(argument, "SetMarkerPath")) { // SetMarkerPath %d %d %d int source_marker, path_number, next_marker; if (trap_CmdArgc() != 4) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); source_marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); path_number = atoi(argument); trap_CmdArgv(3, argument, sizeof(argument)); next_marker = atoi(argument); SetMarkerPath(source_marker, path_number, next_marker); } else if (streq(argument, "SetMarkerPathFlags")) { // SetMarkerPathFlags %d %d %s int source_marker, path_number, path_flags; if (trap_CmdArgc() != 4) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); source_marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); path_number = atoi(argument); trap_CmdArgv(3, argument, sizeof(argument)); path_flags = DecodeMarkerPathFlagString(argument); SetMarkerPathFlags(source_marker, path_number, path_flags); } else if (streq(argument, "SetMarkerFlag")) { // SetMarkerFlag %d %s int source_marker, marker_flags; if (trap_CmdArgc() != 3) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); source_marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); marker_flags = DecodeMarkerFlagString(argument); SetMarkerFlag(source_marker, marker_flags); } else if (streq(argument, "SetMarkerViewOfs")) { // SetMarkerViewOfs %d %f int source_marker; float offset; if (trap_CmdArgc() != 3) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); source_marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); offset = atof(argument); SetMarkerViewOffset(source_marker, offset); } else if (streq(argument, "SetMarkerPathAngleHint")) { int source_marker; int path_number; int hint; if (trap_CmdArgc() != 4) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); source_marker = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); path_number = atoi(argument); trap_CmdArgv(3, argument, sizeof(argument)); hint = atoi(argument); SetMarkerAngleHint(source_marker, path_number, hint); } else if (streq(argument, "SetMapDeathHeight")) { if (trap_CmdArgc() != 2) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); mapDeathHeight = atoi(argument); G_Printf("Set death height to %d\n", mapDeathHeight); } else if (streq(argument, "SetRocketJumpPathFields")) { int marker_number; int path_number; float pitch, yaw; int delay; if (trap_CmdArgc() != 6) { continue; } trap_CmdArgv(1, argument, sizeof(argument)); marker_number = atoi(argument); trap_CmdArgv(2, argument, sizeof(argument)); path_number = atoi(argument); trap_CmdArgv(3, argument, sizeof(argument)); pitch = atof(argument); trap_CmdArgv(4, argument, sizeof(argument)); yaw = atof(argument); trap_CmdArgv(5, argument, sizeof(argument)); delay = atoi(argument); BotSetRocketJumpFields(marker_number, path_number, pitch, yaw, delay); } } std_fclose(file); return true; } #endif QW-Group-ktx-d05d6ca/src/marker_util.c000066400000000000000000000133031475442401000177010ustar00rootroot00000000000000/* marker_util.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" // Globals void SUB_regen(void); // self = item, other = player that just touched the marker // called even if the item is waiting to respawn void check_marker(gedict_t *self, gedict_t *other) { vec3_t temp; float distance; if (self->fb.T & MARKER_NOTOUCH) { return; } if (g_random() < 0.25) { self->fb.touchPlayer = other; self->fb.touchPlayerTime = g_globalvars.time + 2.5; } // Distance from item's viewheight to player VectorAdd(self->s.v.absmin, self->s.v.view_ofs, temp); VectorSubtract(temp, other->s.v.origin, temp); distance = vlen(temp); // touch_distance is set to max value at start of every frame, so this will fire for multiple markers only // if it is closer than previous if ((distance < other->fb.touch_distance) && ((self->s.v.absmin[2] - 20) < other->s.v.absmin[2]) && CanDamage(self, other)) { other->fb.touch_distance = distance; //if (other->isBot && other->fb.touch_marker != self) //G_sprint (other, 2, "touched %3d/%s, g %d\n", self->fb.index, self->classname, g_edicts[other->s.v.goalentity].fb.index); other->fb.touch_marker = self; other->fb.Z_ = self->fb.Z_; // Trigger brute-force finding of closest marker if we don't touch another one in time other->fb.touch_marker_time = g_globalvars.time + 5; } } void marker_touch(void) { if (IsMarkerFrame() && (other->ct == ctPlayer)) { check_marker(self, other); } } void adjust_view_ofs_z(gedict_t *ent) { gedict_t *fallspot_self = ent; vec3_t testplace; ent = dropper; VectorSet(testplace, fallspot_self->s.v.absmin[0] + fallspot_self->s.v.view_ofs[0], fallspot_self->s.v.absmin[1] + fallspot_self->s.v.view_ofs[1], fallspot_self->s.v.absmin[2] + fallspot_self->s.v.view_ofs[2] + 1); VectorCopy(testplace, ent->s.v.origin); ent->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (walkmove(ent, 0, 0)) { if (ent->s.v.origin[2] <= testplace[2]) { if (droptofloor(ent)) { if (ent->s.v.origin[2] > testplace[2] - 56) { fallspot_self->s.v.view_ofs[2] = ent->s.v.origin[2] - fallspot_self->s.v.absmin[2]; } } } } } gedict_t* LocateNextMarker(vec3_t org, gedict_t *ignore_ent) { gedict_t *marker_ = NULL; gedict_t *closest_marker = NULL; float shortest_distance = 1000000; vec3_t marker_center; qbool editor_mode = FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE); float distance = 0; float min_distance = 0; float max_distance = editor_mode ? 100 : 1000; if (ignore_ent) { VectorAdd(ignore_ent->s.v.absmin, ignore_ent->s.v.absmax, marker_center); VectorScale(marker_center, 0.5f, marker_center); min_distance = VectorDistance(marker_center, org); } for (marker_ = world; (marker_ = trap_findradius(marker_, org, max_distance));) { if (marker_ == ignore_ent) { ignore_ent = NULL; continue; } if (!editor_mode && streq(marker_->classname, "door") && !(marker_->fb.T & MARKER_DOOR_TOUCHABLE)) { continue; } if (marker_->fb.fl_marker || (editor_mode && marker_->fb.index)) { VectorAdd(marker_->s.v.absmin, marker_->s.v.absmax, marker_center); VectorScale(marker_center, 0.5f, marker_center); } else { continue; } distance = VectorDistance(marker_center, org); if (distance < min_distance) { continue; } if ((distance == min_distance) && ignore_ent) { continue; } traceline(PASSVEC3(org), PASSVEC3(marker_center), true, dropper); if (g_globalvars.trace_fraction != 1) { distance = distance + 1000; } if (distance < shortest_distance) { shortest_distance = distance; closest_marker = marker_; } } return closest_marker; } gedict_t* LocateMarker(vec3_t org) { return LocateNextMarker(org, NULL); } // If the current item is a goal but has been taken and waiting to respawn, set a virtual goal void AssignVirtualGoal_apply(gedict_t *marker_) { int goal_number = marker_->fb.G_; if (goal_number) { gedict_t *test_goal = marker_; if (WaitingToRespawn(marker_)) { int i = 0; for (i = 0; i < NUMBER_PATHS; ++i) { test_goal = marker_->fb.paths[i].next_marker; if (test_goal && (test_goal->fb.G_ == goal_number) && !WaitingToRespawn(test_goal)) { break; } } if (i >= NUMBER_PATHS) { test_goal = marker_; } } marker_->fb.virtual_goal = test_goal; } } // Assign virtual goal to all markers in an items zone void AssignVirtualGoal(gedict_t *item) { gedict_t *marker_; for (marker_ = FirstZoneMarker(item->fb.Z_); marker_; marker_ = marker_->fb.Z_next) { AssignVirtualGoal_apply(marker_); } } qbool ExistsPath(gedict_t *from_marker, gedict_t *to_marker, int *new_path_state) { int i = 0; if ((from_marker == NULL) || (to_marker == NULL)) { return false; } for (i = 0; i < NUMBER_PATHS; ++i) { if (from_marker->fb.paths[i].next_marker == to_marker) { *new_path_state = from_marker->fb.paths[i].flags; return true; } } return false; } void CheckWaterColumn(gedict_t *m, vec3_t m_pos, vec3_t testplace) { m->fb.T |= T_WATER; VectorCopy(m_pos, testplace); while (true) { vec3_t point; VectorCopy(testplace, self->s.v.origin); self->s.v.origin[2] += 16; self->s.v.flags = FL_ONGROUND_PARTIALGROUND; if (!walkmove(self, 0, 0)) { m->fb.T |= T_NO_AIR; return; } VectorCopy(testplace, point); point[2] += 32; if (trap_pointcontents(point[0], point[1], point[2]) == CONTENT_EMPTY) { do { testplace[2] = testplace[2] - 1; VectorCopy(testplace, point); point[2] += 32; } while (trap_pointcontents(point[0], point[1], point[2]) == CONTENT_EMPTY); return; } testplace[2] = testplace[2] + 16; } } #endif QW-Group-ktx-d05d6ca/src/match.c000066400000000000000000001620671475442401000164730ustar00rootroot00000000000000/* * 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 * * * $Id$ */ #include "g_local.h" void NextLevel(void); void IdlebotForceStart(void); void StartMatch(void); void remove_specs_wizards(void); void lastscore_add(void); void StartLogs(void); void StopLogs(void); void ClearDemoMarkers(void); void EM_CorrectStats(void); void MatchEndStats(void); void SM_PrepareTeamsStats(void); void SM_PrepareShowscores(void); static void SM_ExecuteQueuedSpawnEffects(void); void race_match_start(void); qbool race_can_cancel_demo(void); extern int g_matchstarttime; qbool initial_match_spawns; int maxPlayerCount; // Return count of players which have state cs_connected or cs_spawned. // It is weird because used string comparision so I treat it as slow and idiotic but it return more players than CountPlayers(). int WeirdCountPlayers(void) { gedict_t *p; int num; char state[16]; for (num = 0, p = world + 1; p <= world + MAX_CLIENTS; p++) { infokey(p, "*spectator", state, sizeof(state)); if (state[0]) { continue; // ignore spectators } infokey(p, "*state", state, sizeof(state)); if (streq(state, "connected") || streq(state, "spawned")) { num++; } } return num; } float CountPlayers(void) { gedict_t *p; float num = 0; for (p = world; (p = find_plr(p));) { num++; } return num; } float CountBots(void) { gedict_t *p; float num = 0; for (p = world; (p = find_plr(p));) { if (p->isBot) { num++; } } return num; } float CountRPlayers(void) { gedict_t *p; float num = 0; for (p = world; (p = find_plr(p));) { if (p->ready) { num++; } } return num; } float CountTeams(void) { gedict_t *p, *p2; float num = 0; char *s = ""; for (p = world; (p = find_plr(p));) { p->k_flag = 0; } for (p = world; (p = find_plr(p));) { if (p->k_flag || strnull(s = getteam(p))) { continue; } p->k_flag = 1; num++; for (p2 = p; (p2 = find_plr(p2));) { if (streq(s, getteam(p2))) { p2->k_flag = 1; } } } return num; } // return number of teams where at least one member is ready? float CountRTeams(void) { gedict_t *p, *p2; float num = 0; char *s = ""; for (p = world; (p = find_plr(p));) { p->k_flag = 0; } for (p = world; (p = find_plr(p));) { if (p->k_flag || !p->ready || strnull(s = getteam(p))) { continue; } p->k_flag = 1; num++; for (p2 = p; (p2 = find_plr(p2));) { if (streq(s, getteam(p2))) { p2->k_flag = 1; } } } return num; } // count the members in each team and store the max in maxPlayerCount // and return 0 if at least one team has less members than 'memcnt' // else return 1 (even we have more members than memcnt, dunno is this bug <- FIXME) int CheckMembers(float memcnt) { gedict_t *p, *p2; float f1; int retVal = 1; char *s = ""; maxPlayerCount = 0; for (p = world; (p = find_plr(p));) { p->k_flag = 0; } for (p = world; (p = find_plr(p));) { if (p->k_flag) { continue; } p->k_flag = 1; f1 = 1; if (!strnull(s = getteam(p))) { for (p2 = p; (p2 = find_plr(p2));) { if (streq(s, getteam(p2))) { p2->k_flag = 1; f1++; } } } maxPlayerCount = max(f1, maxPlayerCount); if (f1 < memcnt) { retVal = 0; } } return retVal; } extern demo_marker_t demo_markers[]; extern int demo_marker_index; void ListDemoMarkers(void) { int i = 0; if (!demo_marker_index) { return; } G_bprint(2, "%s:\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Demo markers")); for (i = 0; i < demo_marker_index; ++i) { int total = (int)(demo_markers[i].time - match_start_time); G_bprint(2, "%s: %d:%02d \220%s\221\n", redtext("Time"), (total / 60), (total % 60), demo_markers[i].markername); } G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } void EM_on_MatchEndBreak(int isBreak) { gedict_t *p; for (p = world; (p = find_client(p));) { if (isBreak) { on_match_break(p); } else { on_match_end(p); } } } // WARNING: if we are skip log, we are also delete demo void EndMatch(float skip_log) { gedict_t *p; int old_match_in_progress = match_in_progress; char *tmp; float f1; qbool is_real_match_end = !isHoonyModeAny() || HM_is_game_over(); qbool f_modified_done = false, f_ruleset_done = false, f_version_done = false; char *matchtag = ezinfokey(world, "matchtag"); qbool has_matchtag = matchtag != NULL && matchtag[0]; if (match_over || !match_in_progress) { return; } match_over = 1; k_berzerk = 0; remove_projectiles(); // s: zero the flag k_sudden_death = 0; if (!strnull(tmp = cvar_string("_k_host"))) { trap_cvar_set("hostname", tmp); // restore host name at match end } trap_lightstyle(0, "m"); // spec silence { int fpd = iKey(world, "fpd"); fpd = fpd & ~64; localcmd("serverinfo fpd %d\n", fpd); cvar_fset("sv_spectalk", 1); } if (isCA()) { CA_MatchBreak(); } if (isHoonyModeAny()) { G_bprint(2, "The point is over\n"); HM_point_stats(); } else if (deathmatch) { G_bprint(2, "The match is over\n"); } EM_CorrectStats(); if (k_bloodfest) { extern void bloodfest_stats(void); // remove any powerup left for (p = world; (p = nextent(p));) { if (streq(p->classname, "item_artifact_invulnerability") || streq(p->classname, "item_artifact_invisibility") || streq(p->classname, "item_artifact_super_damage")) { ent_remove(p); continue; } } bloodfest_stats(); } if ( /* skip_log || */!deathmatch) { ; } else { if (is_real_match_end && !isRACE()) { ListDemoMarkers(); } if (is_real_match_end) { if (!isCA()) { MatchEndStats(); } lastscore_add(); // save game result somewhere, so we can show it later } } if (is_real_match_end) { for (p = world; (p = find(p, FOFCLSN, "ghost"));) { ent_remove(p); } } StopTimer(skip_log); // WARNING: if we are skip log, we are also delete demo if (is_real_match_end) { for (f1 = 666; k_teamid >= f1; f1++) { localcmd("localinfo %d \"\"\n", (int)f1); //removing key } for (f1 = 1; k_userid >= f1; f1++) { localcmd("localinfo %d \"\"\n", (int)f1); //removing key } } if (old_match_in_progress == 2) { for (p = world; (p = find_plr(p));) { p->ready = 0; // force players be not ready after match is end. if (has_matchtag && cvar("k_on_end_f_modified") && !f_modified_done) { stuffcmd(p, "say f_modified\n"); f_modified_done = true; } if (has_matchtag && cvar("k_on_end_f_ruleset") && !f_ruleset_done) { stuffcmd(p, "say f_ruleset\n"); f_ruleset_done = true; } if (has_matchtag && cvar("k_on_end_f_version") && !f_version_done) { stuffcmd(p, "say f_version\n"); f_version_done = true; } } } EM_on_MatchEndBreak(skip_log); if (isHoonyModeAny()) { qbool demomarker_logged = false; if (!HM_is_game_over()) { match_over = 0; // All bots ready first for (p = world; (p = find_plr(p));) { if (p->isBot) { p->ready = true; } } for (p = world; (p = find_plr(p));) { if (!demomarker_logged) { stuffcmd(p, "//demomark 0 round-%2d\n", HM_current_point()); demomarker_logged = true; } stuffcmd(p, "ready\n"); } } else { for (p = world; (p = find_plr(p));) { stuffcmd(p, "hmstats\n"); } StopLogs(); NextLevel(); } } else { StopLogs(); NextLevel(); } // allow ready/break in bloodfest without map reloading. if (k_bloodfest || isCA()) { match_over = 0; } if (is_real_match_end) { g_matchstarttime = 0; } } void SaveOvertimeStats(void) { gedict_t *p; if (k_overtime) { for (p = world; (p = find_plr(p));) { // save overtime stats p->ps.ot_a = (int)p->s.v.armorvalue; p->ps.ot_items = p->s.v.items; // float p->ps.ot_h = (int)p->s.v.health; } } } void CheckOvertime(void) { // SM_PrepareShowscores() is called in StartMatch(), but in matchless mode this happens when the first player joins. // Therefore, teams != 2 yet and the function doesn't do anything. // This causes matchless CTF to go into perpetual overtime, since "sc = get_scores1() - get_scores2();" calculated below will always return 0. // So, we call this function here to handle this scenario. gedict_t *timer, *ed1, *ed2 ; int teams, players ; int sc; int k_mb_overtime; int k_exttime; SM_PrepareShowscores(); ed1 = get_ed_scores1(); ed2 = get_ed_scores2(); teams = CountTeams(); players = CountPlayers(); sc = get_scores1() - get_scores2(); k_mb_overtime = cvar("k_overtime"); k_exttime = bound(1, cvar("k_exttime"), 999); // at least some reasonable values // In hoonymode the round is timing out, not the match - we're effectively always in suddendeath mode if (isHoonyModeAny()) { HM_draw(); return; } // If 0 no overtime, 1 overtime, 2 sudden death // And if its neither then well we exit if (!k_mb_overtime || ((k_mb_overtime != 1) && (k_mb_overtime != 2) && (k_mb_overtime != 3))) { EndMatch(0); return; } // Overtime. // Ok we have now decided that the game is ending, so decide overtime wise here what to do. if ((isDuel() || isFFA()) && ed1 && ed2) { sc = ed1->s.v.frags - ed2->s.v.frags; } // if( k_matchLess ) { // k_mb_overtime = 0; // no overtime in matchLess mode // } // else if (lgc_enabled()) { k_mb_overtime = 0; // no overtime in lgc mode } if ((isTeam() || isCTF()) && (teams != 2)) { k_mb_overtime = 0; // no overtime in case of less than 2 or more than 2 teams } else if (((isDuel() || isFFA()) && ed1 && ed2) // duel or ffa || ((isTeam() || isCTF()) && (teams == 2) && (players > 1))) // Handle a 2v2 or above team game or 1v1 CTF { if (((k_mb_overtime == 3) && abs(sc) > 1) // tie-break overtime allowed with one frag difference (c) ktpro || ((k_mb_overtime != 3) && abs(sc) > 0)) // time based or sudden death overtime allowed with zero frag difference { k_mb_overtime = 0; } } else { k_mb_overtime = 0; } if (!k_mb_overtime) { EndMatch(0); return; } k_overtime = k_mb_overtime; SaveOvertimeStats(); G_bprint(2, "time over, the game is a draw\n"); if (k_overtime == 1) { // Ok its increase time self->cnt = k_exttime; self->cnt2 = 60; localcmd("serverinfo status \"%d min left\"\n", (int)self->cnt); G_bprint(2, "\220%s\221 minute%s overtime follows\n", dig3(k_exttime), count_s(k_exttime)); self->s.v.nextthink = g_globalvars.time + 1; match_end_time += self->cnt * 60; } else if (k_overtime == 2) { k_sudden_death = SD_NORMAL; match_end_time = 0; } else { k_sudden_death = SD_TIEBREAK; match_end_time = 0; } if (k_sudden_death) { G_bprint(2, "%s %s\n", SD_type_str(), redtext("overtime begins")); // added timer removal at sudden death beginning for (timer = world; (timer = find(timer, FOFCLSN, "timer"));) { ent_remove(timer); } } } // Called every second during a match. cnt = minutes, cnt2 = seconds left. // Tells the time every now and then. void TimerThink(void) { gedict_t *p; int idle_time; float f1, f2; //if in matchless mode, check that the user hasn't exceeded k_matchless_max_idle_time if (k_matchLess && CountPlayers() && match_in_progress && k_matchLess_idle_time) { for (p = world; (p = find_plr(p));) { idle_time = (int)(g_globalvars.time - p->attack_finished); if (idle_time > k_matchLess_idle_time) { G_sprint( p, 2, "You were forced to reconnect as spectator by exceeding the maximum idle time of %i seconds.\n", k_matchLess_idle_time); stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "spectator 1\n"); if (!strnull(ezinfokey(p, "Qizmo"))) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "say ,:dis\nwait;wait;wait; say ,:reconnect\n"); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "disconnect\nwait;wait;reconnect\n"); } } else if (idle_time == k_matchLess_idle_warn) { G_sprint( p, 2, "\207%s You will be forced to spectate if you do not fire within %i seconds!\n", redtext("WARNING:"), (k_matchLess_idle_time - k_matchLess_idle_warn)); } } } if (!k_matchLess && !CountPlayers()) { EndMatch(1); return; } if (k_sudden_death) { return; } if ((self->k_teamnum < g_globalvars.time) && !k_checkx) { k_checkx = 1; // global which set to true when some time spend after match start } // berzerk if (k_berzerktime != 0) { f1 = k_berzerktime; f2 = floor(f1 / 60); f1 = f1 - (f2 * 60); f2 = f2 + 1; if ((self->cnt2 == f1) && (self->cnt == f2)) { G_bprint(2, "BERZERK!!!!\n"); trap_lightstyle(0, "ob"); k_berzerk = 1; for (p = world; (p = find_plr(p));) { if (strcmp(p->netname, "") && p->s.v.health > 0) { p->s.v.items = (int)p->s.v.items | (IT_QUAD | IT_INVULNERABILITY); p->super_time = 1; p->super_damage_finished = g_globalvars.time + 3600; p->invincible_time = 1; p->invincible_finished = g_globalvars.time + 2; } } } } (self->cnt2)--; if (!self->cnt2) { self->cnt2 = 60; self->cnt -= 1; localcmd("serverinfo status \"%d min left\"\n", (int)self->cnt); if (!self->cnt) { CheckOvertime(); return; } G_bprint(2, "\220%s\221 minute%s remaining\n", dig3(self->cnt), count_s(self->cnt)); self->s.v.nextthink = g_globalvars.time + 1; if (k_showscores && !isCA()) { if ((current_umode < um2on2on2) || (current_umode > um4on4on4)) { int sc = get_scores1() - get_scores2(); if (sc) { G_bprint(2, "%s \220%s\221 leads by %s frag%s\n", redtext("Team"), cvar_string((sc > 0 ? "_k_team1" : "_k_team2")), dig3(abs((int)sc)), count_s(abs((int)sc))); } else { G_bprint(2, "The game is currently a tie\n"); } } else { // if the current UserMode is 2on2on2, 3on3on3, 4on4on4, we have 3 teams int s1 = get_scores1(); int s2 = get_scores2(); int s3 = get_scores3(); int sc; if ((s1 > s2) && (s1 > s3)) { // Team 1 is leading if (s2 > s3) { sc = get_scores1() - get_scores2(); } else { sc = get_scores1() - get_scores3(); } G_bprint(2, "%s \220%s\221 leads by %s frag%s\n", redtext("Team"), cvar_string("_k_team1"), dig3(abs((int)sc)), count_s(abs((int)sc))); } else if ((s2 > s1) && (s2 > s3)) { // Team 2 is leading if (s1 > s3) { sc = get_scores2() - get_scores1(); } else { sc = get_scores2() - get_scores3(); } G_bprint(2, "%s \220%s\221 leads by %s frag%s\n", redtext("Team"), cvar_string("_k_team2"), dig3(abs((int)sc)), count_s(abs((int)sc))); } else if ((s3 > s1) && (s3 > s2)) { // Team 3 is leading if (s1 > s2) { sc = get_scores3() - get_scores1(); } else { sc = get_scores3() - get_scores3(); } G_bprint(2, "%s \220%s\221 leads by %s frag%s\n", redtext("Team"), cvar_string("_k_team3"), dig3(abs((int)sc)), count_s(abs((int)sc))); } else { G_bprint(2, "The game is currently a tie\n"); } } } return; } if ((self->cnt == 1) && ((self->cnt2 == 30) || (self->cnt2 == 15) || (self->cnt2 <= 10))) { G_bprint(2, "\220%s\221 second%s\n", dig3(self->cnt2), count_s(self->cnt2)); } self->s.v.nextthink = g_globalvars.time + 1; } // remove/add some items from map regarding dmm and game mode void SM_PrepareMap(void) { gedict_t *p; if (isCTF()) { SpawnRunes(cvar("k_ctf_runes")); } // this must be removed in any cases remove_projectiles(); for (p = world; (p = nextent(p));) { // going for the if content record.. if (isRA() || isRACE() || ((deathmatch == 4) && (cvar("k_instagib") || cvar("k_midair"))) || cvar("k_noitems") || k_bloodfest) { if (streq(p->classname, "weapon_nailgun") || streq(p->classname, "weapon_supernailgun") || streq(p->classname, "weapon_supershotgun") || streq(p->classname, "weapon_rocketlauncher") || streq(p->classname, "weapon_grenadelauncher") || streq(p->classname, "weapon_lightning") || streq(p->classname, "item_shells") || streq(p->classname, "item_spikes") || streq(p->classname, "item_rockets") || streq(p->classname, "item_cells") || streq(p->classname, "item_health") || streq(p->classname, "item_armor1") || streq(p->classname, "item_armor2") || streq(p->classname, "item_armorInv") || streq(p->classname, "item_artifact_invulnerability") || streq(p->classname, "item_artifact_envirosuit") || streq(p->classname, "item_artifact_invisibility") || streq(p->classname, "item_artifact_super_damage")) { soft_ent_remove(p); continue; } } if (deathmatch == 2) { if (streq(p->classname, "item_armor1") || streq(p->classname, "item_armor2") || streq(p->classname, "item_armorInv")) { soft_ent_remove(p); continue; } } if (deathmatch >= 4) { if (streq(p->classname, "weapon_nailgun") || streq(p->classname, "weapon_supernailgun") || streq(p->classname, "weapon_supershotgun") || streq(p->classname, "weapon_rocketlauncher") || streq(p->classname, "weapon_grenadelauncher") || streq(p->classname, "weapon_lightning")) { // no weapons for any of this deathmatches (4 or 5) soft_ent_remove(p); continue; } if (deathmatch == 4) { if (streq(p->classname, "item_shells") || streq(p->classname, "item_spikes") || streq(p->classname, "item_rockets") || streq(p->classname, "item_cells") || (streq(p->classname, "item_health") && ((int)p->s.v.spawnflags & H_MEGA))) { // no weapon ammo and megahealth for dmm4 soft_ent_remove(p); continue; } } } if (k_killquad && streq(p->classname, "item_artifact_super_damage")) { // no normal quad in killquad mode. soft_ent_remove(p); continue; } } ClearBodyQue(); // hide corpses } // put clients in server and reset some params static void SM_PrepareClients(void) { int hdc, i, j, player_count = 0; char *pl_team; gedict_t *p, *temp; gedict_t *players[MAX_CLIENTS]; qbool hoonymode_reset = isHoonyModeAny() && HM_current_point() > 0; k_teamid = 666; localcmd("localinfo 666 \"\"\n"); trap_executecmd(); // <- this really needed initial_match_spawns = true; for (p = world; (p = find_plr(p));) { players[player_count++] = p; } for (i = player_count - 1; i > 0; i--) { j = rand() % (i + 1); temp = players[i]; players[i] = players[j]; players[j] = temp; } for (j = 0; j < player_count; j++) { p = players[j]; if (!k_matchLess) { // skip setup k_teamnum in matchLess mode pl_team = getteam(p); p->k_teamnum = 0; if (!strnull(pl_team)) { i = 665; while (k_teamid > i && !p->k_teamnum) { i++; if (streq(pl_team, ezinfokey(world, va("%d", i)))) { p->k_teamnum = i; } } if (!p->k_teamnum) { // team not found in localinfo, so put it in i++; p->k_teamnum = k_teamid = i; localcmd("localinfo %d \"%s\"\n", i, pl_team); trap_executecmd(); // <- this really needed } } else p->k_teamnum = 666; } if (!hoonymode_reset) { p->kills = p->suicides = p->friendly = p->deaths = p->s.v.frags = 0; } hdc = p->ps.handicap; // save player handicap if (!hoonymode_reset) { memset((void*) &(p->ps), 0, sizeof(p->ps)); // clear player stats WS_Reset(p); // force reset "new weapon stats" } p->ps.handicap = hdc; // restore player handicap if (isRA()) { if (isWinner(p) || isLoser(p)) { setfullwep(p); } continue; } // ignore k_respawn() in case of coop unless bloodfest if (!deathmatch && !k_bloodfest) { continue; } // ignore k_respawn() in case of CA if (isCA()) { continue; } // ignore k_respawn() in case of race mode if (isRACE()) { continue; } k_respawn(p, false); p->k_pauseRequests = MAX_PAUSE_REQUESTS; } initial_match_spawns = false; // now that every player is spawned, do sounds & fog effect SM_ExecuteQueuedSpawnEffects(); } // This creates visual effect & sound effects for players at start of match // See bug #115... if 2 players spawn next to each other, the first player hears the second, but the second only hears the first based on final location during pre-war static void SM_ExecuteQueuedSpawnEffects(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { if (p->spawn_effect_queued) { vec3_t fog_org; trap_makevectors(p->s.v.angles); VectorMA(p->s.v.origin, 20, g_globalvars.v_forward, fog_org); spawn_tfog(fog_org); play_teleport(p); p->spawn_effect_queued = false; } } } void SM_PrepareShowscores(void) { gedict_t *p; char *team1 = ""; char *team2 = ""; char *team3 = ""; if (k_matchLess && !isCTF()) // skip this in matchLess mode, unless CTF matchless (otherwise causes unlimited overtime because "sc" is always = 0 in CheckOvertime()) { return; } if (((!isTeam() && !isCTF()) || ((CountRTeams() != 2) && (CountRTeams() != 3))) && !(isCTF() && k_matchLess)) // we need 2 ready teams, unless CTF matchless { return; } if ((p = find_plr(world))) { team1 = getteam(p); } if (strnull(team1)) { return; } while ((p = find_plr(p))) { team2 = getteam(p); if (strneq(team1, team2)) { break; } } if (strnull(team2) || streq(team1, team2)) { return; } k_showscores = 1; cvar_set("_k_team1", team1); cvar_set("_k_team2", team2); if ((current_umode >= um2on2on2) && (current_umode <= um4on4on4)) { // let's see if there is a player with a 3rd team while ((p = find_plr(p))) { team3 = getteam(p); if (strneq(team1, team3) && strneq(team2, team3)) { break; } } if (strnull(team3) || streq(team1, team3) || streq(team2, team3)) { return; } cvar_set("_k_team3", team3); } } void SM_PrepareHostname(void) { char *team1 = cvar_string("_k_team1"); char *team2 = cvar_string("_k_team2"); cvar_set("_k_host", cvar_string("hostname")); // save host name at match start if (k_showscores && !strnull(team1) && !strnull(team2)) { if ((current_umode < um2on2on2) || (current_umode > um4on4on4)) { cvar_set("hostname", va("%s (%.4s vs. %.4s)\207", cvar_string("hostname"), team1, team2)); } else { char *team3 = cvar_string("_k_team3"); cvar_set("hostname", va("%s (%.4s vs. %.4s vs. %.4s)\207", cvar_string("hostname"), team1, team2, team3)); } } else { cvar_set("hostname", va("%s\207", cvar_string("hostname"))); } } void SM_on_MatchStart(void) { gedict_t *p; for (p = world; (p = find_client(p));) { on_match_start(p); } } // Reset player frags and start the timer. void HideSpawnPoints(void); void StartMatch(void) { char date[64]; // reset bloodfest vars. bloodfest_reset(); k_nochange = 0; k_showscores = 0; k_standby = 0; k_checkx = 0; k_userid = 1; localcmd("localinfo 1 \"\"\n"); trap_executecmd(); // <- this really needed first_rl_taken = false; // no one took rl yet SM_PrepareMap(); // remove/add some items from map regardind with dmm and game mode HideSpawnPoints(); match_start_time = g_globalvars.time; g_matchstarttime = (int)(g_globalvars.time * 1000); match_in_progress = 2; // Disable berzerk at start k_berzerk = 0; // Get berzerk mode time if (cvar("k_bzk")) { k_berzerktime = cvar("k_btime"); } else { k_berzerktime = 0; } lastTeamLocationTime = -TEAM_LOCATION_UPDATE_TIME; // update on next frame remove_specs_wizards(); // remove wizards SM_PrepareClients(); // put clients in server and reset some params if (!QVMstrftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %Z", 0)) { date[0] = 0; } if (deathmatch && (!isHoonyModeAny() || (HM_current_point() == 0))) { if (date[0]) { G_bprint(2, "matchdate: %s\n", date); } if (!k_matchLess || cvar("k_matchless_countdown")) { G_bprint(2, "%s\n", redtext("The match has begun!")); } } // spec silence { int fpd = iKey(world, "fpd"); int k_spectalk = (coop ? 1 : bound(0, cvar("k_spectalk"), 1)); cvar_fset("sv_spectalk", k_spectalk); fpd = (k_spectalk) ? (fpd & ~64) : (fpd | 64); localcmd("serverinfo fpd %d\n", fpd); } self->k_teamnum = g_globalvars.time + 3; //dirty i know, but why waste space? // FIXME: waste space, but be clean if (isHoonyModeAny() && HM_timelimit() > 0) { int minutes = bound(0, HM_timelimit() / 60, 9999); int seconds = HM_timelimit() % 60; if (seconds) { ++minutes; } else { seconds = 60; } self->cnt = minutes; self->cnt2 = seconds; localcmd("serverinfo status \"%d min left\"\n", minutes); match_end_time = match_start_time + (minutes - 1) * 60 + seconds; } else { self->cnt = bound(0, timelimit, 9999); self->cnt2 = 60; localcmd("serverinfo status \"%d min left\"\n", (int)timelimit); match_end_time = match_start_time + self->cnt * 60; } self->think = (func_t) TimerThink; self->s.v.nextthink = g_globalvars.time + 1; SM_PrepareShowscores(); SM_PrepareHostname(); SM_PrepareTeamsStats(); SM_PrepareCA(); SM_on_MatchStart(); ClearDemoMarkers(); StartLogs(); #ifdef BOT_SUPPORT BotsMatchStart(); #endif if (!self->cnt) { ent_remove(self); // timelimit == 0, so match will end no due to timelimit but due to fraglimit or something } if (isRACE()) { race_match_start(); } stuffcmd_flags(world, STUFFCMD_DEMOONLY, "//ktx matchstart\n"); cvar_fset("qtv_sayenabled", 0); } // just check if someone using handicap static qbool handicap_in_use(void) { gedict_t *p; int from; for (from = 0, p = world; (p = find_plrghst(p, &from));) { if (GetHandicap(p) != 100) { return true; } } return false; } void PersonalisedCountdown(char *baseText) { char text[1024]; gedict_t *p; for (p = world; (p = find_plr(p)); /**/) { strlcpy(text, baseText, sizeof(text)); if (HM_current_point_type() == HM_PT_SET) { strlcat(text, redtext("* Set Point *"), sizeof(text)); strlcat(text, "\n\n", sizeof(text)); } if (p->k_hoony_new_spawn && !strnull(p->k_hoony_new_spawn->targetname)) { strlcat(text, va("Next %8.8s\n", redtext(p->k_hoony_new_spawn->targetname)), sizeof(text)); if (timelimit) { strlcat(text, va("%s %3s\n", "Timelimit", dig3(timelimit)), sizeof(text)); } else if (isHoonyModeDuel() && world->hoony_timelimit) { int minutes = world->hoony_timelimit / 60; int seconds = world->hoony_timelimit % 60; if (minutes == 0) { strlcat(text, va("%s %3ss\n", "Duration", dig3(seconds)), sizeof(text)); } else if (seconds == 0) { strlcat(text, va("%s %3sm\n", "Duration", dig3(minutes)), sizeof(text)); } else { strlcat(text, va("%s %1s:%2s\n", "Duration", dig3(minutes), dig3(seconds)), sizeof(text)); } } if (!strnull(world->hoony_defaultwinner)) { if (streq(p->k_hoony_new_spawn->targetname, world->hoony_defaultwinner)) { strlcat(text, va("Draw %s\n", redtext(" you win")), sizeof(text)); } else { strlcat(text, va("Draw %s\n", redtext("you lose")), sizeof(text)); } } } G_centerprint(p, "%s", text); } } void PrintCountdown(int seconds) { // Countdown: seconds // // // EQL semifinal // // Deathmatch x // Mode D u e l | T e a m | F F A | C O O P | BLOODFST | C T F | RA | CA // Spawnmodel KTX | bla bla bla // optional // Antilag On|Off // NoItems On // optional // Midair On // optional // Instagib On // optional // Yawnmode On // optional // Airstep On // optional // TmOverlay On // optional // Teamplay x // Timelimit xx // Fraglimit xxx // Overtime xx Overtime printout, supports sudden death display // Powerups On|Off|QPRS // Dmgfrags On // optional // Noweapon // Handicap in use // optional char text[1024] = { 0 }; char *mode = ""; char *ot = ""; char *nowp = ""; char *matchtag = redtext(ezinfokey(world, "matchtag")); strlcat(text, va("%s: %2s\n\n\n", redtext("Countdown"), dig3(seconds)), sizeof(text)); // if (matchtag[0]) { // strlcat(text, va("matchtag %s\n\n\n", matchtag), sizeof(text)); // } // else { // strlcat(text, "no matchtag\n\n\n", sizeof(text)); // } if (isHoonyModeDuel() && seconds <= 3) { PersonalisedCountdown(text); return; } // useless in RA if (!isRA() && !coop && !isRACE()) { strlcat(text, va("%s %2s\n", "Deathmatch", dig3(deathmatch)), sizeof(text)); } if (k_bloodfest) { mode = redtext("BLOODFST"); } else if (coop) { mode = redtext("C O O P"); } else if (isRA()) { mode = redtext("RA"); } else if (isCA()) { if (cvar("k_clan_arena") == 2) { mode = redtext("Wipeout"); } else { mode = redtext("CA"); } } else if (isHoonyModeDuel()) { mode = redtext("Hoony"); } else if (lgc_enabled()) { mode = redtext("LGC"); } else if (isHoonyModeTDM()) { mode = redtext("BlitzTDM"); } else if (isRACE()) { mode = redtext("R A C E"); } else if (isDuel()) { mode = redtext("D u e l"); } else if (isTeam()) { mode = redtext("T e a m"); } else if (isFFA()) { mode = redtext("F F A"); } else if (isCTF()) { mode = redtext("C T F"); } else { mode = redtext("Unknown"); } strlcat(text, va("%s %8s\n", "Mode", mode), sizeof(text)); if (isCA()) { strlcat(text, va("%s %3s\n", "RoundWins", dig3(CA_wins_required())), sizeof(text)); } else if (isHoonyModeTDM() && HM_current_point()) { strlcat(text, "\n", sizeof(text)); strlcat(text, (char*) HM_round_explanation(), sizeof(text)); strlcat(text, (char*) HM_series_explanation(), sizeof(text)); strlcat(text, "\n", sizeof(text)); } else if (isRACE()) { if (race.round_number >= race.rounds) { strlcat(text, va("Round %7s\n", redtext("final")), sizeof(text)); } strlcat(text, va("%s %9s\n", "Pts", race_scoring_system_name()), sizeof(text)); } if (!(isHoonyModeTDM() && HM_current_point())) { // if ( cvar( "k_spw" ) != 3 ) if (!isRACE()) { strlcat(text, va("%s %4s\n", "Respawns", respawn_model_name_short(cvar("k_spw"))), sizeof(text)); } if (cvar("sv_antilag")) { strlcat(text, va("%s %5s\n", "Antilag", dig3((int)cvar("sv_antilag"))), sizeof(text)); } if (cvar("k_noitems") && !isRACE()) { strlcat(text, va("%s %5s\n", "NoItems", redtext("on")), sizeof(text)); } if (cvar("k_midair")) { strlcat(text, va("%s %6s\n", "Midair", redtext("on")), sizeof(text)); } if (cvar("k_instagib")) { strlcat(text, va("%s %4s\n", "Instagib", redtext("on")), sizeof(text)); } if (k_yawnmode) { strlcat(text, va("%s %4s\n", "Yawnmode", redtext("on")), sizeof(text)); } if (cvar("pm_airstep")) { strlcat(text, va("%s %5s\n", "Airstep", redtext("on")), sizeof(text)); } vw_enabled = vw_available && cvar("k_allow_vwep") && cvar("k_vwep"); if (vw_enabled && !isRACE()) { strlcat(text, va("%s %8s\n", "VWep", redtext("on")), sizeof(text)); } if (cvar("k_teamoverlay") && tp_num() && !isDuel() && !isRACE()) { strlcat(text, va("%s %3s\n", "TmOverlay", redtext("on")), sizeof(text)); } if (!isRA() && (isTeam() || isCTF())) { strlcat(text, va("%s %4s\n", "Teamplay", dig3(teamplay)), sizeof(text)); } } if (isHoonyModeAny()) { int hm_timelimit = HM_timelimit(); if (hm_timelimit) { int minutes = hm_timelimit / 60; int seconds = hm_timelimit % 60; if (minutes == 0) { strlcat(text, va("%s %3ss\n", "Duration", dig3(seconds)), sizeof(text)); } else if (seconds == 0) { strlcat(text, va("%s %3sm\n", "Duration", dig3(minutes)), sizeof(text)); } else { strlcat(text, va("%s %1s:%2s\n", "Duration", dig3(minutes), dig3(seconds)), sizeof(text)); } } if (HM_rounds()) { strlcat(text, va(" %s %2s/%2s\n", "Round", dig3(HM_current_point() + 1), dig3(HM_rounds())), sizeof(text)); } } else if (timelimit) { strlcat(text, va("%s %3s\n", "Timelimit", dig3(timelimit)), sizeof(text)); } if (!isHoonyModeAny() && fraglimit) { strlcat(text, va("%s %3s\n", "Fraglimit", dig3(fraglimit)), sizeof(text)); } switch ((int)cvar("k_overtime")) { case 0: ot = redtext("off"); break; case 1: ot = dig3(cvar("k_exttime")); break; case 2: ot = redtext("sd"); break; case 3: ot = va("%s %s", dig3(tiecount()), redtext("tb")); break; default: ot = redtext("Unkn"); break; } if (!isHoonyModeAny()) { if (timelimit && cvar("k_overtime")) { strlcat(text, va("%s %4s\n", "Overtime", ot), sizeof(text)); } } if (!isRA() && Get_Powerups() && strneq("off", Get_PowerupsStr())) { strlcat(text, va("%s %4s\n", "Powerups", redtext(Get_PowerupsStr())), sizeof(text)); } if (cvar("k_dmgfrags")) { strlcat(text, va("%s %4s\n", "Dmgfrags", redtext("on")), sizeof(text)); } if (cvar("k_freshteams")) { strlcat(text, va("%s %2s\n", "&c07fFreshTeams&r", redtext("on")), sizeof(text)); } if (cvar("k_nosweep")) { strlcat(text, va("%s %5s\n", "NoSweep", redtext("on")), sizeof(text)); } if ((deathmatch == 4) && !cvar("k_midair") && !cvar("k_instagib") && !strnull(nowp = str_noweapon((int)cvar("k_disallow_weapons") & DA_WPNS))) { strlcat(text, va("\n%s %4s\n", "Noweapon", redtext(nowp[0] == 32 ? (nowp + 1) : nowp)), sizeof(text)); } if (handicap_in_use()) { strlcat(text, "\n" "Handicap in use\n", sizeof(text)); } if (isHoonyModeAny()) { if (((HM_current_point() % 2) == 0)) { strlcat(text, va("\n%-13s\n", redtext("New spawns")), sizeof(text)); } else { strlcat(text, va("\n%-13s\n", redtext("Switch spawns")), sizeof(text)); } } if (tot_mode_enabled()) { strlcat(text, va("\nTribe of Tjernobyl mode %2s\n", redtext("on")), sizeof(text)); strlcat(text, va("Break on death %11s\n", (int)cvar(FB_CVAR_BREAK_ON_DEATH) ? redtext("on") : redtext("off")), sizeof(text)); strlcat(text, va("Bot weapon %15s\n", redtext(WpName(FrogbotWeapon()))), sizeof(text)); strlcat(text, va("Bot health %15s\n", dig3(FrogbotHealth())), sizeof(text)); strlcat(text, va("Bot skill %16s\n", dig3(FrogbotSkillLevel())), sizeof(text)); strlcat(text, va("Quad damage multiplier %3s\n", dig3(FrogbotQuadMultiplier())), sizeof(text)); } if (matchtag[0]) { strlcat(text, va("\nmatchtag %s\n\n\n", matchtag), sizeof(text)); } else { strlcat(text, "\nno matchtag\n\n\n", sizeof(text)); } G_cp2all("%s", text); } qbool isCanStart(gedict_t *s, qbool forceMembersWarn) { int k_lockmin = (isCA() || isRACE()) ? 2 : cvar("k_lockmin"); int k_lockmax = (isCA() || isRACE()) ? 2 : cvar("k_lockmax"); int k_membercount = cvar("k_membercount"); int i = CountRTeams(); int sub; int nready; char *txt = ""; gedict_t *p; // no limits in RA if (isRA()) { return true; } // some limits in duel... if (isDuel()) { sub = CountPlayers() - 2; if (sub > 0) // we need two players in duel... { txt = va("Get rid of %d player%s!\n", sub, count_s(sub)); if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } } // no team/members rules limitation in non team game if (!isTeam() && !isCTF()) { return true; } // below Team or CTF game modes and limits... for (p = world; (p = find_plr(p));) { if (strnull(getteam(p))) { txt = "Get rid of players with empty team\n"; if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } } if (i < k_lockmin) { sub = k_lockmin - i; txt = va("%d more team%s required!\n", sub, count_s(sub)); if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } if (i > k_lockmax) { sub = i - k_lockmax; txt = va("Get rid of %d team%s!\n", sub, count_s(sub)); if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } nready = 0; for (p = world; (p = find_plr(p));) { if (p->ready) { nready++; } } if (!CheckMembers(k_membercount)) { if (!forceMembersWarn) // warn anyway if we want { if (nready != k_attendees && !s) { return false; // inform not in all cases, less annoying } } txt = va("%s %d %s\n" "%s\n", redtext("Server wants at least"), k_membercount, redtext("players in each team"), redtext("Waiting...")); if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } if (isCTF() && !k_matchLess) // In matchless CTF, the "this map does not support CTF mode" would get spammed constantly in an unsupported map. So, don't bother returning false. { // can't really play ctf if map doesn't have flags gedict_t *rflag = find(world, FOFCLSN, "item_flag_team1"); gedict_t *bflag = find(world, FOFCLSN, "item_flag_team2"); if (!rflag || !bflag) { txt = "This map does not support CTF mode\n"; if (s) { G_sprint(s, 2, "%s", txt); } else { G_bprint(2, "%s", txt); } return false; } } return true; } void standby_think(void) { gedict_t *p; if (match_in_progress == 1 && !isRA()) { k_standby = 1; for (p = world; (p = find_plr(p));) { if (!strnull(p->netname)) { //set to ghost, 0.2 second before matchstart if (isHoonyModeDuel() && p->k_hoony_new_spawn) { // move viewpoint to selected spawn VectorCopy(p->k_hoony_new_spawn->s.v.origin, p->s.v.origin); p->s.v.origin[2] += 1; VectorCopy(p->k_hoony_new_spawn->s.v.angles, p->s.v.angles); p->s.v.fixangle = true; setnowep(p); } p->s.v.takedamage = 0; p->s.v.solid = 0; p->s.v.movetype = 0; p->s.v.modelindex = 0; p->model = ""; } } } ent_remove(self); } // Called every second during the countdown. void TimerStartThink(void) { gedict_t *p; k_attendees = CountPlayers(); if (!isCanStart( NULL, true)) { G_bprint(2, "Aborting...\n"); StopTimer(1); return; } self->cnt2 -= 1; if (self->cnt2 == 1) { p = spawn(); p->s.v.owner = EDICT_TO_PROG(world); p->classname = "standby_th"; p->s.v.nextthink = g_globalvars.time + 0.8; p->think = (func_t) standby_think; if (isHoonyModeAny()) { HM_reset_map(); } } else if (self->cnt2 <= 0) { G_cp2all("%s", ""); StartMatch(); return; } PrintCountdown(self->cnt2); if (self->cnt2 < 6) { char *gr = redtext("Get ready"); for (p = world; (p = find_client(p));) { if ((p->ct == ctPlayer) && !p->ready) { G_sprint(p, 2, "%s!\n", gr); } stuffcmd(p, "play buttons/switch04.wav\n"); } } self->s.v.nextthink = g_globalvars.time + 1; } void ShowMatchSettings(void) { int i; char *txt = ""; // G_bprint(2, "Spawnmodel: %s\n", redtext( respawn_model_name( cvar( "k_spw" ) ) )); // changed to print only if other than default if ((i = get_fair_pack())) { // Output the Fairpack setting here switch (i) { case 0: txt = "off"; break; case 1: txt = "best weapon"; break; case 2: txt = "last weapon fired"; break; default: txt = "!Unknown!"; break; } G_bprint(2, "Fairpacks setting: %s\n", redtext(txt)); } // print qizmo ( FPD ) settings if (!isHoonyModeAny() || HM_current_point() == 0) { i = iKey(world, "fpd"); if (i & 170) { char buf[256] = { 0 }; if (i & 2) { strlcat(buf, " timer", sizeof(buf)); } if (i & 8) { strlcat(buf, " lag", sizeof(buf)); } if (i & 32) { strlcat(buf, " enemy", sizeof(buf)); } if (i & 128) { strlcat(buf, " point", sizeof(buf)); } G_bprint(2, "QiZmo:%s disabled\n", redtext(buf)); } } } // duel_dag_vs_zu-zu[dm3] // team_no!_vs_fom[dm3] // ctf_no!_vs_fom[dm3] // ffa_10[dm3] // where 10 is count of players // ra_10[dm3] // where 10 is count of players // unknown_10[dm3] // where 10 is count of players char* CompilateDemoName(void) { static char demoname[60]; char date[128], *fmt; char teams[MAX_CLIENTS][MAX_TEAM_NAME]; int i; int players; gedict_t *p; char *name, *vs; demoname[0] = 0; if (isRA()) { strlcat(demoname, va("ra_%d", (int)CountPlayers()), sizeof(demoname)); } else if (isCA()) { if (cvar("k_clan_arena") == 1) { strlcat(demoname, "ca", sizeof(demoname)); } else { strlcat(demoname, "wipeout", sizeof(demoname)); } getteams(teams); for (vs = "_", i = 0; i < MAX_CLIENTS; i++) { if (strnull(teams[i])) { break; } strlcat(demoname, vs, sizeof(demoname)); strlcat(demoname, teams[i], sizeof(demoname)); vs = "_vs_"; } } else if (isRACE() && !race_match_mode()) { players = 0; strlcat(demoname, "race", sizeof(demoname)); for (vs = "_", p = world; (p = find_plr(p));) { if (strnull(name = getname(p)) || !(p->racer)) { continue; } if (players < 2) { strlcat(demoname, vs, sizeof(demoname)); strlcat(demoname, name, sizeof(demoname)); } else if (players == 2) { strlcat(demoname, vs, sizeof(demoname)); strlcat(demoname, "others", sizeof(demoname)); } ++players; } } else if (isDuel()) { strlcat(demoname, "duel", sizeof(demoname)); if (isRACE()) { strlcat(demoname, "_race", sizeof(demoname)); } if (cvar("k_midair")) { strlcat(demoname, "_midair", sizeof(demoname)); } if (cvar("k_instagib")) { strlcat(demoname, "_instagib", sizeof(demoname)); } for (vs = "_", p = world; (p = find_plr(p));) { if (strnull(name = getname(p))) { continue; } if (isRACE() && !(p->race_participant)) { continue; } strlcat(demoname, vs, sizeof(demoname)); strlcat(demoname, name, sizeof(demoname)); vs = "_vs_"; } } else if (isTeam() || isCTF()) { char teams[MAX_CLIENTS][MAX_TEAM_NAME]; int cnt = getteams(teams); int clt = cvar("maxclients"); //CountPlayers(); // guess is this XonX if ((clt > 1) && (cnt > 1) && !(clt % cnt)) { clt /= cnt; // yes } else { clt = 0; // no } if (isTeam()) { const char *strCurrentUmode; // The parameter is (current_umode-1), because the UserModes_t enum has `umUnknown` as first element, // but the um_list[] array doesn't have an 'empty' first row strCurrentUmode = um_name_byidx(current_umode-1); if (strCurrentUmode != NULL) { strlcat(demoname, (char *)strCurrentUmode, sizeof(demoname)); } else { // Something is wrong with current_umode. Let's use the legacy format strlcat(demoname, (clt ? va("%don%d", clt, clt) : "team"), sizeof(demoname)); } } else { strlcat(demoname, "ctf", sizeof(demoname)); } if (isRACE()) { strlcat(demoname, "_race", sizeof(demoname)); } for (vs = "_", i = 0; i < MAX_CLIENTS; i++) { if (strnull(teams[i])) { break; } strlcat(demoname, vs, sizeof(demoname)); strlcat(demoname, teams[i], sizeof(demoname)); vs = "_vs_"; } } else if (isFFA()) { if (isRACE()) { strlcat(demoname, "race_", sizeof(demoname)); } strlcat(demoname, va("ffa_%d", (int)CountPlayers()), sizeof(demoname)); } else { if (isRACE()) { strlcat(demoname, "race_", sizeof(demoname)); } strlcat(demoname, va("unknown_%d", (int)CountPlayers()), sizeof(demoname)); } if (isRACE()) { strlcat(demoname, va("[%s_r%02d]", mapname, race.active_route), sizeof(demoname)); } else { strlcat(demoname, va("[%s]", mapname), sizeof(demoname)); } fmt = cvar_string("k_demoname_date"); if (!strnull(fmt) && QVMstrftime(date, sizeof(date), fmt, 0)) { strlcat(demoname, date, sizeof(demoname)); } return demoname; } void StartDemoRecord(void) { char *demoname; // extralog should be set by easyrecord and if we skip recording we will have it set to WRONG value. // So this set it at least to something reasonable ffs. cvar_set("extralogname", ""); if (cvar("demo_tmp_record")) { // FIXME: TODO: make this more like ktpro qbool record = false; if (isRACE()) { record = true; } else if (!deathmatch) { record = false; } else if (isFFA() && cvar("demo_skip_ktffa_record")) { record = false; } else if (isHoonyModeAny() && HM_current_point() > 0) { record = false; // don't try to record (segfault) when already recording } else { record = true; } if (record) { if (!strnull(cvar_string("serverdemo"))) { localcmd("sv_democancel\n"); // demo is recording, cancel before new one } demoname = CompilateDemoName(); localcmd("sv_demoeasyrecord \"%s\"\n", demoname); } } } // Spawns the timer and starts the countdown. void StartTimer(void) { gedict_t *timer; if (match_in_progress || intermission_running || match_over) { return; } if (k_matchLess && !CountPlayers()) { return; // can't start countdown in matchless mode due to no players, } k_force = 0; for (timer = world; (timer = find(timer, FOFCLSN, "idlebot"));) { ent_remove(timer); } for (timer = world; (timer = find(timer, FOFCLSN, "timer"));) { ent_remove(timer); } for (timer = world; (timer = find(timer, FOFCLSN, "standby_th"));) { ent_remove(timer); } if (!k_matchLess) { ShowMatchSettings(); } if (!k_matchLess || k_bloodfest) { for (timer = world; (timer = find_client(timer));) { stuffcmd(timer, "play items/protect2.wav\n"); } } timer = spawn(); timer->s.v.owner = EDICT_TO_PROG(world); timer->classname = "timer"; timer->cnt = 0; timer->cnt2 = max(3, (int)cvar("k_count")); // at the least we want a 3 second countdown if (isHoonyModeDuel() && (HM_current_point() > 0)) { timer->cnt2 = 3; // first point gets usual 10 seconds, next points gets less } if (k_bloodfest) { // at the least 5 second countdown in bloodfest mode. timer->cnt2 = max(5, (int)cvar("k_count")); } else if (!deathmatch) { // no countdown in coop or similar modes. timer->cnt2 = 0; } else if (k_matchLess) { if (!cvar("k_matchless_countdown")) { timer->cnt2 = 0; // no countdown if variable is not specified. } } (timer->cnt2)++; timer->s.v.nextthink = g_globalvars.time + 0.001; timer->think = (func_t) TimerStartThink; match_in_progress = 1; localcmd("serverinfo status Countdown\n"); StartDemoRecord(); // if allowed } static qbool match_can_cancel_demo(void) { char matchtag[64] = { 0 }; int k_demo_mintime = bound(0, cvar("k_demo_mintime"), 3600); if (!match_start_time) { return true; // match not started } #ifdef BOT_SUPPORT // if any bots involved, /break is a standard cancel, regardless of matchtag if (CountBots() == 0) { #endif // don't cancel demo for match with matchtag infokey(world, "matchtag", matchtag, sizeof(matchtag)); if (!strnull(matchtag)) { return false; } #ifdef BOT_SUPPORT } #endif // only cancel if /break before set time elapsed if (k_demo_mintime <= 0) { k_demo_mintime = 120; // 120 seconds is default } return (g_globalvars.time - match_start_time) < k_demo_mintime; } // Whenever a countdown or match stops, remove the timer and reset everything. // also stop/cancel demo recording void StopTimer(int removeDemo) { gedict_t *timer, *p; if (match_in_progress == 1) G_cp2all("%s", ""); // clear center print k_force = 0; match_in_progress = 0; if (k_standby) { // Stops the bug where players are set to ghosts 0.2 second to go and countdown aborts. // standby flag needs clearing (sturm) k_standby = 0; for (p = world; (p = find_plr(p));) { setfullwep(p); p->s.v.takedamage = DAMAGE_AIM; p->s.v.solid = SOLID_SLIDEBOX; p->s.v.movetype = MOVETYPE_WALK; setmodel(p, "progs/player.mdl"); } } for (timer = world; (timer = find(timer, FOFCLSN, "timer"));) { ent_remove(timer); } for (timer = world; (timer = find(timer, FOFCLSN, "standby_th"));) { ent_remove(timer); } if (removeDemo && (match_can_cancel_demo()) && (race_can_cancel_demo()) && !strnull(cvar_string("serverdemo"))) { localcmd("sv_democancel\n"); // demo is recording and must be removed, do it } match_start_time = 0; // do not set to Standby during points, (unless its the final point of course) if (!isHoonyModeAny() || (HM_current_point_type() == HM_PT_FINAL)) { localcmd("serverinfo status Standby\n"); } } void IdlebotForceStart(void) { gedict_t *p; int i; G_bprint(2, "server is tired of waiting\n" "match WILL commence!\n"); i = 0; for (p = world; (p = find_plr(p));) { if (p->ready) { i++; } else { G_bprint(2, "%s was kicked by IDLE BOT\n", p->netname); G_sprint(p, 2, "Bye bye! Pay attention next time.\n"); stuffcmd(p, "disconnect\n"); // FIXME: stupid way } } k_attendees = i; if (k_attendees > 1) { StartTimer(); } else { G_bprint(2, "Can't start! More players needed.\n"); EndMatch(1); } } void IdlebotThink(void) { gedict_t *p; int i; if (cvar("k_idletime") <= 0) { ent_remove(self); return; } self->attack_finished -= 1; i = CountPlayers(); if (((0.5f * i) > CountRPlayers()) || (i < 2)) { G_bprint(2, "console: bah! chickening out?\n" "server disables the %s\n", redtext("idle bot")); ent_remove(self); return; } k_attendees = CountPlayers(); if (!isCanStart(NULL, true)) { G_bprint(2, "%s removed\n", redtext("idle bot")); ent_remove(self); return; } if (self->attack_finished < 1) { IdlebotForceStart(); ent_remove(self); return; } else { i = self->attack_finished; if ((i < 5) || !(i % 5)) { for (p = world; (p = find_plr(p));) { if (!p->ready) { G_sprint(p, 2, "console: %d second%s to go ready\n", i, (i == 1 ? "" : "s")); } } } } self->s.v.nextthink = g_globalvars.time + 1; } void IdlebotCheck(void) { gedict_t *p; int i; int bots = CountBots(); if ((cvar("k_idletime") <= 0) || bots) { if ((p = find(world, FOFCLSN, "idlebot"))) { ent_remove(p); } return; } i = CountPlayers(); if (((0.5f * i) > CountRPlayers()) || (i < 2)) { p = find(world, FOFCLSN, "idlebot"); if (p) { G_bprint(2, "console: bah! chickening out?\n" "server disables the %s\n", redtext("idle bot")); ent_remove(p); } return; } if (match_in_progress || intermission_running || k_force) { return; } // no idle bot in practice mode if (k_practice) // #practice mode# { return; } if ((p = find(world, FOFCLSN, "idlebot"))) // already have idlebot { return; } //50% or more of the players are ready! go-go-go k_attendees = CountPlayers(); if (!isCanStart( NULL, true)) { G_sprint(self, 2, "Can't issue %s!\n", redtext("idle bot")); return; } p = spawn(); p->classname = "idlebot"; p->think = (func_t) IdlebotThink; p->s.v.nextthink = g_globalvars.time + 0.001; p->attack_finished = max(3, cvar("k_idletime")); G_bprint(2, "\n" "server activates the %s\n", redtext("idle bot")); } void CheckAutoXonX(qbool use_time); void r_changestatus(float t); // Called by a player to inform that (s)he is ready for a match. void PlayerReady(qbool startIdlebot) { gedict_t *p; float nready; char *matchtag = ezinfokey(world, "matchtag"); qbool has_matchtag = matchtag != NULL && matchtag[0]; if (isRACE() && !race_match_mode()) { r_changestatus(1); // race_ready return; } if (self->ct == ctSpec && !isRACE()) { if (!cvar("k_auto_xonx") || k_matchLess) { G_sprint(self, 2, "Command not allowed\n"); return; } if (self->ready) { G_sprint(self, 2, "Type break to unready yourself\n"); return; } self->ready = 1; for (p = world; (p = (match_in_progress ? find_spc(p) : find_client(p)));) { G_sprint(p, 2, "%s %s to play\n", self->netname, redtext("desire")); } CheckAutoXonX(g_globalvars.time < 10 ? true : false); // force switch mode asap if possible after some time spent return; } if (intermission_running || (match_in_progress == 2) || match_over) { return; } if (k_practice && !isRACE()) { // #practice mode# G_sprint(self, 2, "%s\n", redtext("Server in practice mode")); return; } if (self->ready) { G_sprint(self, 2, "Type break to unready yourself\n"); return; } if (is_private_game() && !is_logged_in(self)) { G_sprint(self, 2, "You must login first\n"); return; } if (isCTF() || isHoonyModeTDM()) { if (!streq(getteam(self), "red") && !streq(getteam(self), "blue")) { G_sprint(self, 2, "You must be on team red or blue\n"); return; } } if (k_force && (isTeam() || isCTF())) { nready = 0; for (p = world; (p = find_plr(p));) { if (p->ready) { if (streq(getteam(self), getteam(p)) && !strnull(getteam(self))) { nready = 1; break; } } } if (!nready) { G_sprint(self, 2, "Join an existing team!\n"); return; } } // do not allow empty team in team mode, because it cause problems if ((isTeam() || isCTF() || isCA()) && strnull(getteam(self))) { G_sprint(self, 2, "Set your %s before ready!\n", redtext("team")); return; } if (GetHandicap(self) != 100) { G_sprint(self, 2, "\207%s you are using handicap!\n", redtext("WARNING:")); } self->ready = 1; self->v.brk = 0; self->k_teamnum = 0; // force red or blue color if ctf if (isCTF()) { if (streq(getteam(self), "blue")) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color 13\n"); } else if (streq(getteam(self), "red")) { stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "color 4\n"); } } if (!isHoonyModeAny() || (HM_current_point() == 0)) { G_bprint(2, "%s %s%s\n", self->netname, redtext("is ready"), ((isTeam() || isCTF()) ? va(" \220%s\221", getteam(self)) : "")); } nready = CountRPlayers(); k_attendees = CountPlayers(); if (match_in_progress) { return; // possible in bloodfest. } if (!isCanStart( NULL, false)) { return; // rules does't allow us to start match, idlebot ignored because of same reason } if (k_force) { return; // admin forces match - timer will started somewhere else } // we ignore "all players ready" and "at least two players ready" checks in bloodfest mode. if (!k_bloodfest) { if (nready != k_attendees) { // not all players ready, check idlebot and return if (startIdlebot) { IdlebotCheck(); } return; } // ok all players ready. // only one or less players ready, match is pointless. if (nready < 2) { return; } } if (isHoonyModeAny() && k_attendees && nready == k_attendees) { HM_all_ready(); } else { if (k_attendees && (nready == k_attendees)) { G_bprint(2, "All players ready\n"); } if (has_matchtag && cvar("k_on_start_f_modified")) { stuffcmd(self, "say f_modified\n"); } if (has_matchtag && cvar("k_on_start_f_ruleset")) { stuffcmd(self, "say f_ruleset\n"); } if (has_matchtag && cvar("k_on_start_f_version")) { stuffcmd(self, "say f_version\n"); } G_bprint(2, "Timer started\n"); } StartTimer(); } void PlayerSlowReady(void) { PlayerReady(false); } void PlayerFastReady(void) { PlayerReady(true); } void PlayerBreak(void) { int votes; gedict_t *p; if (isRACE() && !race_match_mode()) { r_changestatus(2); // race_break return; } if ((self->ct == ctSpec) && !isRACE()) { if (!cvar("k_auto_xonx") || k_matchLess) { G_sprint(self, 2, "Command not allowed\n"); return; } if (!self->ready) { return; } self->ready = 0; for (p = world; (p = (match_in_progress ? find_spc(p) : find_client(p)));) { G_sprint(p, 2, "%s %s to play\n", self->netname, redtext("lost desire")); } return; } if (!self->ready || intermission_running || match_over) { return; } if (isCA() && (match_in_progress == 2) && !self->ca_ready) { G_sprint(self, 2, "You must be in the game to vote\n"); return; } if (k_matchLess && !k_bloodfest) { // do not allow break/next_map commands in some cases. if (cvar("k_no_vote_map")) { G_sprint(self, 2, "Voting next map is %s allowed\n", redtext("not")); return; } } if (!match_in_progress) { self->ready = 0; G_bprint(2, "%s %s\n", self->netname, redtext("is not ready")); return; } if (!k_matchLess || k_bloodfest) { // try stop countdown. (countdown between hoony-mode points can't be stopped, treat as standard break request). qbool can_stop_hoonymode = (!isHoonyModeAny() || HM_current_point() == 0); if (match_in_progress == 1 && can_stop_hoonymode) { p = find(world, FOFCLSN, "timer"); if (p && p->cnt2 > 1) { self->ready = 0; if (!k_matchLess || (k_bloodfest && (CountRPlayers() < 1))) { G_bprint(2, "%s %s\n", self->netname, redtext("stops the countdown")); StopTimer(1); } else { G_bprint(2, "%s %s\n", self->netname, redtext("is not ready")); } } return; } } if (self->v.brk) { self->v.brk = 0; G_bprint(2, "%s %s %s vote%s\n", self->netname, redtext("withdraws"), redtext(g_his(self)), ((votes = get_votes_req(OV_BREAK, true)) ? va(" (%d)", votes) : "")); return; } self->v.brk = 1; G_bprint(2, "%s %s%s\n", self->netname, redtext(k_matchLess ? "votes for next map" : "votes for stopping the match"), ((votes = get_votes_req( OV_BREAK, true)) ? va(" (%d)", votes) : "")); // show warning to player - that he can't stop countdown alone in matchless mode. if (k_matchLess && (match_in_progress == 1) && (CountPlayers() == 1)) { G_sprint(self, 2, "You can't stop countdown alone\n"); } vote_check_break(); } QW-Group-ktx-d05d6ca/src/mathlib.c000066400000000000000000000311701475442401000170050ustar00rootroot00000000000000/* * Copyright (C) 1996-1997 Id Software, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * $Id$ */ // mathlib.c -- math primitives //#include //#include "quakedef.h" #include "g_local.h" //void Sys_Error (char *error, ...); vec3_t vec3_origin = { 0, 0, 0 }; int nanmask = 255 << 23; /*-----------------------------------------------------------------*/ #define DEG2RAD(a) ((a * M_PI) / 180.0F) 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 = 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); } #if defined(_WIN32) && defined(_MSC_VER) #pragma optimize( "", off ) #endif 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[0][0] = zrot[1][1] = zrot[2][2] = 1.0F; zrot[0][0] = cos(DEG2RAD(degrees)); zrot[0][1] = sin(DEG2RAD(degrees)); zrot[1][0] = -sin(DEG2RAD(degrees)); zrot[1][1] = 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]; } } #if defined(_WIN32) && defined(_MSC_VER) #pragma optimize( "", on ) #endif /*-----------------------------------------------------------------*/ float anglemod(float a) { #if 0 if (a >= 0) { a -= 360*(int)(a/360); } else { a += 360*( 1 + (int)(-a/360) ); } #endif a = (360.0 / 65536) * ((int)(a * (65536 / 360.0)) & 65535); return a; } /* ================== BOPS_Error Split out like this for ASM to call. ================== */ void BOPS_Error(void) { //Sys_Error ("BoxOnPlaneSide: Bad signbits"); } #if !id386 /* ================== BoxOnPlaneSide Returns 1, 2, or 1 + 2 ================== */ int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, mplane_t *p) { float dist1, dist2; int sides; #if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this // function // 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; } #endif // 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; // shut up compiler BOPS_Error(); break; } #if 0 int i; vec3_t corners[2]; for (i = 0 ; i<3 ; i++) { if (plane->normal[i] < 0) { corners[0][i] = emins[i]; corners[1][i] = emaxs[i]; } else { corners[1][i] = emins[i]; corners[0][i] = emaxs[i]; } } dist = DotProduct(plane->normal, corners[0]) - plane->dist; dist2 = DotProduct(plane->normal, corners[1]) - plane->dist; sides = 0; if (dist1 >= 0) { sides = 1; } if (dist2 < 0) { sides |= 2; } #endif sides = 0; if (dist1 >= p->dist) { sides = 1; } if (dist2 < p->dist) { sides |= 2; } #ifdef PARANOID //if (sides == 0) // Sys_Error ("BoxOnPlaneSide: sides==0"); #endif return sides; } #endif void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { float angle; float sr, sp, sy, cr, cp, cy; angle = angles[YAW] * (M_PI * 2 / 360); sy = sin(angle); cy = cos(angle); angle = angles[PITCH] * (M_PI * 2 / 360); sp = sin(angle); cp = cos(angle); angle = angles[ROLL] * (M_PI * 2 / 360); sr = sin(angle); cr = cos(angle); forward[0] = cp * cy; forward[1] = cp * sy; forward[2] = -sp; right[0] = (-1 * sr * sp * cy + -1 * cr * -sy); right[1] = (-1 * sr * sp * sy + -1 * cr * cy); right[2] = -1 * sr * cp; up[0] = (cr * sp * cy + -sr * -sy); up[1] = (cr * sp * sy + -sr * cy); up[2] = cr * cp; } int VectorCompare(vec3_t v1, vec3_t v2) { int i; for (i = 0; i < 3; i++) { if (v1[i] != v2[i]) { return 0; } } return 1; } int VectorCompareF(vec3_t v1, float x, float y, float z) { if ((v1[0] != x) || (v1[1] != y) || (v1[2] != z)) { return 0; } return 1; } 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) { float length; length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; length = sqrt(length); // FIXME return length; } float VectorDistance(vec3_t v1, vec3_t v2) { vec3_t diff; VectorSubtract(v1, v2, diff); return vlen(diff); } float VectorNormalize(vec3_t v) { float length, ilength; length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; length = sqrt(length); // FIXME if (length) { ilength = 1 / length; v[0] *= ilength; v[1] *= ilength; v[2] *= ilength; } 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) != 0) { answer++; } return answer; } /* ================ R_ConcatRotations ================ */ 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]; } /* ================ R_ConcatTransforms ================ */ 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]; } /* =================== FloorDivMod Returns mathematically correct (floor-based) quotient and remainder for numer and denom, both of which should contain no fractional part. The quotient must fit in 32 bits. ==================== */ void FloorDivMod(double numer, double denom, int *quotient, int *rem) { int q, r; double x; #ifndef PARANOID // if (denom <= 0.0) // Sys_Error ("FloorDivMod: bad denominator %d\n", denom); // if ((floor(numer) != numer) || (floor(denom) != denom)) // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n", // numer, denom); #endif if (numer >= 0.0) { x = floor(numer / denom); q = (int)x; r = (int)floor(numer - (x * denom)); } else { // // perform operations with positive values, and fix mod to make floor-based // x = floor(-numer / denom); q = -(int)x; r = (int)floor(-numer - (x * denom)); if (r != 0) { q--; r = (int)denom - r; } } *quotient = q; *rem = r; } /* =================== GreatestCommonDivisor ==================== */ int GreatestCommonDivisor(int i1, int i2) { if (i1 > i2) { if (i2 == 0) { return (i1); } return GreatestCommonDivisor(i2, i1 % i2); } else { if (i1 == 0) { return (i2); } return GreatestCommonDivisor(i1, i2 % i1); } } #if !id386 // TODO: move to nonintel.c /* =================== Invert24To16 Inverts an 8.24 value to a 16.16 value ==================== */ fixed16_t Invert24To16(fixed16_t val) { if (val < 256) { return (fixed16_t)0xFFFFFFFF; } return (fixed16_t)(((double)0x10000 * (double)0x1000000 / (double)val) + 0.5); } #endif QW-Group-ktx-d05d6ca/src/misc.c000066400000000000000000000473601475442401000163300ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" //============================================================================ #define START_OFF 1 void light_use(void) { if ((int)(self->s.v.spawnflags) & START_OFF) { trap_lightstyle(self->style, "m"); self->s.v.spawnflags -= START_OFF; } else { trap_lightstyle(self->style, "a"); self->s.v.spawnflags += START_OFF; } } /*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, it will toggle between on or off. */ void SP_light(void) { if (!self->targetname) { // inert light ent_remove(self); return; } if (self->style >= 32) { self->use = (func_t) light_use; if ((int)self->s.v.spawnflags & START_OFF) { trap_lightstyle(self->style, "a"); } else { trap_lightstyle(self->style, "m"); } } } /*QUAKED light_fluoro (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, it will toggle between on or off. Makes steady fluorescent humming sound */ void SP_light_fluoro(void) { if (self->style >= 32) { self->use = (func_t) light_use; if ((int)self->s.v.spawnflags & START_OFF) { trap_lightstyle(self->style, "a"); } else { trap_lightstyle(self->style, "m"); } } trap_precache_sound("ambience/fl_hum1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/fl_hum1.wav", 0.5, ATTN_STATIC); } /*QUAKED light_fluorospark (0 1 0) (-8 -8 -8) (8 8 8) Non-displayed light. Default light value is 300 Default style is 10 Makes sparking, broken fluorescent sound */ void SP_light_fluorospark(void) { if (!self->style) { self->style = 10; } trap_precache_sound("ambience/buzz1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/buzz1.wav", 0.5, ATTN_STATIC); } /*QUAKED light_globe (0 1 0) (-8 -8 -8) (8 8 8) Sphere globe light. Default light value is 300 Default style is 0 */ void SP_light_globe(void) { trap_precache_model("progs/s_light.spr"); setmodel(self, "progs/s_light.spr"); makestatic(self); } void FireAmbient(gedict_t *self) { trap_precache_sound("ambience/fire1.wav"); // attenuate fast trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/fire1.wav", 0.5, ATTN_STATIC); } /*QUAKED light_torch_small_walltorch (0 .5 0) (-10 -10 -20) (10 10 20) Short wall torch Default light value is 200 Default style is 0 */ void SP_light_torch_small_walltorch(void) { trap_precache_model("progs/flame.mdl"); setmodel(self, "progs/flame.mdl"); FireAmbient(self); makestatic(self); } /*QUAKED light_flame_large_yellow (0 1 0) (-10 -10 -12) (12 12 18) Large yellow flame ball */ void SP_light_flame_large_yellow(void) { trap_precache_model("progs/flame2.mdl"); setmodel(self, "progs/flame2.mdl"); self->s.v.frame = 1; FireAmbient(self); makestatic(self); } /*QUAKED light_flame_small_yellow (0 1 0) (-8 -8 -8) (8 8 8) START_OFF Small yellow flame ball */ void SP_light_flame_small_yellow(void) { trap_precache_model("progs/flame2.mdl"); setmodel(self, "progs/flame2.mdl"); FireAmbient(self); makestatic(self); } /*QUAKED light_flame_small_white (0 1 0) (-10 -10 -40) (10 10 40) START_OFF Small white flame ball */ void SP_light_flame_small_white(void) { trap_precache_model("progs/flame2.mdl"); setmodel(self, "progs/flame2.mdl"); FireAmbient(self); makestatic(self); } //============================================================================ /*QUAKED misc_fireball (0 .5 .8) (-8 -8 -8) (8 8 8) Lava Balls */ void fire_fly(void); void fire_touch(void); void SP_misc_fireball(void) { trap_precache_model("progs/lavaball.mdl"); self->classname = "fireball"; self->s.v.nextthink = g_globalvars.time + (g_random() * 5); self->think = (func_t) fire_fly; if (!self->speed) { self->speed = 1000; } } void fire_fly(void) { gedict_t *fireball; fireball = spawn(); fireball->s.v.solid = SOLID_TRIGGER; fireball->s.v.movetype = MOVETYPE_TOSS; fireball->isMissile = true; // well, you can really treat fireball as missilie, nothing bad gonna heppen. SetVector(fireball->s.v.velocity, (g_random() * 100) - 50, (g_random() * 100) - 50, self->speed + (g_random() * 200)); fireball->classname = "fireball"; setmodel(fireball, "progs/lavaball.mdl"); setsize(fireball, 0, 0, 0, 0, 0, 0); setorigin(fireball, PASSVEC3(self->s.v.origin)); fireball->s.v.nextthink = g_globalvars.time + 5; fireball->think = (func_t) SUB_Remove; fireball->touch = (func_t) fire_touch; self->s.v.nextthink = g_globalvars.time + (g_random() * 5) + 3; self->think = (func_t) fire_fly; } void fire_touch(void) { // Yawnmode: no damage from fireall if (!k_yawnmode) { other->deathtype = dtFIREBALL; T_Damage(other, self, self, 20); } ent_remove(self); } //============================================================================ void barrel_explode(void) { self->s.v.takedamage = DAMAGE_NO; self->classname = "explo_box"; // did say self.owner T_RadiusDamage(self, self, 160, world, dtEXPLO_BOX); WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_EXPLOSION); WriteCoord( MSG_MULTICAST, self->s.v.origin[0]); WriteCoord( MSG_MULTICAST, self->s.v.origin[1]); WriteCoord( MSG_MULTICAST, self->s.v.origin[2] + 32); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } /*QUAKED misc_explobox (0 .5 .8) (0 0 0) (32 32 64) TESTING THING */ void SP_misc_explobox(void) { float oldz; self->s.v.solid = SOLID_BBOX; self->s.v.movetype = MOVETYPE_NONE; trap_precache_model("maps/b_explob.bsp"); setmodel(self, "maps/b_explob.bsp"); setsize(self, 0, 0, 0, 32, 32, 64); trap_precache_sound("weapons/r_exp3.wav"); self->s.v.health = 20; self->th_die = barrel_explode; self->s.v.takedamage = DAMAGE_AIM; self->s.v.origin[2] += 2; oldz = self->s.v.origin[2]; droptofloor(self); if ((oldz - self->s.v.origin[2]) > 250) { G_Printf("item fell out of level at '%f %f %f'\n", PASSVEC3(self->s.v.origin)); ent_remove(self); } } /*QUAKED misc_explobox2 (0 .5 .8) (0 0 0) (32 32 64) Smaller exploding box, REGISTERED ONLY */ void SP_misc_explobox2(void) { float oldz; self->s.v.solid = SOLID_BBOX; self->s.v.movetype = MOVETYPE_NONE; trap_precache_model("maps/b_exbox2.bsp"); setmodel(self, "maps/b_exbox2.bsp"); setsize(self, 0, 0, 0, 32, 32, 32); trap_precache_sound("weapons/r_exp3.wav"); self->s.v.health = 20; self->th_die = barrel_explode; self->s.v.takedamage = DAMAGE_AIM; self->s.v.origin[2] += 2; oldz = self->s.v.origin[2]; droptofloor(self); if ((oldz - self->s.v.origin[2]) > 250) { G_Printf("item fell out of level at '%f %f %f'\n", PASSVEC3(self->s.v.origin)); ent_remove(self); } } //============================================================================ #define SPAWNFLAG_SUPERSPIKE 1 #define SPAWNFLAG_LASER 2 void Laser_Touch(void) { vec3_t org; if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } if (trap_pointcontents(PASSVEC3(self->s.v.origin)) == CONTENT_SKY) { ent_remove(self); return; } sound(self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC); normalize(self->s.v.velocity, org); VectorScale(org, 8, org); VectorSubtract(self->s.v.origin, org, org); //org = self->s.v.origin - 8*normalize(self->s.v.velocity); if (ISLIVE(other)) { SpawnBlood(org, 15); other->deathtype = dtLASER; T_Damage(other, self, PROG_TO_EDICT(self->s.v.owner), 15); } else { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_GUNSHOT); WriteByte( MSG_MULTICAST, 5); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); trap_multicast(PASSVEC3(org), MULTICAST_PVS); } ent_remove(self); } gedict_t *newmis; // FIXME: funny place for such global void LaunchLaser(vec3_t org, vec3_t vec) { //vec3_t vec; if (streq(self->classname, "monster_enforcer")) { sound(self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM); } normalize(vec, vec); newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->s.v.owner = EDICT_TO_PROG(self); newmis->s.v.movetype = MOVETYPE_FLY; newmis->isMissile = true; newmis->s.v.solid = SOLID_BBOX; newmis->s.v.effects = EF_DIMLIGHT; setmodel(newmis, "progs/laser.mdl"); setsize(newmis, 0, 0, 0, 0, 0, 0); setorigin(newmis, PASSVEC3(org)); //newmis->s.v.velocity = vec * 600; VectorScale(vec, 600, newmis->s.v.velocity); vectoangles(newmis->s.v.velocity, newmis->s.v.angles); newmis->s.v.nextthink = g_globalvars.time + 5; newmis->think = (func_t) SUB_Remove; newmis->touch = (func_t) Laser_Touch; } void spike_touch(void); void superspike_touch(void); void spikeshooter_use(void) { if ((int)(self->s.v.spawnflags) & SPAWNFLAG_LASER) { sound(self, CHAN_VOICE, "enforcer/enfire.wav", 1, ATTN_NORM); LaunchLaser(self->s.v.origin, self->s.v.movedir); } else { sound(self, CHAN_VOICE, "weapons/spike2.wav", 1, ATTN_NORM); launch_spike(self->s.v.origin, self->s.v.movedir); VectorScale(self->s.v.movedir, 500, PROG_TO_EDICT(g_globalvars.newmis)->s.v.velocity); // newmis->s.v.velocity = self->s.v.movedir * 500; if ((int)(self->s.v.spawnflags) & SPAWNFLAG_SUPERSPIKE) { PROG_TO_EDICT(g_globalvars.newmis)->touch = (func_t) superspike_touch; } } } void shooter_think(void) { spikeshooter_use(); self->s.v.nextthink = g_globalvars.time + self->wait; VectorScale(self->s.v.movedir, 500, PROG_TO_EDICT(g_globalvars.newmis)->s.v.velocity); // newmis->s.v.velocity = self->s.v.movedir * 500; } /*QUAKED trap_spikeshooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser When triggered, fires a spike in the direction set in QuakeEd. Laser is only for REGISTERED. */ void SP_trap_spikeshooter(void) { SetMovedir(); self->use = (func_t) spikeshooter_use; if ((int)(self->s.v.spawnflags) & SPAWNFLAG_LASER) { trap_precache_model("progs/laser.mdl"); trap_precache_sound("enforcer/enfire.wav"); trap_precache_sound("enforcer/enfstop.wav"); } else { trap_precache_sound("weapons/spike2.wav"); } } /*QUAKED trap_shooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser Continuously fires spikes. "wait" g_globalvars.time between spike (1.0 default) "nextthink" delay before firing first spike, so multiple shooters can be stagered. */ void SP_trap_shooter(void) { SP_trap_spikeshooter(); if (self->wait == 0) { self->wait = 1; } self->s.v.nextthink = self->s.v.nextthink + self->wait + self->s.v.ltime; self->think = (func_t) shooter_think; } /* =============================================================================== =============================================================================== */ void make_bubbles(void); void bubble_remove(void); void bubble_bob(void); /*QUAKED air_bubbles (0 .5 .8) (-8 -8 -8) (8 8 8) testing air bubbles */ void SP_air_bubbles(void) { ent_remove(self); } void make_bubbles(void) { gedict_t *bubble; bubble = spawn(); setmodel(bubble, "progs/s_bubble.spr"); setorigin(bubble, PASSVEC3(self->s.v.origin)); bubble->s.v.movetype = MOVETYPE_NOCLIP; bubble->s.v.solid = SOLID_NOT; SetVector(bubble->s.v.velocity, 0, 0, 15); bubble->s.v.nextthink = g_globalvars.time + 0.5; bubble->think = (func_t) bubble_bob; bubble->touch = (func_t) bubble_remove; bubble->classname = "bubble"; bubble->s.v.frame = 0; bubble->cnt = 0; setsize(bubble, -8, -8, -8, 8, 8, 8); self->s.v.nextthink = g_globalvars.time + g_random() + 0.5; self->think = (func_t) make_bubbles; } void bubble_split(void) { gedict_t *bubble; bubble = spawn(); setmodel(bubble, "progs/s_bubble.spr"); setorigin(bubble, PASSVEC3(self->s.v.origin)); bubble->s.v.movetype = MOVETYPE_NOCLIP; bubble->s.v.solid = SOLID_NOT; VectorCopy(self->s.v.velocity, bubble->s.v.velocity); bubble->s.v.nextthink = g_globalvars.time + 0.5; bubble->think = (func_t) bubble_bob; bubble->touch = (func_t) bubble_remove; bubble->classname = "bubble"; bubble->s.v.frame = 1; bubble->cnt = 10; setsize(bubble, -8, -8, -8, 8, 8, 8); self->s.v.frame = 1; self->cnt = 10; if (self->s.v.waterlevel != 3) { ent_remove(self); } } void bubble_remove(void) { if (streq(other->classname, self->classname)) { // dprint ("bump"); return; } ent_remove(self); } void bubble_bob(void) { float rnd1, rnd2, rnd3; // vec3_t vtmp1, modi; self->cnt = self->cnt + 1; if (self->cnt == 4) { bubble_split(); } if (self->cnt == 20) { ent_remove(self); } rnd1 = self->s.v.velocity[0] + (-10 + (g_random() * 20)); rnd2 = self->s.v.velocity[1] + (-10 + (g_random() * 20)); rnd3 = self->s.v.velocity[2] + 10 + g_random() * 10; if (rnd1 > 10) { rnd1 = 5; } if (rnd1 < -10) { rnd1 = -5; } if (rnd2 > 10) { rnd2 = 5; } if (rnd2 < -10) { rnd2 = -5; } if (rnd3 < 10) { rnd3 = 15; } if (rnd3 > 30) { rnd3 = 25; } self->s.v.velocity[0] = rnd1; self->s.v.velocity[1] = rnd2; self->s.v.velocity[2] = rnd3; self->s.v.nextthink = g_globalvars.time + 0.5; self->think = (func_t) bubble_bob; } /*~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~> ~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~*/ /*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8) Just for the debugging level. Don't use */ void viewthing(void) { self->s.v.movetype = MOVETYPE_NONE; self->s.v.solid = SOLID_NOT; trap_precache_model("progs/player.mdl"); setmodel(self, "progs/player.mdl"); } /* ============================================================================== SIMPLE BMODELS ============================================================================== */ void func_wall_use(void) { // change to alternate textures self->s.v.frame = 1 - self->s.v.frame; } /*QUAKED func_wall (0 .5 .8) ? This is just a solid wall if not inhibitted */ void SP_func_wall(void) { SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything self->s.v.solid = SOLID_BSP; self->use = (func_t) func_wall_use; setmodel(self, self->model); } /*QUAKED func_illusionary (0 .5 .8) ? A simple entity that looks solid but lets you walk through it. */ void SP_func_illusionary(void) { SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_NONE; self->s.v.solid = SOLID_NOT; setmodel(self, self->model); makestatic(self); } /*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4 This bmodel will appear if the episode has allready been completed, so players can't reenter it. */ void SP_func_episodegate(void) { if (!((int)(g_globalvars.serverflags) & (int)(self->s.v.spawnflags))) { return; // can still enter episode } SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything self->s.v.solid = SOLID_BSP; self->use = (func_t) func_wall_use; setmodel(self, self->model); } /*QUAKED func_bossgate (0 .5 .8) ? This bmodel appears unless players have all of the episode sigils. */ void SP_func_bossgate(void) { if (((int)(g_globalvars.serverflags) & 15) == 15) { return; // all episodes completed } SetVector(self->s.v.angles, 0, 0, 0); self->s.v.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything self->s.v.solid = SOLID_BSP; self->use = (func_t) func_wall_use; setmodel(self, self->model); } //============================================================================ /*QUAKED ambient_suck_wind (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_suck_wind(void) { trap_precache_sound("ambience/suck1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/suck1.wav", 1, ATTN_STATIC); } /*QUAKED ambient_drone (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_drone(void) { trap_precache_sound("ambience/drone6.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/drone6.wav", 0.5, ATTN_STATIC); } /*QUAKED ambient_flouro_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_flouro_buzz(void) { trap_precache_sound("ambience/buzz1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/buzz1.wav", 1, ATTN_STATIC); } /*QUAKED ambient_drip (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_drip(void) { trap_precache_sound("ambience/drip1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/drip1.wav", 0.5, ATTN_STATIC); } /*QUAKED ambient_comp_hum (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_comp_hum(void) { trap_precache_sound("ambience/comp1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/comp1.wav", 1, ATTN_STATIC); } /*QUAKED ambient_thunder (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_thunder(void) { trap_precache_sound("ambience/thunder1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/thunder1.wav", 0.5, ATTN_STATIC); } /*QUAKED ambient_light_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_light_buzz(void) { trap_precache_sound("ambience/fl_hum1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/fl_hum1.wav", 0.5, ATTN_STATIC); } /*QUAKED ambient_swamp1 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_swamp1(void) { trap_precache_sound("ambience/swamp1.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/swamp1.wav", 0.5, ATTN_STATIC); } /*QUAKED ambient_swamp2 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) */ void SP_ambient_swamp2(void) { trap_precache_sound("ambience/swamp2.wav"); trap_ambientsound(PASSVEC3(self->s.v.origin), "ambience/swamp2.wav", 0.5, ATTN_STATIC); } void SP_ambient_general(void) { if (strnull(self->noise)) { G_Error ("No soundfile set in noise!\n"); ent_remove(self); return; } trap_precache_sound (self->noise); switch ((int) ceil((double) self->speed)) { case 0: self->speed = ATTN_NORM; break; case -1: self->speed = ATTN_NONE; break; default: break; } if (self->volume <= 0) { self->volume = 0.5f; } trap_ambientsound (PASSVEC3(self->s.v.origin), self->noise, self->volume, self->speed); ent_remove(self); } //============================================================================ void noise_think(void) { self->s.v.nextthink = g_globalvars.time + 0.5; sound(self, 1, "enforcer/enfire.wav", 1, ATTN_NORM); sound(self, 2, "enforcer/enfstop.wav", 1, ATTN_NORM); sound(self, 3, "enforcer/sight1.wav", 1, ATTN_NORM); sound(self, 4, "enforcer/sight2.wav", 1, ATTN_NORM); sound(self, 5, "enforcer/sight3.wav", 1, ATTN_NORM); sound(self, 6, "enforcer/sight4.wav", 1, ATTN_NORM); sound(self, 7, "enforcer/pain1.wav", 1, ATTN_NORM); } /*QUAKED misc_noisemaker (1 0.5 0) (-10 -10 -10) (10 10 10) For optimzation testing, starts a lot of sounds. */ void SP_misc_noisemaker(void) { trap_precache_sound("enforcer/enfire.wav"); trap_precache_sound("enforcer/enfstop.wav"); trap_precache_sound("enforcer/sight1.wav"); trap_precache_sound("enforcer/sight2.wav"); trap_precache_sound("enforcer/sight3.wav"); trap_precache_sound("enforcer/sight4.wav"); trap_precache_sound("enforcer/pain1.wav"); trap_precache_sound("enforcer/pain2.wav"); trap_precache_sound("enforcer/death1.wav"); trap_precache_sound("enforcer/idle1.wav"); self->s.v.nextthink = g_globalvars.time + 0.1 + g_random(); self->think = (func_t) noise_think; } QW-Group-ktx-d05d6ca/src/motd.c000066400000000000000000000103241475442401000163260ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // motd.c #include "g_local.h" void PMOTDThink(void) { int i; char buf[2048] = { 0 }; char *s; // remove MOTD in some cases if ((self->attack_finished < g_globalvars.time) // expired || (!k_matchLess && match_in_progress) // non matchless and (match has began or countdown) || (k_matchLess && match_in_progress == 1) // matchless and countdown || (PROG_TO_EDICT(self->s.v.owner)->attack_finished > g_globalvars.time)) // player fire something, so he wanna play, not reading motd { if (self->attack_finished < g_globalvars.time) { G_centerprint(PROG_TO_EDICT(self->s.v.owner), "%s", ""); } ent_remove(self); return; } if (PROG_TO_EDICT(self->s.v.owner)->wp_stats || PROG_TO_EDICT(self->s.v.owner)->sc_stats || PROG_TO_EDICT(self->s.v.owner)->shownick_time) { self->s.v.nextthink = g_globalvars.time + 1; // do not interference with +wp_stats or +scores and shownick return; } for (i = 1; i <= MOTD_LINES; i++) { if (strnull(s = cvar_string(va("k_motd%d", i)))) { continue; } strlcat(buf, s, sizeof(buf)); strlcat(buf, "\n", sizeof(buf)); } // no "welcome" - if k_motd keys is present - because admin may wanna customize this if (strnull(buf)) { strlcat(buf, "Welcome\n\n", sizeof(buf)); } strlcat(buf, "\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n\n", sizeof(buf)); strlcat(buf, va("Running %s %s", redtext(cvar_string("qwm_name")), redtext(cvar_string("qwm_version"))), sizeof(buf)); if (strlen(cvar_string("qws_name")) && strlen(cvar_string("qws_version"))) { strlcat(buf, va(" on %s %s", redtext(cvar_string("qws_name")), redtext(cvar_string("qws_version"))), sizeof(buf)); } strlcat(buf, va("\n\nType \"%s\" for available commands\nType \"%s\" for server details", redtext("commands"), redtext("about")), sizeof(buf)); G_centerprint(PROG_TO_EDICT(self->s.v.owner), "%s", buf); self->s.v.nextthink = g_globalvars.time + 0.7; } void SMOTDThink(void) { PMOTDThink(); // equal motd for player and spectator now } void MOTDThinkX(void) { gedict_t *owner = PROG_TO_EDICT(self->s.v.owner); // FIXME: server work around, frags are not restored, ie showed as 0, force update frags manually if (owner->s.v.frags && ((int)(owner - world - 1) >= 0) && ((int)(owner - world - 1) < MAX_CLIENTS)) { WriteByte(MSG_ALL, SVC_UPDATEFRAGS); // update frags WriteByte(MSG_ALL, (int)(owner - world - 1)); WriteShort(MSG_ALL, owner->s.v.frags); } // select MOTD for spectator or player self->think = (func_t)(owner->ct == ctSpec ? SMOTDThink : PMOTDThink); self->s.v.nextthink = g_globalvars.time + 0.3; if (owner->k_stuff) { if (k_matchLess) // remove motd if player already stuffed, because them probably sow motd already one time { ent_remove(self); } } // stuff or not to stuff, that the question! if (!(owner->k_stuff & STUFF_MAPS)) { StuffMaps(owner); } else if (!(owner->k_stuff & STUFF_COMMANDS)) { StuffModCommands(owner); } } void MakeMOTD(void) { gedict_t *motd; int i = bound(0, cvar("k_motd_time"), 30); motd = spawn(); motd->classname = "motd"; motd->s.v.owner = EDICT_TO_PROG(self); motd->think = (func_t) MOTDThinkX; motd->s.v.nextthink = g_globalvars.time + 0.1; motd->attack_finished = g_globalvars.time + (i ? i : (k_matchLess ? 3 : 7)); } void RemoveMOTD(void) { gedict_t *motd; int owner = EDICT_TO_PROG(self); for (motd = world; (motd = find(motd, FOFCLSN, "motd"));) // self MOTD { if (owner == motd->s.v.owner) { ent_remove(motd); } } } QW-Group-ktx-d05d6ca/src/native_lib.c000066400000000000000000000015171475442401000175030ustar00rootroot00000000000000/* * $Id$ */ // native_lib.c -- different OS'es have different lib functions implementation, work around. // this file is only included when building a dll #ifdef Q3_VM #error "Do not use in VM build" #endif #include "g_local.h" #ifdef _WIN32 // ripped from VVD code int Q_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) { int ret; if (!count) { return 0; } ret = _vsnprintf(buffer, count, format, argptr); buffer[count - 1] = 0; return ret; } #if defined(_MSC_VER) && (_MSC_VER < 1900) int snprintf(char *buffer, size_t count, char const *format, ...) { int ret; va_list argptr; if (!count) { return 0; } va_start(argptr, format); ret = _vsnprintf(buffer, count, format, argptr); buffer[count - 1] = 0; va_end(argptr); return ret; } #endif // !(Visual Studio 2015+) #endif // _WIN32 QW-Group-ktx-d05d6ca/src/plats.c000066400000000000000000000263141475442401000165140ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void plat_center_touch(void); void plat_outside_touch(void); void plat_trigger_use(void); void plat_go_up(void); void plat_go_down(void); void plat_crush(void); #define PLAT_LOW_TRIGGER 1 void plat_spawn_inside_trigger(void) { gedict_t *trigger; vec3_t tmin, tmax; // // middle trigger // trigger = spawn(); trigger->touch = (func_t) plat_center_touch; trigger->s.v.movetype = MOVETYPE_NONE; trigger->s.v.solid = SOLID_TRIGGER; trigger->s.v.enemy = EDICT_TO_PROG(self); tmin[0] = self->s.v.mins[0] + 25; tmin[1] = self->s.v.mins[1] + 25; tmin[2] = self->s.v.mins[2] + 0; tmax[0] = self->s.v.maxs[0] - 25; tmax[1] = self->s.v.maxs[1] - 25; tmax[2] = self->s.v.maxs[2] + 8; tmin[2] = tmax[2] - (self->pos1[2] - self->pos2[2] + 8); if ((int)(self->s.v.spawnflags) & PLAT_LOW_TRIGGER) tmax[2] = tmin[2] + 8; if (self->s.v.size[0] <= 50) { tmin[0] = (self->s.v.mins[0] + self->s.v.maxs[0]) / 2; tmax[0] = tmin[0] + 1; } if (self->s.v.size[1] <= 50) { tmin[1] = (self->s.v.mins[1] + self->s.v.maxs[1]) / 2; tmax[1] = tmin[1] + 1; } setsize(trigger, PASSVEC3(tmin), PASSVEC3(tmax)); } void plat_hit_top(void) { sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->state = STATE_TOP; self->think = (func_t) plat_go_down; self->s.v.nextthink = self->s.v.ltime + 3; #ifdef BOT_SUPPORT if (bots_enabled()) { BotEventPlatformHitTop(self); } #endif } void plat_hit_bottom(void) { sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise1, 1, ATTN_NORM); self->state = STATE_BOTTOM; #ifdef BOT_SUPPORT if (bots_enabled()) { BotEventPlatformHitBottom(self); } #endif } void plat_go_down(void) { sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); self->state = STATE_DOWN; SUB_CalcMove(self->pos2, self->speed, plat_hit_bottom); } void plat_go_up(void) { sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); self->state = STATE_UP; SUB_CalcMove(self->pos1, self->speed, plat_hit_top); } void plat_center_touch(void) { // return if countdown or map frozen if (!k_practice) // #practice mode# { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } } if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } self = PROG_TO_EDICT(self->s.v.enemy); #ifdef BOT_SUPPORT BotPlatformTouched(self, other); #endif if (self->state == STATE_BOTTOM) { plat_go_up(); } else if (self->state == STATE_TOP) { self->s.v.nextthink = self->s.v.ltime + 1; // delay going down } } void plat_outside_touch(void) { // return if countdown or map frozen if (!k_practice) // #practice mode# { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } } if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } //dprint ("plat_outside_touch\n"); self = PROG_TO_EDICT(self->s.v.enemy); if (self->state == STATE_TOP) { plat_go_down(); } } void plat_trigger_use(void) { if (self->think) { return; // already activated } plat_go_down(); } void plat_crush(void) { //dprint ("plat_crush\n"); other->deathtype = dtSQUISH; T_Damage(other, self, self, 1); if (self->state == STATE_UP) { plat_go_down(); } else if (self->state == STATE_DOWN) { plat_go_up(); } else { G_Error("plat_crush: bad self.state\n"); } } void plat_use(void) { self->use = (func_t) SUB_Null; if (self->state != STATE_UP) { G_Error("plat_use: not in up state"); } plat_go_down(); } /*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. If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height. Set "sounds" to one of the following: 1) base fast 2) chain slow */ void SP_func_plat(void) { //gedict_t* t; if (!self->t_length) { self->t_length = 80; } if (!self->t_width) { self->t_width = 10; } if (self->s.v.sounds == 0) { self->s.v.sounds = 2; } // FIX THIS TO LOAD A GENERIC PLAT SOUND if (self->s.v.sounds == 1) { trap_precache_sound("plats/plat1.wav"); trap_precache_sound("plats/plat2.wav"); self->noise = "plats/plat1.wav"; self->noise1 = "plats/plat2.wav"; } if (self->s.v.sounds == 2) { trap_precache_sound("plats/medplat1.wav"); trap_precache_sound("plats/medplat2.wav"); self->noise = "plats/medplat1.wav"; self->noise1 = "plats/medplat2.wav"; } VectorCopy(self->s.v.angles, self->mangle); //self->mangle = self->s.v.angles; SetVector(self->s.v.angles, 0, 0, 0); self->classname = "plat"; self->s.v.solid = SOLID_BSP; self->s.v.movetype = MOVETYPE_PUSH; setorigin(self, PASSVEC3(self->s.v.origin)); setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); self->blocked = (func_t) plat_crush; if (!self->speed) { self->speed = 150; } // pos1 is the top position, pos2 is the bottom VectorCopy(self->s.v.origin, self->pos1); VectorCopy(self->s.v.origin, self->pos2); //self->pos1 = self->s.v.origin; //self->pos2 = self->s.v.origin; if (self->height) { self->pos2[2] = self->s.v.origin[2] - self->height; } else { self->pos2[2] = self->s.v.origin[2] - self->s.v.size[2] + 8; } self->use = (func_t) plat_trigger_use; plat_spawn_inside_trigger(); // the "start moving" trigger if (self->targetname) { self->state = STATE_UP; self->use = (func_t) plat_use; } else { setorigin(self, PASSVEC3(self->pos2)); self->state = STATE_BOTTOM; } } //============================================================================ void train_next(void); void funcref_train_find(void); void train_blocked(void) { if (g_globalvars.time < self->attack_finished) { return; } self->attack_finished = g_globalvars.time + 0.5; other->deathtype = dtSQUISH; T_Damage(other, self, self, self->dmg); } void train_use(void) { if (self->think != (func_t) funcref_train_find) { return; // already activated } train_next(); } void train_wait(void) { if (self->wait) { self->s.v.nextthink = self->s.v.ltime + self->wait; sound(self, CHAN_NO_PHS_ADD + CHAN_VOICE, self->noise, 1, ATTN_NORM); } else { self->s.v.nextthink = self->s.v.ltime + 0.1; } // make trains stop if frozen if ((match_in_progress == 2) || (!cvar("k_freeze") && !match_in_progress) || k_practice) // #practice mode# { self->think = (func_t) train_next; } } void train_next(void) { gedict_t *targ; vec3_t tmpv; targ = find(world, FOFS(targetname), self->target); if (!targ) { G_Error("train_next: no next target"); } self->target = targ->target; if (!self->target) { G_Error("train_next: no next target"); } if (targ->wait) { self->wait = targ->wait; } else { self->wait = 0; } sound(self, CHAN_VOICE, self->noise1, 1, ATTN_NORM); VectorSubtract(targ->s.v.origin, self->s.v.mins, tmpv); SUB_CalcMove(tmpv, self->speed, train_wait); } void funcref_train_find(void) { gedict_t *targ; targ = find(world, FOFS(targetname), self->target); if (!targ) { G_Error("funcref_train_find: no next target"); } // qqshka: i comment below line, this let us freeze level _right_ after spawn, // of course if k_freeze is set, if u uncomment this, train will move one time, // even k_freeze is set // self->target = targ->target; setorigin(self, targ->s.v.origin[0] - self->s.v.mins[0], targ->s.v.origin[1] - self->s.v.mins[1], targ->s.v.origin[2] - self->s.v.mins[2]); if (!self->targetname) { // not triggered, so start immediately self->s.v.nextthink = self->s.v.ltime + 0.1; self->think = (func_t) train_next; } } /*QUAKED funcref_train (0 .5 .8) ? 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 sounds 1) ratchet metal */ void SP_func_train(void) { if (!self->speed) { self->speed = 100; } if (!self->target) { G_Error("funcref_train without a target"); } if (!self->dmg) { self->dmg = 2; } if (self->s.v.sounds == 0) { // self->noise = ( "misc/null.wav" ); /// trap_precache_sound( "misc/null.wav" ); // self->noise1 = ( "misc/null.wav" ); // trap_precache_sound( "misc/null.wav" ); // qqshka: shut up null.wav, have some artefact, we can hear self->noise = ""; self->noise1 = ""; } if (self->s.v.sounds == 1) { self->noise = ("plats/train2.wav"); trap_precache_sound("plats/train2.wav"); self->noise1 = ("plats/train1.wav"); trap_precache_sound("plats/train1.wav"); } self->cnt = 1; self->s.v.solid = SOLID_BSP; self->s.v.movetype = MOVETYPE_PUSH; self->blocked = (func_t) train_blocked; self->use = (func_t) train_use; self->classname = "train"; setmodel(self, self->model); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); setorigin(self, PASSVEC3(self->s.v.origin)); // start trains on the second frame, to make sure their targets have had // a chance to spawn self->s.v.nextthink = self->s.v.ltime + 0.1; self->think = (func_t) funcref_train_find; } /*QUAKED misc_teleporttrain (0 .5 .8) (-8 -8 -8) (8 8 8) This is used for the final bos */ void SP_misc_teleporttrain(void) { if (!self->speed) { self->speed = 100; } if (!self->target) { G_Error("funcref_train without a target"); } self->cnt = 1; self->s.v.solid = SOLID_NOT; self->s.v.movetype = MOVETYPE_PUSH; self->blocked = (func_t) train_blocked; self->use = (func_t) train_use; SetVector(self->s.v.avelocity, 100, 200, 300); //self->s.v.avelocity = '100 200 300'; // self->noise = ( "misc/null.wav" ); // trap_precache_sound( "misc/null.wav" ); // self->noise1 = ( "misc/null.wav" ); // trap_precache_sound( "misc/null.wav" ); // qqshka: shut up null.wav, have some artefact, we can hear self->noise = ""; self->noise1 = ""; trap_precache_model("progs/teleport.mdl"); setmodel(self, "progs/teleport.mdl"); setsize(self, PASSVEC3(self->s.v.mins), PASSVEC3(self->s.v.maxs)); setorigin(self, PASSVEC3(self->s.v.origin)); // start trains on the second frame, to make sure their targets have had // a chance to spawn self->s.v.nextthink = self->s.v.ltime + 0.1; self->think = (func_t) funcref_train_find; } QW-Group-ktx-d05d6ca/src/player.c000066400000000000000000001016401475442401000166610ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void bubble_bob(void); void BotPlayerDeathEvent(gedict_t *player); void AmmoUsed(gedict_t *player); /* ============================================================================== PLAYER ============================================================================== */ void player_run(void); void player_stand1(void) { self->s.v.frame = 17; self->think = (func_t) player_stand1; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 0; if (self->s.v.velocity[0] || self->s.v.velocity[1]) { self->walkframe = 0; player_run(); return; } if ((self->s.v.weapon == IT_AXE) || (self->s.v.weapon == IT_HOOK)) { if (self->walkframe >= 12) { self->walkframe = 0; } self->s.v.frame = 17 + self->walkframe; } else { if (self->walkframe >= 5) { self->walkframe = 0; } self->s.v.frame = 12 + self->walkframe; } self->walkframe = self->walkframe + 1; } void player_run(void) { self->s.v.frame = 6; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 0; if (!self->s.v.velocity[0] && !self->s.v.velocity[1]) { self->walkframe = 0; player_stand1(); return; } if (self->s.v.weapon == IT_AXE || self->s.v.weapon == IT_HOOK) { if (self->walkframe >= 6) { self->walkframe = 0; } if (self->movement[0] < 0) { self->s.v.frame = 5 - self->walkframe; } else { self->s.v.frame = 0 + self->walkframe; } } else { if (self->walkframe >= 6) { self->walkframe = 0; } if (self->movement[0] < 0) { self->s.v.frame = 11 - self->walkframe; } else { self->s.v.frame = 6 + self->walkframe; } } self->walkframe = self->walkframe + 1; } void muzzleflash(void) { WriteByte( MSG_MULTICAST, SVC_MUZZLEFLASH); WriteEntity( MSG_MULTICAST, self); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PVS); } void player_chain1(void) { self->s.v.frame = 137; self->think = (func_t) player_chain2; self->s.v.nextthink = next_frame(); self->s.v.weaponframe = 2; GrappleThrow(); } void player_chain2(void) { self->s.v.frame = 138; self->think = (func_t) player_chain3; self->s.v.nextthink = next_frame(); self->s.v.weaponframe = 3; } void player_chain3(void) { self->s.v.frame = 139; self->s.v.weaponframe = 3; if (!self->hook_out) { player_chain5(); } else if (vlen(self->s.v.velocity) >= 750) { player_chain4(); } else { self->think = (func_t) player_chain3; self->s.v.nextthink = next_frame(); } } void player_chain4(void) { // Original ctf grapple used frame 73 here, but that causes problems with cl_deadbodyfilter 2 // Frame 139 is a decent alternative especially given that 73 never looked good anyway // self->s.v.frame = 73; self->s.v.frame = 139; self->s.v.weaponframe = 4; if (!self->hook_out) { player_chain5(); } else if (vlen(self->s.v.velocity) < 750) { player_chain3(); } else { self->think = (func_t) player_chain4; self->s.v.nextthink = next_frame(); } } void player_chain5(void) { self->s.v.frame = 140; self->s.v.weaponframe = 5; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = next_frame(); } void player_shot1(void) { self->s.v.frame = 113; self->think = (func_t) player_shot2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 1; muzzleflash(); } void player_shot2(void) { self->s.v.frame = 114; self->think = (func_t) player_shot3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 2; } void player_shot3(void) { self->s.v.frame = 115; self->think = (func_t) player_shot4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 3; } void player_shot4(void) { self->s.v.frame = 116; self->think = (func_t) player_shot5; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 4; } void player_shot5(void) { self->s.v.frame = 117; self->think = (func_t) player_shot6; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 5; } void player_shot6(void) { self->s.v.frame = 118; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 6; } void player_axe1(void) { self->s.v.frame = 119; self->think = (func_t) player_axe2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 1; } void player_axe2(void) { self->s.v.frame = 120; self->think = (func_t) player_axe3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 2; } void player_axe3(void) { self->s.v.frame = 121; self->think = (func_t) player_axe4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 3; W_FireAxe(); } void player_axe4(void) { self->s.v.frame = 122; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 4; } void player_axeb1(void) { self->s.v.frame = 125; self->think = (func_t) player_axeb2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 5; } void player_axeb2(void) { self->s.v.frame = 126; self->think = (func_t) player_axeb3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 6; } void player_axeb3(void) { self->s.v.frame = 127; self->think = (func_t) player_axeb4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 7; W_FireAxe(); } void player_axeb4(void) { self->s.v.frame = 128; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 8; } void player_axec1(void) { self->s.v.frame = 131; self->think = (func_t) player_axec2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 1; } void player_axec2(void) { self->s.v.frame = 132; self->think = (func_t) player_axec3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 2; } void player_axec3(void) { self->s.v.frame = 133; self->think = (func_t) player_axec4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 3; W_FireAxe(); } void player_axec4(void) { self->s.v.frame = 134; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 4; } void player_axed1(void) { self->s.v.frame = 137; self->think = (func_t) player_axed2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 5; } void player_axed2(void) { self->s.v.frame = 138; self->think = (func_t) player_axed3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 6; } void player_axed3(void) { self->s.v.frame = 139; self->think = (func_t) player_axed4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 7; W_FireAxe(); } void player_axed4(void) { self->s.v.frame = 140; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 8; } //============================================================================ // this shit present in ktpro, but test does't show why we need this, because 99.9% of time diff is just 0 void set_idealtime(void) { float diff = self->s.v.ltime - g_globalvars.time; if (diff < -0.05) { diff = -0.05; } self->s.v.nextthink = self->s.v.ltime = g_globalvars.time + diff + 0.1; } void player_nail1(void) { self->s.v.frame = 103; self->think = (func_t) player_nail2; self->s.v.nextthink = g_globalvars.time + 0.1; if (!self->s.v.button0 || intermission_running || self->s.v.impulse) { self->walkframe = 0; player_run(); return; } set_idealtime(); muzzleflash(); self->s.v.weaponframe = self->s.v.weaponframe + 1; if (self->s.v.weaponframe >= 9) { self->s.v.weaponframe = 1; } SuperDamageSound(); W_FireSpikes(4); self->attack_finished = g_globalvars.time + 0.2; AmmoUsed(self); } void player_nail2(void) { self->s.v.frame = 104; self->think = (func_t) player_nail1; self->s.v.nextthink = g_globalvars.time + 0.1; if (!self->s.v.button0 || intermission_running || self->s.v.impulse) { self->walkframe = 0; player_run(); return; } set_idealtime(); muzzleflash(); self->s.v.weaponframe = self->s.v.weaponframe + 1; if (self->s.v.weaponframe >= 9) { self->s.v.weaponframe = 1; } SuperDamageSound(); W_FireSpikes(-4); self->attack_finished = g_globalvars.time + 0.2; AmmoUsed(self); } //============================================================================ void player_light1(void) { self->s.v.frame = 105; self->think = (func_t) player_light2; self->s.v.nextthink = g_globalvars.time + 0.1; if (!self->s.v.button0 || intermission_running || self->s.v.impulse) { if (lgc_enabled()) { lgc_register_fire_stop(self); } self->walkframe = 0; player_run(); return; } set_idealtime(); muzzleflash(); self->s.v.weaponframe = self->s.v.weaponframe + 1; if (self->s.v.weaponframe >= 5) { self->s.v.weaponframe = 1; } SuperDamageSound(); W_FireLightning(); self->attack_finished = g_globalvars.time + 0.2; } void player_light2(void) { self->s.v.frame = 106; self->think = (func_t) player_light1; self->s.v.nextthink = g_globalvars.time + 0.1; if (!self->s.v.button0 || intermission_running || self->s.v.impulse) { if (lgc_enabled()) { lgc_register_fire_stop(self); } self->walkframe = 0; player_run(); return; } set_idealtime(); muzzleflash(); self->s.v.weaponframe = self->s.v.weaponframe + 1; if (self->s.v.weaponframe >= 5) { self->s.v.weaponframe = 1; } SuperDamageSound(); W_FireLightning(); self->attack_finished = g_globalvars.time + 0.2; } //============================================================================ void player_rocket1(void) { self->s.v.frame = 107; self->think = (func_t) player_rocket2; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 1; muzzleflash(); } void player_rocket2(void) { self->s.v.frame = 108; self->think = (func_t) player_rocket3; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 2; } void player_rocket3(void) { self->s.v.frame = 109; self->think = (func_t) player_rocket4; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 3; } void player_rocket4(void) { self->s.v.frame = 110; self->think = (func_t) player_rocket5; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 4; } void player_rocket5(void) { self->s.v.frame = 111; self->think = (func_t) player_rocket6; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 5; } void player_rocket6(void) { self->s.v.frame = 112; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 6; } void DeathBubbles(float num_bubbles); void PainSound(void) { int rs; if (ISDEAD(self)) { return; } // water pain sounds if (((self->s.v.watertype == CONTENT_WATER) || (self->s.v.watertype == CONTENT_SLIME)) && (self->s.v.waterlevel == 3)) { DeathBubbles(1); if (match_in_progress != 2) { return; } if (g_random() > 0.5) { sound(self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, "player/drown2.wav", 1, ATTN_NORM); } return; } // slime pain sounds if (self->s.v.watertype == CONTENT_SLIME) { // FIX ME put in some steam here if (match_in_progress != 2) { return; } if (g_random() > 0.5) { sound(self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM); } return; } if (self->s.v.watertype == CONTENT_LAVA) { if (match_in_progress != 2) { return; } if (g_random() > 0.5) { sound(self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM); } return; } if (self->pain_finished > g_globalvars.time) { self->axhitme = 0; return; } self->pain_finished = g_globalvars.time + 0.5; // don't make multiple pain sounds right after each other // ax pain sound if (self->axhitme == 1) { self->axhitme = 0; sound(self, CHAN_VOICE, "player/axhit1.wav", 1, ATTN_NORM); return; } rs = (g_random() * 5) + 1; self->noise = ""; if (rs == 1) { self->noise = "player/pain1.wav"; } else if (rs == 2) { self->noise = "player/pain2.wav"; } else if (rs == 3) { self->noise = "player/pain3.wav"; } else if (rs == 4) { self->noise = "player/pain4.wav"; } else if (rs == 5) { self->noise = "player/pain5.wav"; } else { self->noise = "player/pain6.wav"; } sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); return; } void player_pain1(void) { self->s.v.frame = 35; self->think = (func_t) player_pain2; self->s.v.nextthink = g_globalvars.time + 0.1; PainSound(); self->s.v.weaponframe = 0; } void player_pain2(void) { self->s.v.frame = 36; self->think = (func_t) player_pain3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_pain3(void) { self->s.v.frame = 37; self->think = (func_t) player_pain4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_pain4(void) { self->s.v.frame = 38; self->think = (func_t) player_pain5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_pain5(void) { self->s.v.frame = 39; self->think = (func_t) player_pain6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_pain6(void) { self->s.v.frame = 40; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_axpain1(void) { self->s.v.frame = 29; self->think = (func_t) player_axpain2; self->s.v.nextthink = g_globalvars.time + 0.1; PainSound(); self->s.v.weaponframe = 0; } void player_axpain2(void) { self->s.v.frame = 30; self->think = (func_t) player_axpain3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_axpain3(void) { self->s.v.frame = 31; self->think = (func_t) player_axpain4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_axpain4(void) { self->s.v.frame = 32; self->think = (func_t) player_axpain5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_axpain5(void) { self->s.v.frame = 33; self->think = (func_t) player_axpain6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_axpain6(void) { self->s.v.frame = 34; self->walkframe = 0; self->think = (func_t) player_run; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_pain(struct gedict_s *attacker, float take) { // G_bprint(2, "player_pain\n"); if (match_in_progress != 2) { return; // no pain at all in prewar } if (isCA() && (streq(getteam(self), getteam(attacker)) || self->no_pain)) { return; // No pain when shooting teammates in CA or when respawning (wipeout) } if (self->s.v.weaponframe) { return; } if (self->invisible_finished > g_globalvars.time) { return; // eyes don't have pain frames } if (self->s.v.weapon == IT_AXE) { player_axpain1(); } else { player_pain1(); } } void player_diea1(void); void player_dieb1(void); void player_diec1(void); void player_died1(void); void player_diee1(void); void player_die_ax1(void); void DeathBubblesSpawn(void) { gedict_t *bubble; if (PROG_TO_EDICT(self->s.v.owner)->s.v.waterlevel != 3) { return; } bubble = spawn(); setmodel(bubble, "progs/s_bubble.spr"); setorigin(bubble, PROG_TO_EDICT(self->s.v.owner)->s.v.origin[0], PROG_TO_EDICT(self->s.v.owner)->s.v.origin[1], PROG_TO_EDICT(self->s.v.owner)->s.v.origin[2] + 24); bubble->s.v.movetype = MOVETYPE_NOCLIP; bubble->s.v.solid = SOLID_NOT; SetVector(bubble->s.v.velocity, 0, 0, 15); bubble->s.v.nextthink = g_globalvars.time + 0.5; bubble->think = (func_t) bubble_bob; bubble->classname = "bubble"; bubble->s.v.frame = 0; bubble->cnt = 0; setsize(bubble, -8, -8, -8, 8, 8, 8); self->s.v.nextthink = g_globalvars.time + 0.1; self->think = (func_t) DeathBubblesSpawn; self->air_finished = self->air_finished + 1; if (self->air_finished >= self->bubble_count) { ent_remove(self); } } void DeathBubbles(float num_bubbles) { gedict_t *bubble_spawner; bubble_spawner = spawn(); setorigin(bubble_spawner, PASSVEC3(self->s.v.origin)); bubble_spawner->s.v.movetype = MOVETYPE_NONE; bubble_spawner->s.v.solid = SOLID_NOT; bubble_spawner->s.v.nextthink = g_globalvars.time + 0.1; bubble_spawner->think = (func_t) DeathBubblesSpawn; bubble_spawner->air_finished = 0; bubble_spawner->s.v.owner = EDICT_TO_PROG(self); bubble_spawner->bubble_count = num_bubbles; return; } void DeathSound(void) { int rs; // water death sounds if (self->s.v.waterlevel == 3) { DeathBubbles(5); sound(self, CHAN_VOICE, "player/h2odeath.wav", 1, ATTN_NONE); return; } rs = ((g_random() * 4) + 1); if (rs == 1) { self->noise = "player/death1.wav"; } if (rs == 2) { self->noise = "player/death2.wav"; } if (rs == 3) { self->noise = "player/death3.wav"; } if (rs == 4) { self->noise = "player/death4.wav"; } if (rs == 5) { self->noise = "player/death5.wav"; } sound(self, CHAN_VOICE, self->noise, 1, ATTN_NONE); return; } void PlayerDead(void) { self->s.v.nextthink = -1; // allow respawn after a certain time self->s.v.deadflag = DEAD_DEAD; // Yawnmode: hide player corpses after animation // - Molgrum if (k_yawnmode) { setmodel(self, ""); } } void VelocityForDamage(float dm, vec3_t v) { vec3_t v2; if (vlen(damage_inflictor->s.v.velocity) > 0) { VectorScale(damage_inflictor->s.v.velocity, 0.5, v); VectorSubtract(self->s.v.origin, damage_inflictor->s.v.origin, v2); VectorNormalize(v2); VectorScale(v2, 25, v2); VectorAdd(v, v2, v); // v = 0.5 * damage_inflictor->s.v.velocity; // v = v + (25 * normalize((self->s.v.origin)-damage_inflictor->s.v.origin)); v[2] = 100 + 240 * g_random(); v[0] = v[0] + (200 * crandom()); v[1] = v[1] + (200 * crandom()); //dprint ("Velocity gib\n"); } else { v[0] = 100 * crandom(); v[1] = 100 * crandom(); v[2] = 200 + 100 * g_random(); } //v[0] = 100 * crandom(); //v[1] = 100 * crandom(); //v[2] = 200 + 100 * g_random(); if (dm > -50) { // dprint ("level 1\n"); VectorScale(v, 0.7, v); // v = v * 0.7; } else if (dm > -200) { // dprint ("level 3\n"); VectorScale(v, 2, v); // v = v * 2; } else VectorScale(v, 10, v); // v = v * 10; return;//v; } gedict_t* ThrowGib(char *gibname, float dm) { gedict_t *newent; int k_short_gib = cvar("k_short_gib"); // if set - remove faster newent = spawn(); VectorCopy(self->s.v.origin, newent->s.v.origin); setmodel(newent, gibname); setsize(newent, 0, 0, 0, 0, 0, 0); VelocityForDamage(dm, newent->s.v.velocity); newent->s.v.movetype = MOVETYPE_BOUNCE; newent->isMissile = true; newent->s.v.solid = SOLID_NOT; newent->s.v.avelocity[0] = g_random() * 600; newent->s.v.avelocity[1] = g_random() * 600; newent->s.v.avelocity[2] = g_random() * 600; newent->think = (func_t) SUB_Remove; newent->s.v.ltime = g_globalvars.time; newent->s.v.nextthink = g_globalvars.time + (k_short_gib ? 2 : (10 + g_random() * 10)); newent->s.v.frame = 0; newent->s.v.flags = 0; return newent; } void ThrowHead(char *gibname, float dm) { setmodel(self, gibname); self->s.v.frame = 0; self->s.v.movetype = MOVETYPE_BOUNCE; // qqshka: NO, you can't do that, that NOT projectile, its player entity! // self->isMissile = true; self->s.v.takedamage = DAMAGE_NO; self->s.v.solid = SOLID_NOT; SetVector(self->s.v.view_ofs, 0, 0, 8); setsize(self, -16, -16, 0, 16, 16, 56); VelocityForDamage(dm, self->s.v.velocity); self->s.v.origin[2] = self->s.v.origin[2] - 24; self->s.v.flags -= ((int)(self->s.v.flags)) & FL_ONGROUND; SetVector(self->s.v.avelocity, 0, crandom() * 600, 0); } void GibPlayer(void) { qbool bloodfest_round_connect = (k_bloodfest && !self->ready); // in case of bloodfest and connecion during round. gedict_t *p; self->vw_index = 0; if (isRACE() || bloodfest_round_connect) { ThrowHead("", self->s.v.health); } else { ThrowHead("progs/h_player.mdl", self->s.v.health); } if (bloodfest_round_connect) { return; // do not spawn sounds and gibs, preventing abuse. } if (match_in_progress == 2) { ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); } if (isRACE() && race.status) { return; } // spawn temporary entity. p = spawn(); setorigin(p, PASSVEC3(self->s.v.origin)); p->s.v.nextthink = g_globalvars.time + 0.1; p->think = (func_t) SUB_Remove; if (TELEDEATH(self)) { sound(p, CHAN_VOICE, "player/teledth1.wav", 1, ATTN_NONE); } else { sound(p, CHAN_VOICE, (g_random() < 0.5 ? "player/gib.wav" : "player/udeath.wav"), 1, ATTN_NONE); } } void StartDie(void); void PlayerBreak(void); void PlayerDie(void) { self->ca_alive = false; if (!self->isBot && tot_mode_enabled() && cvar(FB_CVAR_BREAK_ON_DEATH)) { PlayerBreak(); } DropPowerups(); if (isCTF()) { if (self->hook_out) { GrappleReset(self->hook); self->attack_finished = g_globalvars.time + 0.75; self->hook_out = true; // FIXME: for which reason this set to true? } DropRune(); PlayerDropFlag(self, false); } TeamplayDeathEvent(self); #ifdef BOT_SUPPORT BotPlayerDeathEvent(self); #endif self->s.v.items -= (int)self->s.v.items & IT_INVISIBILITY; self->invisible_finished = 0; // don't die as eyes self->invincible_finished = 0; // so we have quad few milleseconds after death // self->super_damage_finished = 0; // moved to prethink, like in ktpro self->radsuit_finished = 0; self->s.v.modelindex = modelindex_player; // don't use eyes DropBackpack(); self->weaponmodel = ""; if (vw_enabled) { self->vw_index = 9; // null vwep model } SetVector(self->s.v.view_ofs, 0, 0, -8); self->s.v.deadflag = DEAD_DYING; self->s.v.solid = SOLID_NOT; self->s.v.flags -= ((int)(self->s.v.flags)) & FL_ONGROUND; self->s.v.movetype = MOVETYPE_TOSS; if (self->s.v.velocity[2] < 10) { self->s.v.velocity[2] = self->s.v.velocity[2] + g_random() * 300; } if ((self->s.v.health < -40) || (dtSQUISH == self->deathtype) || (dtSUICIDE == self->deathtype) || isRA()) { GibPlayer(); // Yawnmode: respawn has the same delay (900ms) regardless of deathtype gib/normal // - Molgrum // Hoonymode: Also force some time, e.g. to prevent instant respawn after /kill which // can cause bug if kill telefrags an idle player (counts as two points...) // only ever happens in testing, but oh well --phil if (k_yawnmode || isHoonyModeDuel()) { self->s.v.nextthink = g_globalvars.time + 0.9; self->think = (func_t) PlayerDead; return; } PlayerDead(); return; } if (match_in_progress == 2) { DeathSound(); } self->s.v.angles[0] = 0; self->s.v.angles[2] = 0; // function part split and called here StartDie(); } // created this function because it is called from client.qc as well // was originally part of PlayerDie() and hasn't been altered void StartDie(void) { if (self->s.v.weapon == IT_AXE) { player_die_ax1(); return; } // if ( k_yawnmode ) // qqshka: this way it better if (1) { // Yawnmode: exclude diea1 and diec1 so the respawn time is always 900 ms switch (i_rnd(1, 3)) { case 1: player_dieb1(); break; case 2: player_died1(); break; default: player_diee1(); break; } } else { // Note that this generates random values in 1..6 range, so player_diee1 is // executed twice as often as other death sequences. Dunno if this should be fixed -- Tonik int i = 1 + floor(g_random() * 6); switch (i) { case 1: player_diea1(); break; case 2: player_dieb1(); break; case 3: player_diec1(); break; case 4: player_died1(); break; default: player_diee1(); break; } } } void player_diea1(void) { self->s.v.frame = 50; self->think = (func_t) player_diea2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea2(void) { self->s.v.frame = 51; self->think = (func_t) player_diea3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea3(void) { self->s.v.frame = 52; self->think = (func_t) player_diea4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea4(void) { self->s.v.frame = 53; self->think = (func_t) player_diea5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea5(void) { self->s.v.frame = 54; self->think = (func_t) player_diea6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea6(void) { self->s.v.frame = 55; self->think = (func_t) player_diea7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea7(void) { self->s.v.frame = 56; self->think = (func_t) player_diea8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea8(void) { self->s.v.frame = 57; self->think = (func_t) player_diea9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea9(void) { self->s.v.frame = 58; self->think = (func_t) player_diea10; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea10(void) { self->s.v.frame = 59; self->think = (func_t) player_diea11; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diea11(void) { self->s.v.frame = 60; self->think = (func_t) player_diea11; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } void player_dieb1(void) { self->s.v.frame = 61; self->think = (func_t) player_dieb2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb2(void) { self->s.v.frame = 62; self->think = (func_t) player_dieb3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb3(void) { self->s.v.frame = 63; self->think = (func_t) player_dieb4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb4(void) { self->s.v.frame = 64; self->think = (func_t) player_dieb5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb5(void) { self->s.v.frame = 65; self->think = (func_t) player_dieb6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb6(void) { self->s.v.frame = 66; self->think = (func_t) player_dieb7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb7(void) { self->s.v.frame = 67; self->think = (func_t) player_dieb8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb8(void) { self->s.v.frame = 68; self->think = (func_t) player_dieb9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_dieb9(void) { self->s.v.frame = 69; self->think = (func_t) player_dieb9; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } void player_diec1(void) { self->s.v.frame = 70; self->think = (func_t) player_diec2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec2(void) { self->s.v.frame = 71; self->think = (func_t) player_diec3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec3(void) { self->s.v.frame = 72; self->think = (func_t) player_diec4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec4(void) { self->s.v.frame = 73; self->think = (func_t) player_diec5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec5(void) { self->s.v.frame = 74; self->think = (func_t) player_diec6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec6(void) { self->s.v.frame = 75; self->think = (func_t) player_diec7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec7(void) { self->s.v.frame = 76; self->think = (func_t) player_diec8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec8(void) { self->s.v.frame = 77; self->think = (func_t) player_diec9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec9(void) { self->s.v.frame = 78; self->think = (func_t) player_diec10; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec10(void) { self->s.v.frame = 79; self->think = (func_t) player_diec11; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec11(void) { self->s.v.frame = 80; self->think = (func_t) player_diec12; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec12(void) { self->s.v.frame = 81; self->think = (func_t) player_diec13; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec13(void) { self->s.v.frame = 82; self->think = (func_t) player_diec14; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec14(void) { self->s.v.frame = 83; self->think = (func_t) player_diec15; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diec15(void) { self->s.v.frame = 84; self->think = (func_t) player_diec15; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } void player_died1(void) { self->s.v.frame = 85; self->think = (func_t) player_died2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died2(void) { self->s.v.frame = 86; self->think = (func_t) player_died3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died3(void) { self->s.v.frame = 87; self->think = (func_t) player_died4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died4(void) { self->s.v.frame = 88; self->think = (func_t) player_died5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died5(void) { self->s.v.frame = 89; self->think = (func_t) player_died6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died6(void) { self->s.v.frame = 90; self->think = (func_t) player_died7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died7(void) { self->s.v.frame = 91; self->think = (func_t) player_died8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died8(void) { self->s.v.frame = 92; self->think = (func_t) player_died9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_died9(void) { self->s.v.frame = 93; self->think = (func_t) player_died9; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } void player_diee1(void) { self->s.v.frame = 94; self->think = (func_t) player_diee2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee2(void) { self->s.v.frame = 95; self->think = (func_t) player_diee3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee3(void) { self->s.v.frame = 96; self->think = (func_t) player_diee4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee4(void) { self->s.v.frame = 97; self->think = (func_t) player_diee5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee5(void) { self->s.v.frame = 98; self->think = (func_t) player_diee6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee6(void) { self->s.v.frame = 99; self->think = (func_t) player_diee7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee7(void) { self->s.v.frame = 100; self->think = (func_t) player_diee8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee8(void) { self->s.v.frame = 101; self->think = (func_t) player_diee9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_diee9(void) { self->s.v.frame = 102; self->think = (func_t) player_diee9; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } void player_die_ax1(void) { self->s.v.frame = 41; self->think = (func_t) player_die_ax2; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax2(void) { self->s.v.frame = 42; self->think = (func_t) player_die_ax3; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax3(void) { self->s.v.frame = 43; self->think = (func_t) player_die_ax4; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax4(void) { self->s.v.frame = 44; self->think = (func_t) player_die_ax5; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax5(void) { self->s.v.frame = 45; self->think = (func_t) player_die_ax6; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax6(void) { self->s.v.frame = 46; self->think = (func_t) player_die_ax7; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax7(void) { self->s.v.frame = 47; self->think = (func_t) player_die_ax8; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax8(void) { self->s.v.frame = 48; self->think = (func_t) player_die_ax9; self->s.v.nextthink = g_globalvars.time + 0.1; } void player_die_ax9(void) { self->s.v.frame = 49; self->think = (func_t) player_die_ax9; self->s.v.nextthink = g_globalvars.time + 0.1; PlayerDead(); } QW-Group-ktx-d05d6ca/src/q_shared.c000066400000000000000000000144301475442401000171530ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ // q_shared.c -- stateless support routines that are included in each code dll #include "q_shared.h" /* ============================================================================ BYTE ORDER FUNCTIONS ============================================================================ */ /* // can't just use function pointers, or dll linkage can // mess up when qcommon is included in multiple places static short (*_BigShort) (short l); static short (*_LittleShort) (short l); static int (*_BigLong) (int l); static int (*_LittleLong) (int l); static qint64 (*_BigLong64) (qint64 l); static qint64 (*_LittleLong64) (qint64 l); static float (*_BigFloat) (const float *l); static float (*_LittleFloat) (const 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);} qint64 BigLong64 (qint64 l) {return _BigLong64(l);} qint64 LittleLong64 (qint64 l) {return _LittleLong64(l);} float BigFloat (const float *l) {return _BigFloat(l);} float LittleFloat (const float *l) {return _LittleFloat(l);} */ extern void G_Error(const char *fmt, ...) PRINTF_FUNC(1); 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; } qint64 Long64Swap(qint64 ll) { qint64 result; result.b0 = ll.b7; result.b1 = ll.b6; result.b2 = ll.b5; result.b3 = ll.b4; result.b4 = ll.b3; result.b5 = ll.b2; result.b6 = ll.b1; result.b7 = ll.b0; return result; } qint64 Long64NoSwap(qint64 ll) { return ll; } typedef union { float f; unsigned int i; } _FloatByteUnion; float FloatSwap(const float *f) { const _FloatByteUnion *in; _FloatByteUnion out; in = (_FloatByteUnion*) f; out.i = LongSwap(in->i); return out.f; } float FloatNoSwap(const float *f) { return *f; } /* ================ Swap_Init ================ */ /* void Swap_Init (void) { byte swaptest[2] = {1,0}; // set the byte swapping variables in a portable manner if ( *(short *)swaptest == 1) { _BigShort = ShortSwap; _LittleShort = ShortNoSwap; _BigLong = LongSwap; _LittleLong = LongNoSwap; _BigLong64 = Long64Swap; _LittleLong64 = Long64NoSwap; _BigFloat = FloatSwap; _LittleFloat = FloatNoSwap; } else { _BigShort = ShortNoSwap; _LittleShort = ShortSwap; _BigLong = LongNoSwap; _LittleLong = LongSwap; _BigLong64 = Long64NoSwap; _LittleLong64 = Long64Swap; _BigFloat = FloatNoSwap; _LittleFloat = FloatSwap; } } */ /* ============================================================================ LIBRARY REPLACEMENT FUNCTIONS ============================================================================ */ int Q_isprint(int c) { if ((c >= 0x20) && (c <= 0x7E)) { return (1); } return (0); } int Q_islower(int c) { if ((c >= 'a') && (c <= 'z')) { return (1); } return (0); } int Q_isupper(int c) { if ((c >= 'A') && (c <= 'Z')) { return (1); } return (0); } int Q_isalpha(int c) { if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { return (1); } return (0); } char* Q_strrchr(const char *string, int c) { char cc = c; char *s; char *sp = (char*) 0; s = (char*) string; while (*s) { if (*s == cc) { sp = s; } s++; } if (cc == 0) { sp = s; } return sp; } /* ============= Q_strncpyz Safe strncpy that ensures a trailing zero ============= */ void Q_strncpyz(char *dest, const char *src, int destsize) { // bk001129 - also NULL dest if (!dest) { G_Error("Q_strncpyz: NULL dest"); } if (!src) { G_Error("Q_strncpyz: NULL src"); } if (destsize < 1) { G_Error("Q_strncpyz: destsize < 1"); } strncpy(dest, src, destsize - 1); dest[destsize - 1] = 0; } int Q_stricmpn(const char *s1, const char *s2, int n) { int c1, c2; // bk001129 - moved in 1.17 fix not in id codebase if (s1 == NULL) { if (s2 == NULL) { return 0; } else { return -1; } } else if (s2 == NULL) { return 1; } 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 ((c1 < c2) ? -1 : 1); } } } while (c1); return 0; // strings are equal } int Q_strncmp(const char *s1, const 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) { return ((c1 < c2) ? -1 : 1); } } while (c1); return 0; // strings are equal } int Q_stricmp(const char *s1, const char *s2) { return ((s1 && s2) ? Q_stricmpn(s1, s2, 99999) : -1); } char* Q_strlwr(char *s1) { char *s; s = s1; while (*s) { *s = tolower(*s); s++; } return s1; } char* Q_strupr(char *s1) { char *s; s = s1; while (*s) { *s = toupper(*s); s++; } return s1; } // never goes past bounds or leaves without a terminating 0 void Q_strcat(char *dest, int size, const char *src) { int l1; l1 = strlen(dest); if (l1 >= size) { G_Error("Q_strcat: already overflowed"); } Q_strncpyz(dest + l1, src, size - l1); } QW-Group-ktx-d05d6ca/src/race.c000066400000000000000000003627711475442401000163150ustar00rootroot00000000000000// // race.c - race implementation, yeah got inspiration from ktpro (c) (tm) (etc) // #include "g_local.h" void SP_info_intermission(void); #define MAX_TXTLEN 128 #define TOP_FILE_VERSION 2 #define POS_FILE_VERSION 2 #define RACEFLAG_TOUCH_RACEFAIL 1 #define RACEFLAG_TOUCH_RACEEND 2 #define RACEFLAG_ENTITY_KEEP 4 #define RACE_MAX_CAPTURES 600 #define RACE_CAPTURE_FPS 10 #define RACE_GUIDE_BASE_ENT (MAX_CLIENTS + 1) #define RACE_JUMP_INDICATORS 4 #define RACE_PACEMAKER_JUMPS_CVAR "k_race_pace_jumps" #define RACE_PACEMAKER_LEGAL_RECORD "k_race_pace_legal" #define RACE_PACEMAKER_HEADSTART_CVAR "k_race_pace_headstart" #define RACE_PACEMAKER_RESOLUTION_CVAR "k_race_pace_resolution" #define RACE_PACEMAKER_ENABLED_CVAR "k_race_pace_enabled" #define RACE_SIMULTANEOUS_CVAR "k_race_simultaneous" #define RACE_SCORINGSYSTEM_CVAR "k_race_scoring_system" #define RACE_MATCH_CVAR "k_race_match" #define RACE_MATCH_ROUNDS_CVAR "k_race_match_rounds" #define RACE_ROUTE_NUMBER_CVAR "k_race_route_number" #define RACE_ROUTE_MAPNAME_CVAR "k_race_route_mapname" #define RACE_PACEMAKER_HEADSTART_MIN 0.00f #define RACE_PACEMAKER_HEADSTART_MAX 1.00f #define RACE_PACEMAKER_HEADSTART_INCR 0.25f #define RACE_PACEMAKER_RESOLUTION_MIN 0 #define RACE_PACEMAKER_RESOLUTION_MAX 3 #define RACE_PACEMAKER_RESOLUTION_INCR 1 #define RACE_PACEMAKER_TRAIL_COUNT 12 #define RACE_MIN_MATCH_ROUNDS 3 #define RACE_MAX_MATCH_ROUNDS 21 #define RACE_INCR_PARAMS(name) (RACE_PACEMAKER_##name##_CVAR),(RACE_PACEMAKER_##name##_INCR),(RACE_PACEMAKER_##name##_MIN),(RACE_PACEMAKER_##name##_MAX) void UserMode_SetMatchTag(char *matchtag); typedef struct race_capture_pos_s { float race_time; vec3_t origin; vec_t angles[2]; } race_capture_pos_t; typedef struct race_capture_jump_s { float race_time; vec3_t origin; } race_capture_jump_t; typedef struct race_capture_s { race_capture_pos_t positions[1200]; race_capture_jump_t jumps[100]; int position_count; int jump_count; } race_capture_t; typedef struct race_capture_playback_s { race_capture_t capture; int position; int jump; } race_capture_playback_t; race_capture_t player_captures[MAX_CLIENTS]; race_capture_playback_t guide; typedef struct race_player_match_info_s { race_capture_t best_run_capture; int wins; int completions; float times[RACE_MAX_MATCH_ROUNDS + 1]; float best_time; float total_time; float total_distance; } race_player_match_info_t; static race_player_match_info_t player_match_info[MAX_CLIENTS]; static void update_jump_markers(float race_time, int guide_start, int resolution); static gedict_t *race_jump_indicators[RACE_JUMP_INDICATORS]; static float race_jump_indicator_times[RACE_JUMP_INDICATORS]; void ktpro_autotrack_on_powerup_take(gedict_t *racer); static void race_cancel(qbool cancelrecord, const char *fmt, ...) PRINTF_FUNC(2); static void race_start(qbool cancelrecord, const char *fmt, ...) PRINTF_FUNC(2); static void race_fwopen(const char *fmt, ...) PRINTF_FUNC(1); static void race_fropen(const char *fmt, ...) PRINTF_FUNC(1); static void race_fprintf(const char *fmt, ...) PRINTF_FUNC(1); void race_unready_all(void); void r_route(void); void race_record(void); void race_stoprecord(qbool cancel); void race_remove_ent(void); void race_set_players_movetype_and_etc(void); void race_cleanmap(void); void unmute_all_players(void); void HideSpawnPoints(void); void ShowSpawnPoints(void); void kill_race_idler(void); void write_topscores(void); void read_topscores(void); void init_scores(void); qbool race_match_mode(void); qbool race_match_started(void); int race_award_points(int position, int participants); gedict_t* race_find_race_participants(gedict_t *p); qbool race_pacemaker_enabled(void); qbool is_rules_change_allowed(void); qbool race_command_checks(void); qbool race_is_started(void); static void race_update_pacemaker(void); static void race_clear_pacemaker(void); static void race_init_capture(void); static void race_save_position(void); static void race_finish_capture(qbool store, int player_num); static void race_pacemaker_race_start(void); static void race_remove_pacemaker_indicator(void); static void race_make_active_racer(gedict_t *r, gedict_t *s); static qbool race_end(gedict_t *racer, qbool valid, qbool complete); static char* race_position_string(int position); static qbool race_simultaneous(void); static void race_update_closest_positions(void); static void race_match_round_end(void); static float race_vlen(vec3_t velocity) { return sqrt(velocity[0] * velocity[0] + velocity[1] * velocity[1]); } fileHandle_t race_fhandle = -1; race_t race; // whole race struct char* classname_for_nodeType(raceRouteNodeType_t nodeType); #define RACE_INVALID_RECORD_TIME 999999 #define RACE_DEFAULT_TIMEOUT 60 #define RACE_MAX_TIMEOUT 3600 static int next_route = -1; // STATIC //============================================ static void set_usercmd_trace(gedict_t* p, qbool on) { int userId = atoi(ezinfokey(p, "*userid")); if (userId) { localcmd("sv_usercmdtrace %d %s\n", userId, on ? "on" : "off"); trap_executecmd(); } } static void clearall_usercmds_settings(void) { gedict_t* p; for (p = world; (p = find_plr(p)); ) { set_usercmd_trace(p, false); } } //============================================ static int get_server_port(void) { char *ip, *port; int i = 0; if (strnull(ip = cvar_string("sv_local_addr")) || strnull(port = strchr(ip, ':')) || !(i = atoi(port + 1))) { return 27500; } else { return i; } } static const char* race_filename(const char *extension) { static char filename[128]; if (cvar("k_race_times_per_port")) { snprintf(filename, sizeof(filename), "race/race[%s_r%02d]-w%1ds%1d_%d.%s", mapname, race.active_route, race.weapon, race.falsestart, get_server_port(), extension); } else { snprintf(filename, sizeof(filename), "race/race[%s_r%02d]-w%1ds%1d.%s", mapname, race.active_route, race.weapon, race.falsestart, extension); } return filename; } qbool isRACE(void) { return (cvar("k_race")); } static qbool is_valid_record(raceRecord_t *record) { return (record->time < RACE_INVALID_RECORD_TIME); } static int read_record_param(int param) { char arg_1[64] = { 0 }; if (trap_CmdArgc() <= param) { return 0; } trap_CmdArgv(param, arg_1, sizeof(arg_1)); return bound(0, atoi(arg_1) - 1, NUM_BESTSCORES - 1); } void ToggleRace(void) { if (!isRACE() && bots_enabled()) { G_sprint(self, PRINT_HIGH, "Disable bots first with %s\n", redtext("/botcmd disable")); return; } if (!isRACE() && !is_rules_change_allowed()) { return; } if (!isRACE()) { if (!isFFA()) { UserMode(-6); } } if (CountPlayers() && race_is_started()) { return; } cvar_toggle_msg(self, "k_race", redtext("race")); apply_race_settings(); } void RaceCountdownChange(float t) { float rcd = cvar("k_race_countdown") + t; if (match_in_progress || !isRACE() || race_is_started()) { return; } if ((rcd < 6) && (rcd > 0)) { cvar_fset("k_race_countdown", (int)rcd); G_bprint(2, "%s %s %s\n", redtext("Race countdown length set to"), dig3(rcd), redtext("seconds")); return; } G_sprint(self, 2, "%s still %s\n", redtext("race countdown"), dig3(rcd - t)); } // hard coded default settings for RACE static char race_settings[] = "sv_silentrecord 1\n" "deathmatch 4\n" "srv_practice_mode 1\n" "lock_practice 1\n" "allow_toggle_practice 0\n" "sv_demotxt 0\n" "k_spw 1\n" "k_noitems 1\n" "pm_airstep 0\n" "k_race_pace_jumps 0\n" "k_race_pace_legal 0\n" "k_race_pace_headstart 0.5\n" "k_race_pace_resolution 2\n" "k_race_pace_enabled 0\n" "k_race_simultaneous 1\n" "k_race_scoring_system 0\n" "k_race_match 0\n" "k_race_match_rounds 9\n" "timelimit 0\n" "fraglimit 0\n" "qtv_sayenabled 1\n"; static char norace_settings[] = "sv_silentrecord 0\n" "lock_practice 0\n" "srv_practice_mode 0\n" "allow_toggle_practice 5\n" "qtv_sayenabled 0\n"; void apply_race_settings(void) { char buf[1024 * 4]; char *cfg_name; clearall_usercmds_settings(); if (!isRACE()) { race_stoprecord(true); unmute_all_players(); // turn off race settings. trap_readcmd(norace_settings, buf, sizeof(buf)); G_cprint("%s", buf); // Execute configs/reset.cfg and set k_defmode. execute_rules_reset(); return; } // turn on race settings. UserMode_SetMatchTag(""); trap_readcmd(race_settings, buf, sizeof(buf)); G_cprint("%s", buf); cfg_name = va("configs/usermodes/race/default.cfg"); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } cfg_name = va("configs/usermodes/race/%s.cfg", mapname); if (can_exec(cfg_name)) { trap_readcmd(va("exec %s\n", cfg_name), buf, sizeof(buf)); G_cprint("%s", buf); } G_cprint("\n"); } void race_cleanmap(void) { gedict_t *p; for (p = world; (p = nextent(p));) { if (streq(p->classname, "weapon_nailgun") || streq(p->classname, "weapon_supernailgun") || streq(p->classname, "weapon_supershotgun") || streq(p->classname, "weapon_rocketlauncher") || streq(p->classname, "weapon_grenadelauncher") || streq(p->classname, "weapon_lightning") || streq(p->classname, "item_shells") || streq(p->classname, "item_spikes") || streq(p->classname, "item_rockets") || streq(p->classname, "item_cells") || streq(p->classname, "item_health") || streq(p->classname, "item_armor1") || streq(p->classname, "item_armor2") || streq(p->classname, "item_armorInv") || streq(p->classname, "item_artifact_invulnerability") || streq(p->classname, "item_artifact_envirosuit") || streq(p->classname, "item_artifact_invisibility") || streq(p->classname, "item_artifact_super_damage") || streq(p->classname, "item_armor1") || streq(p->classname, "item_armor2") || streq(p->classname, "item_armorInv")) { ent_remove(p); continue; } if (p->race_flags & RACEFLAG_ENTITY_KEEP) { continue; } if (streq(p->classname, "door")) { ent_remove(p); continue; } } } //=========================================== int race_time(void) { if (race.status != raceActive) { return 0; // count time only when race in state raceActive } return ((g_globalvars.time - race.start_time) * 1000); } void setwepall(gedict_t *p) { gedict_t *swap; p->s.v.ammo_nails = 255; p->s.v.ammo_shells = 255; p->s.v.ammo_rockets = 255; p->s.v.ammo_cells = 255; p->s.v.items = IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING; p->lastwepfired = 0; swap = self; self = p; if (!((int)self->s.v.weapon & (int)self->s.v.items)) { self->s.v.weapon = IT_ROCKET_LAUNCHER; } W_SetCurrentAmmo(); self = swap; } void setwepnone(gedict_t *p) { gedict_t *swap; p->s.v.ammo_nails = 0; p->s.v.ammo_shells = 0; p->s.v.ammo_rockets = 0; p->s.v.ammo_cells = 0; p->s.v.items = 0; p->lastwepfired = 0; swap = self; self = p; self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); self = swap; } char* race_route_name(void) { int idx; if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_route_name: race.cnt %d", race.cnt); } idx = race.active_route - 1; if ((idx < 0) || (idx >= race.cnt)) { return "custom"; } return race.route[idx].name; } char* race_route_desc(void) { int idx; if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_route_desc: race.cnt %d", race.cnt); } idx = race.active_route - 1; if ((idx < 0) || (idx >= race.cnt)) { return "custom"; } return race.route[idx].desc; } //============================================ void race_init(void) { int i; memset(&race, 0, sizeof(race)); race.timeout_setting = RACE_DEFAULT_TIMEOUT; race.warned = true; race.status = raceNone; race.weapon = raceWeaponAllowed; race.falsestart = raceFalseStartNo; for (i = 0; i < NUM_BESTSCORES; i++) { race.records[i].time = RACE_INVALID_RECORD_TIME; } race.rounds = bound(RACE_MIN_MATCH_ROUNDS, cvar(RACE_MATCH_ROUNDS_CVAR), RACE_MAX_MATCH_ROUNDS); } // clean up, so we can start actual match and there will be no some shit around void race_shutdown(char *msg) { race_cancel(true, "%s", msg); race_remove_ent(); race_unready_all(); if (cvar("k_spm_show")) { ShowSpawnPoints(); } race_set_players_movetype_and_etc(); } // make all players not ready for race, silently void race_unready_all(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { p->race_ready = 0; } } //============================================ qbool race_route_add_start(void) { if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { return false; } race.route[race.cnt].weapon = raceWeaponAllowed; // default allowed race.route[race.cnt].timeout = 20; // default 20 sec race.route[race.cnt].falsestart = raceFalseStartNo; // default with falsestart return true; } void race_route_add_end(void) { if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_route_add_end: race.cnt %d", race.cnt); } race.cnt++; } raceRouteNode_t* race_add_route_node(float x, float y, float z, float pitch, float yaw, raceRouteNodeType_t type) { int node_idx; if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_add_route_node: race.cnt %d", race.cnt); } node_idx = race.route[race.cnt].cnt; if ((node_idx < 0) || (node_idx >= MAX_ROUTE_NODES)) { return NULL; // we are full } race.route[race.cnt].node[node_idx].type = type; race.route[race.cnt].node[node_idx].org[0] = x; race.route[race.cnt].node[node_idx].org[1] = y; race.route[race.cnt].node[node_idx].org[2] = z; race.route[race.cnt].node[node_idx].ang[0] = pitch; race.route[race.cnt].node[node_idx].ang[1] = yaw; race.route[race.cnt].node[node_idx].ang[2] = 0; VectorClear(race.route[race.cnt].node[node_idx].sizes); race.route[race.cnt].cnt++; // one more node return &race.route[race.cnt].node[node_idx]; } void race_set_route_name(char *name, char *desc) { if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_set_route_name: race.cnt %d", race.cnt); } strlcpy(race.route[race.cnt].name, name, sizeof(race.route[0].name)); strlcpy(race.route[race.cnt].desc, desc, sizeof(race.route[0].desc)); } void race_set_route_timeout(float timeout) { if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_set_route_timeout: race.cnt %d", race.cnt); } race.route[race.cnt].timeout = bound(1, timeout, 999); } void race_set_route_falsestart_mode(raceFalseStartMode_t falsestart) { switch (falsestart) { case raceFalseStartNo: case raceFalseStartYes: break; // known default: G_Error("race_set_route_falsestart_mode: wrong type %d", falsestart); } race.route[race.cnt].falsestart = falsestart; } void race_set_route_weapon_mode(raceWeapoMode_t weapon) { if ((race.cnt < 0) || (race.cnt >= MAX_ROUTES)) { G_Error("race_set_route_weapon_mode: race.cnt %d", race.cnt); } switch (weapon) { case raceWeaponNo: case raceWeaponAllowed: case raceWeapon2s: break; // known default: G_Error("race_set_route_weapon_mode: wrong weapon %d", weapon); } race.route[race.cnt].weapon = weapon; } gedict_t* race_find_race_participants(gedict_t *p) { p = find_plr(p); while (p && !p->race_participant) { p = find_plr(p); } return p; } gedict_t* race_find_racer(gedict_t *p) { p = find_plr(p); while (p && !p->racer) { p = find_plr(p); } return p; } gedict_t* race_get_racer(void) { return race_find_racer(world); } //=========================================== // remove all entitys with particular classname void ent_remove_by_classname(char *classname) { gedict_t *e; for (e = world; (e = ez_find(e, classname));) { ent_remove(e); } } // remove all possibile race entitys void race_remove_ent(void) { int i; for (i = 1; i < nodeMAX; i++) { ent_remove_by_classname(classname_for_nodeType(i)); } } void race_record(void) { if (race.cd_cnt && cvar("k_race_autorecord")) { if (!race_match_mode()) { StartDemoRecord(); // start demo recording } race.race_recording = true; } } void race_stoprecord(qbool cancel) { if (race.race_recording) { if (cancel) { localcmd("sv_democancel\n"); // stop recording demo and discard it } else { StatsToFile(); localcmd("sv_demostop\n"); // stop recording demo and keep it } race.race_recording = false; } } //============================================ char* race_falsestart_mode(int start) { switch (start) { case raceFalseStartNo: return "no falsestart"; case raceFalseStartYes: return "falsestart enabled"; default: G_Error("race_falsestart_mode: wrong race.falsestart %d", start); } return ""; // keep compiler silent } char* race_weapon_mode(int weapon) { switch (weapon) { case raceWeaponNo: return "disallowed"; case raceWeaponAllowed: return "allowed"; case raceWeapon2s: return "allowed after 2s"; default: G_Error("race_weapon_mode: wrong race.weapon %d", weapon); } return ""; // keep compiler silent } qbool race_weapon_allowed(gedict_t *p) { if (!race.status) { return true; // not a race, so allowed } // below is case of RACE is somehow in progress if (race.status != raceActive) { return false; // allowe weapon in active state only } if (!p->racer) { return false; // not a racer } switch (race.weapon) { case raceWeaponNo: return false; case raceWeaponAllowed: return true; case raceWeapon2s: return ((race_time() >= 2000) ? true : false); default: G_Error("race_weapon_allowed: wrong race.weapon %d", race.weapon); } return false; // keep compiler silent } //============================================ char* name_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return "start checkpoint"; case nodeCheckPoint: return "checkpoint"; case nodeEnd: return "finish checkpoint"; default: G_Error("name_for_nodeType: wrong nodeType %d", nodeType); } return ""; // keep compiler silent } char* classname_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return "race_cp_start"; case nodeCheckPoint: return "race_cp"; case nodeEnd: return "race_cp_end"; default: G_Error("classname_for_nodeType: wrong nodeType %d", nodeType); } return ""; // keep compiler silent } char* model_for_nodeType(raceRouteNodeType_t nodeType) { if (cvar("k_race_custom_models")) { switch (nodeType) { case nodeStart: return "progs/start.mdl"; case nodeCheckPoint: return "progs/check.mdl"; case nodeEnd: return "progs/finish.mdl"; default: G_Error("model_for_nodeType: wrong nodeType %d", nodeType); } } else { switch (nodeType) { case nodeStart: return "progs/invulner.mdl"; case nodeCheckPoint: return "progs/w_s_key.mdl"; case nodeEnd: return "progs/invulner.mdl"; default: G_Error("model_for_nodeType: wrong nodeType %d", nodeType); } } return ""; // keep compiler silent } char* touch_sound_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return "items/protect3.wav"; case nodeCheckPoint: return "items/damage.wav"; case nodeEnd: return "items/suit.wav"; default: G_Error("touch_sound_for_nodeType: wrong nodeType %d", nodeType); } return ""; // keep compiler silent } char* spawn_sound_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return "items/protect.wav"; case nodeCheckPoint: return "items/itembk2.wav"; case nodeEnd: return "items/protect.wav"; default: G_Error("spawn_sound_for_nodeType: wrong nodeType %d", nodeType); } return ""; // keep compiler silent } float volume_for_touch_sound_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return 0.5f; case nodeCheckPoint: return 0.3; case nodeEnd: return 0.5f; default: G_Error("volume_for_touch_sound_for_nodeType: wrong nodeType %d", nodeType); } return 1; // keep compiler silent } float blink_effects_for_nodeType(raceRouteNodeType_t nodeType) { switch (nodeType) { case nodeStart: return ( EF_BLUE | EF_GREEN); case nodeCheckPoint: return EF_BLUE; case nodeEnd: return ( EF_BLUE | EF_GREEN); default: G_Error("volume_for_touch_sound_for_nodeType: wrong nodeType %d", nodeType); } return 0; // keep compiler silent } //============================================ // count start + end + intermediate checkpoints int checkpoints_count(void) { int cnt = 0, i; for (i = 1; i < nodeMAX; i++) { cnt += find_cnt( FOFCLSN, classname_for_nodeType(i)); } return cnt; } //============================================ // count ready for race players int race_count_ready_players(void) { int cnt; gedict_t *p; for (cnt = 0, p = world; (p = find_plr(p));) { if (p->race_ready) { cnt++; } } return cnt; } //=========================================== void race_check_racer_falsestart(qbool nextracer) { gedict_t *e; gedict_t *racer; for (racer = world; (racer = race_find_racer(racer)); /**/) { for (e = world; (e = ez_find(e, "race_cp_start"));) { if ((racer->s.v.origin[0] != e->s.v.origin[0]) && (racer->s.v.origin[1] != e->s.v.origin[1])) { if (nextracer) { G_bprint(PRINT_HIGH, "\20%s\21 false-started\n", racer->netname); if (race_end(racer, false, false)) { return; } } else { G_sprint(racer, 2, "Come back here!\n"); VectorCopy(e->s.v.origin, racer->s.v.origin); VectorSet(racer->s.v.velocity, 0, 0, 0); } } } } } void kill_race_idler(void) { gedict_t *e; gedict_t *racer; for (racer = world; (racer = race_find_racer(racer)); /**/) { // FIXME: Keep track of which start, any map with multiple starts would break for (e = world; (e = ez_find(e, "race_cp_start"));) { vec3_t test_point; VectorAdd(racer->s.v.origin, racer->s.v.view_ofs, test_point); if ((test_point[0] >= e->s.v.absmin[0]) && (test_point[0] <= e->s.v.absmax[0]) && (test_point[1] >= e->s.v.absmin[1]) && (test_point[1] <= e->s.v.absmax[1]) && (test_point[2] >= e->s.v.absmin[2]) && (test_point[2] <= e->s.v.absmax[2])) { racer->race_afk++; if (race_match_mode()) { G_bprint(PRINT_HIGH, "\20%s\21 was %s to start\n", racer->netname, redtext("too slow")); if (race_end(racer, false, false)) { return; } } else if (racer->race_afk < 3) { G_bprint(PRINT_HIGH, "\20%s\21 was %s to start\n", racer->netname, redtext("too slow")); if (race_end(racer, false, false)) { return; } } else { G_bprint(PRINT_HIGH, "%s was %s of line-up for %s\n", racer->netname, redtext("kicked out"), redtext("idling")); racer->race_ready = 0; if (race_end(racer, false, false)) { return; } } } else { racer->race_afk = 0; } } } } void race_brighten_checkpoints(void) { int i; gedict_t *e; gedict_t *racer; int furthest_checkpoint = 0; for (racer = world; (racer = race_find_race_participants(racer)); /**/) { furthest_checkpoint = max(furthest_checkpoint, racer->race_id); } for (i = 1; i < nodeMAX; i++) { char *classname = classname_for_nodeType(i); for (e = world; (e = ez_find(e, classname));) { e->s.v.effects = 0; // remove effects e->s.v.nextthink = 0; // stop thinking if (e->race_id == furthest_checkpoint) { e->s.v.effects = ( EF_GREEN); // set some green light for next checkpoint } else { e->s.v.effects = ( EF_RED); // turn all others red } } } } void race_dim_checkpoints(void) { int i; gedict_t *e; for (i = 1; i < nodeMAX; i++) { char *classname = classname_for_nodeType(i); for (e = world; (e = ez_find(e, classname));) { e->s.v.effects = 0; // remove effects e->s.v.nextthink = 0; // stop thinking } } } void race_blink_think(void) { // remove "cute" effects self->s.v.effects = 0; } void race_blink_node(gedict_t *e) { // set some "cute" effects e->s.v.effects = e->race_effects; // reset it to something normal late e->s.v.nextthink = g_globalvars.time + 5; e->think = (func_t) race_blink_think; } //=========================================== void race_VelocityForDamage(float scale, vec3_t dir, vec3_t v) { if (vlen(dir) > 0) { vec3_t ang; VectorCopy(dir, v); VectorNormalize(v); vectoangles(v, ang); trap_makevectors(ang); // VectorMA( v, crandom() * 0.3, g_globalvars.v_right, v ); VectorMA(g_globalvars.v_forward, crandom() * 0.3, g_globalvars.v_right, v); VectorMA(v, crandom() * 0.3, g_globalvars.v_up, v); VectorNormalize(v); VectorScale(v, scale, v); } else { v[0] = 100 * crandom(); v[1] = 100 * crandom(); v[2] = 20 + 10 * g_random(); VectorNormalize(v); VectorScale(v, scale, v); } return; } void race_meat_touch(void) { // sound( self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM ); // bounce sound if ((self->s.v.velocity[0] == 0) && (self->s.v.velocity[1] == 0) && (self->s.v.velocity[2] == 0)) { VectorClear(self->s.v.avelocity); } } void race_spawn_meat(gedict_t *player, char *gibname, float vel) { gedict_t *newent; newent = spawn(); VectorCopy(player->s.v.origin, newent->s.v.origin); setmodel(newent, gibname); setsize(newent, 0, 0, 0, 0, 0, 0); race_VelocityForDamage(vel, player->s.v.velocity, newent->s.v.velocity); newent->s.v.movetype = MOVETYPE_BOUNCE; newent->isMissile = true; newent->s.v.solid = SOLID_TRIGGER; newent->s.v.avelocity[0] = g_random() * 600; newent->s.v.avelocity[1] = g_random() * 600; newent->s.v.avelocity[2] = g_random() * 600; newent->think = (func_t) SUB_Remove; newent->s.v.nextthink = g_globalvars.time + 6 + g_random() * 10; newent->touch = (func_t) race_meat_touch; } //=========================================== void race_sprint_checkpoint(gedict_t *player, gedict_t *cp) { if (cp->race_RouteNodeType == nodeCheckPoint) { G_sprint(player, 2, "%s \220%d\221\n", redtext(name_for_nodeType(cp->race_RouteNodeType)), cp->race_id); } else { G_sprint(player, 2, "%s\n", redtext(name_for_nodeType(cp->race_RouteNodeType))); } } static void race_end_point_touched(gedict_t *self, gedict_t *other) { int player_num = NUM_FOR_EDICT(other) - 1; float speed, frac; // if (race.currentrace[player_num].time) { return; } // They got to the end other->race_closest_guide_pos = guide.capture.position_count; // spawn a bit of meat speed = max(600, vlen(other->s.v.velocity)); frac = bound(0, 0.8, 1); // non random fraction of the speed race_spawn_meat(other, "progs/gib1.mdl", frac * speed + g_random() * (1.0 - frac) * speed); race_spawn_meat(other, "progs/gib2.mdl", frac * speed + g_random() * (1.0 - frac) * speed); race_spawn_meat(other, "progs/gib3.mdl", frac * speed + g_random() * (1.0 - frac) * speed); race_spawn_meat(other, "progs/h_player.mdl", frac * speed + g_random() * (1.0 - frac) * speed); // If multi-racing, report on position for this race if (race.racers_competing > 1) { char *positionString; if (race.last_completion_time < race_time()) { race.racers_complete += race.last_completion_eq + 1; positionString = race_position_string(race.racers_complete); G_bprint(PRINT_HIGH, "\20%s\21 finished%s%s \20%.3fs\21\n", other->netname, strnull(positionString) ? "" : " in ", positionString, race_time() / 1000.0f); race.last_completion_eq = 0; } else { positionString = race_position_string(race.racers_complete); G_bprint(PRINT_HIGH, "\20%s\21 also finished%s%s \20%.3fs\21\n", other->netname, strnull(positionString) ? "" : " in ", positionString, race_time() / 1000.0f); ++race.last_completion_eq; } if (race.racers_complete == 1) { sound(other, CHAN_ITEM, "boss2/sight.wav", 1, ATTN_NONE); } else { sound(other, CHAN_ITEM, "ambience/thunder1.wav", 1, ATTN_NONE); } } // Add marker for demos/clients { stuffcmd( other, "//ktx race end %f %f %f %f %d\n", race_time() / 1000.0f, race.currentrace[player_num].distance, race.currentrace[player_num].maxspeed, race.currentrace[player_num].avgcount ? race.currentrace[player_num].avgspeed / race.currentrace[player_num].avgcount : 0, race.racers_complete); race.currentrace[player_num].time = race_time(); // stop run timer race.currentrace[player_num].position = race.racers_complete; } race_end(other, true, true); } static void race_over(void) { char demoFileName[MAX_OSPATH]; int i, timeposition, nameposition; int best_time_position = 1000; int best_player_num = -1; char *pos; gedict_t *racer = NULL; qbool keep_demo = false; qbool blocked_record = race_pacemaker_enabled() && !cvar(RACE_PACEMAKER_LEGAL_RECORD); qbool debug = cvar("developer"); strlcpy(demoFileName, cvar_string("serverdemo"), sizeof(demoFileName)); pos = strstr(demoFileName, ".mvd"); if (pos) { *pos = '\0'; } read_topscores(); clearall_usercmds_settings(); if (debug) { G_bprint(PRINT_HIGH, "Race over: %d participants\n", race.racers_competing); } for (racer = world; (racer = race_find_race_participants(racer)); /**/) { int player_num = NUM_FOR_EDICT(racer) - 1; if (debug) { G_bprint(PRINT_HIGH, "Player: %d, %s\n", player_num, racer->netname); } if (!race.currentrace[player_num].time) { // They didn't set a time if (debug) { G_bprint(PRINT_HIGH, "- didn't set a time\n"); } continue; } // first, let's see if run time gets into top scores and if name is already ranked timeposition = nameposition = -1; for (i = 0; i < NUM_BESTSCORES; i++) { if (race.currentrace[player_num].time < race.records[i].time) { if (timeposition == -1) { timeposition = i; } } if (streq(race.records[i].racername, racer->netname)) { nameposition = i; } } if (debug) { G_bprint(PRINT_HIGH, "- time %.3f, position %d, nameposition %d\n", race.currentrace[player_num].time, timeposition, nameposition); } // run time is within top scores range if (timeposition != -1) { // if player didn't beat his own record if ((nameposition < timeposition) && (nameposition != -1)) { if (race.racers_competing == 1) { sound(racer, CHAN_ITEM, "ambience/thunder1.wav", 1, ATTN_NONE); G_bprint(PRINT_HIGH, "Run %s in %s%s\n%s couldn't beat %s best time\n", redtext("finished"), dig3s("%.3f", race.currentrace[player_num].time / 1000), redtext("s"), racer->netname, g_his(racer)); } } else { if (!blocked_record) { // if player beat his own record or is not yet ranked if (nameposition == -1) { nameposition = (NUM_BESTSCORES - 1); } if (is_valid_record(&race.records[nameposition])) { // let's remove the old demo if (!strnull(race.records[nameposition].demoname)) { int demo_references = 0; // one demo might now contain records for more than one player, so // only remove if this record is the last reference for (i = 0; i < sizeof(race.records) / sizeof(race.records[0]); ++i) { if (streq(race.records[nameposition].demoname, race.records[i].demoname)) { ++demo_references; } } if (debug) { G_bprint(PRINT_HIGH, "%s has %d references\n", race.records[nameposition].demoname, demo_references); } if (demo_references == 1) { localcmd("sv_demoremove %s\n", race.records[nameposition].demoname); } } } // move old top scores down for (i = nameposition; i > timeposition; i--) { race.records[i] = race.records[i - 1]; } // add new top score race.records[i].time = race.currentrace[player_num].time; strlcpy(race.records[i].racername, racer->netname, sizeof(race.records[i].racername)); if (race.race_recording) { strlcpy(race.records[i].demoname, demoFileName, sizeof(race.records[i].demoname)); } else { memset(race.records[i].demoname, 0, sizeof(race.records[i].demoname)); } race.records[i].distance = race.currentrace[player_num].distance; race.records[i].maxspeed = race.currentrace[player_num].maxspeed; race.records[i].avgspeed = race.currentrace[player_num].avgspeed / race.currentrace[player_num].avgcount; race.records[i].weaponmode = race.weapon; race.records[i].startmode = race.falsestart; if (!QVMstrftime(race.records[i].date, sizeof(race.records[i].date), "%Y-%m-%d %H:%M:%S", 0)) { race.records[i].date[0] = 0; // bad date } // save scores in file write_topscores(); if (race.racers_competing == 1) { if (!i) { // first place! we go the extra mile sound(racer, CHAN_ITEM, "boss2/sight.wav", 1, ATTN_NONE); } else { sound(racer, CHAN_ITEM, "ambience/thunder1.wav", 1, ATTN_NONE); } } if (!i) { race.top_time = race.currentrace[player_num].time; strlcpy(race.top_nick, racer->netname, sizeof(race.top_nick)); } } if (race.racers_competing == 1) { G_bprint(2, "Run %s in %s%s\n", redtext("finished"), dig3s("%.3f", race.currentrace[player_num].time / 1000), redtext("s")); } G_bprint(PRINT_HIGH, "%s %s %s record\n", racer->netname, blocked_record ? "would have taken" : "took the", race_position_string(timeposition + 1)); if (timeposition <= best_time_position) { best_player_num = player_num; best_time_position = timeposition; } keep_demo |= !blocked_record; } } else { // run time did not make it to top scores if (race.racers_competing == 1) { sound(racer, CHAN_ITEM, "boss2/idle.wav", 1, ATTN_NONE); G_bprint(PRINT_HIGH, "Run %s in %s%s\n", redtext("finished"), dig3s("%.3f", race.currentrace[player_num].time / 1000), redtext("s")); } } } if (race_match_started()) { race_match_round_end(); } else { // Continue match with next run race_finish_capture(best_time_position == 0 && !blocked_record, best_player_num); race_start(!keep_demo, "%s", ""); } } void race_node_touch(void) { if (other->ct != ctPlayer) { return; } // no run in progress nor starting if (!race.status) { if (self->attack_finished >= g_globalvars.time) { return; // still in node touch cooldown } self->attack_finished = g_globalvars.time + 5; // touch cooldown of 5s race_blink_node(self); sound(other, CHAN_ITEM, self->noise, self->race_volume, ATTN_NONE); race_sprint_checkpoint(other, self); // display checkpoint type or order } // run in progress or starting if (race.status != raceActive) { return; // starting run countdown } if (!other->racer) { return; // can't touch if not the racer } if (self->race_id < other->race_id) { return; // node already touched during run } if (self->race_id == other->race_id) { // racer touched checkpoint in right order if (self->race_RouteNodeType == nodeEnd) { race_end_point_touched(self, other); } else if (self->race_RouteNodeType == nodeCheckPoint) { int player_num = NUM_FOR_EDICT(other) - 1; stuffcmd( other, "//ktx race cp %d %f %f %f %f\n", other->race_id, race_time() / 1000.0f, race.currentrace[player_num].distance, race.currentrace[player_num].maxspeed, race.currentrace[player_num].avgcount ? race.currentrace[player_num].avgspeed / race.currentrace[player_num].avgcount : 0); } // if its not start checkpoint do something "cute" if (self->race_id) { // do some sound sound(other, CHAN_ITEM, "knight/sword2.wav", 1, ATTN_NONE); } other->race_id++; // bump our id, so we can touch next checkpoint race_brighten_checkpoints(); // set light on next checkpoint return; } if (self->race_id > other->race_id) { // racer touched checkpoint in WRONG order // do some sound sound(other, CHAN_ITEM, "boss2/idle.wav", 1, ATTN_NONE); if (self->race_RouteNodeType == nodeCheckPoint) { G_bprint(PRINT_HIGH, "\20%s\21: %s \220%d\221 touched in wrong order\n", other->netname, redtext(name_for_nodeType(self->race_RouteNodeType)), self->race_id); } else { G_bprint(PRINT_HIGH, "\20%s\21: \220%s\221 touched in wrong order\n", other->netname, redtext(name_for_nodeType(self->race_RouteNodeType))); } race_end(other, true, false); return; } } //=========================================== // this will fix id for end checkpoint void race_fix_end_checkpoint(void) { // get end checkpoint gedict_t *e = ez_find(world, classname_for_nodeType(nodeEnd)); if (e) { e->race_id = 1 + find_cnt( FOFCLSN, classname_for_nodeType(nodeCheckPoint)); // pretty simple logic } } // spawn/putInGame race route node gedict_t* spawn_race_node(raceRouteNode_t *node) { gedict_t *e; char *classname = classname_for_nodeType(node->type); if (checkpoints_count() >= MAX_ROUTE_NODES) { G_Error("spawn_race_node: can't add more, unexpected"); } // free previos points if any, except intermediate checkpoint if (node->type != nodeCheckPoint) { ent_remove_by_classname(classname); } e = spawn(); switch (node->type) { case nodeCheckPoint: e->race_id = 1 + find_cnt( FOFCLSN, classname); // pretty simple logic break; case nodeStart: case nodeEnd: break; default: G_Error("spawn_race_node: wrong node->type %d", node->type); } setmodel(e, model_for_nodeType(node->type)); if (VectorCompareF(node->sizes, 0, 0, 0)) { setsize(e, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); } else { setsize(e, -node->sizes[0] / 2, -node->sizes[1] / 2, -node->sizes[2] / 2, node->sizes[0] / 2, node->sizes[1] / 2, node->sizes[2] / 2); } e->s.v.solid = SOLID_TRIGGER; e->s.v.movetype = MOVETYPE_NONE; e->s.v.flags = FL_ITEM; e->classname = classname; e->noise = touch_sound_for_nodeType(node->type); e->race_volume = volume_for_touch_sound_for_nodeType(node->type); e->race_effects = blink_effects_for_nodeType(node->type); e->touch = (func_t) race_node_touch; e->attack_finished = g_globalvars.time + 1; // + 1 so it not touched immidiatelly, look race_node_touch() for more info e->race_RouteNodeType = (int)node->type; // ah, cast // play spawn sound sound(e, CHAN_AUTO, spawn_sound_for_nodeType(node->type), 1, ATTN_NONE); VectorCopy(node->ang, e->s.v.v_angle); setorigin(e, PASSVEC3(node->org)); // this will fix id for end checkpoint race_fix_end_checkpoint(); return e; } //============================================ // set some race related fields for all players void race_clear_race_fields(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { p->race_participant = p->racer = false; p->hideplayers = p->hideplayers_default; p->race_id = 0; } for (p = world; (p = find_spc(p));) { p->race_participant = p->racer = false; p->hideplayers = p->hideplayers_default; p->race_id = 0; } } static void race_cancel(qbool cancelrecord, const char *fmt, ...) { va_list argptr; char text[1024]; if (!race_match_started()) { va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); race_stoprecord(cancelrecord); G_cp2all("%s", ""); // clear centerprint if (!strnull(text)) { G_bprint(2, "%s", text); } } race_clear_race_fields(); race.status = raceNone; race.warned = true; // set proper move type for players race_set_players_movetype_and_etc(); } //============================================ // // RACE QUEUE helpers // //============================================ // for internal usage static gedict_t* _race_line(int offset) { int i, idx; int c = max(0, race.next_racer + offset); gedict_t *p = g_edicts + 1; // p - start of players for (i = 0; i < MAX_CLIENTS; i++) { idx = (c + i) % MAX_CLIENTS; if (p[idx].ct == ctPlayer && p[idx].race_ready) { race.next_racer = idx; return &(p[idx]); } } return NULL; } // get someone from race queue line gedict_t* race_get_from_line(void) { return _race_line(0); } // this dude will be next in line, in most cases gedict_t* race_set_next_in_line(void) { return _race_line(1); } void init_scores(void) { int i; for (i = 0; i < NUM_BESTSCORES; i++) { race.records[i].time = RACE_INVALID_RECORD_TIME; race.records[i].racername[0] = '\0'; race.records[i].demoname[0] = '\0'; race.records[i].distance = 0; race.records[i].maxspeed = 0; race.records[i].avgspeed = 0; race.records[i].date[0] = '\0'; race.records[i].weaponmode = race.weapon; race.records[i].startmode = race.falsestart; } } void display_scores(void) { int i; if (!race_command_checks()) { return; } G_sprint( self, 2, "\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\237%s %02d\235\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("top"), NUM_BESTSCORES); G_sprint(self, 2, "pos. time name\n"); for (i = 0; i < NUM_BESTSCORES; i++) { if (!is_valid_record(&race.records[i])) { G_sprint(self, 2, " %02d - -\n", i + 1); } else { if (streq(race.records[i].racername, self->netname)) { G_sprint(self, 2, " %02d \215 %07.3f%s %s\n", i + 1, race.records[i].time / 1000.0, redtext("s"), race.records[i].racername); } else { G_sprint(self, 2, " %02d %07.3f%s %s\n", i + 1, race.records[i].time / 1000.0, redtext("s"), race.records[i].racername); } } } } void race_display_line(void) { int i = 0; gedict_t *p; if (!race_command_checks()) { return; } G_sprint(self, 2, "=== %s ===\n", redtext("Line-up")); for (p = world; (p = find_plr(p));) { if (p->race_ready) { i++; if (p->racer) { G_sprint(self, 2, "%2d \215 %s\n", i, p->netname); } else { G_sprint(self, 2, "%2d %s\n", i, p->netname); } } } if (!i) { G_sprint(self, 2, " (Empty) \n"); } } //============================================ qbool race_can_go(qbool cancel) { gedict_t *racer; // can't go on, noone ready if (!race_count_ready_players()) { if (cancel) { race_cancel(true, "Race in standby, no players in line\n"); race_dim_checkpoints(); } return false; } // can't go on, no start checkpoint if (!ez_find(world, classname_for_nodeType(nodeStart))) { if (cancel) { race_cancel(true, "Race in standby, no %s\n", name_for_nodeType(nodeStart)); } return false; } // can't go on, no end checkpoint if (!ez_find(world, classname_for_nodeType(nodeEnd))) { if (cancel) { race_cancel(true, "Race in standby, no %s\n", name_for_nodeType(nodeEnd)); } return false; } if (race.status) { // Multi-person racing: this is fine, means we can't find even one racer if (!race_get_racer()) { if (cancel) { race_start(true, "Race aborted, racer vanished\n"); } return false; } } if (race.status == raceActive) { int timeouts = 0; int deaths = 0; gedict_t *timeout_plr = NULL; qbool race_ended = false; // Multi-person racing: end individual racer's races if they die for (racer = world; (racer = race_find_racer(racer)); /**/) { if (racer->s.v.health <= 0 && cancel) { // do some sound race_ended |= race_end(racer, true, false); G_bprint(PRINT_HIGH, "\20%s\21 died\n", racer->netname); k_respawn(racer, false); if (race_ended) { break; } } // Timeout everyone still racing if (race.timeout < g_globalvars.time) { if (cancel) { race_ended |= race_end(racer, true, false); timeout_plr = racer; ++timeouts; if (race_ended) { break; } } } } // Reduce number of announcements if (timeouts || deaths) { // do some sound sound(world, CHAN_ITEM, "boss2/idle.wav", 1, ATTN_NONE); if (timeouts == 1 && timeout_plr) { G_bprint(PRINT_HIGH, "\20%s\21 couldn't finish in time\n", timeout_plr->netname); } else if (timeouts > 1) { G_bprint(PRINT_HIGH, "\20%d\21 players couldn't finish in time\n", timeouts); } } // Race officially ends once everyone has stopped return !race_ended; } return true; } // // qbool restart: // true - means continue current competition, just select next racer in line, keep best results. // false - means start completely new race, reset best result and etc. static void race_start(qbool cancelrecord, const char *fmt, ...) { va_list argptr; char text[1024]; extern void ktpro_autotrack_on_race_status_changed(void); gedict_t *r, *n, *s; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); // cancel it first, this will clear something what probably wasn't cleared before race_cancel(cancelrecord, "%s", text); // switch status to coutdown race.status = raceCD; // set countdown timer race.cd_cnt = cvar("k_race_countdown"); race.cd_next_think = g_globalvars.time; if (!race.timeout_setting) { race.timeout_setting = RACE_DEFAULT_TIMEOUT; } s = ez_find(world, classname_for_nodeType(nodeStart)); if (!s) { race_shutdown("race_start: can't find start checkpoint, shutdown race\n"); return; } if (race_simultaneous()) { // Everyone in queue gets to race race.racers_competing = 0; for (r = world; (r = find_plr(r)); /**/) { if ((r->ct == ctPlayer) && r->race_ready) { race_make_active_racer(r, s); ++race.racers_competing; } } } else { race.racers_competing = 0; r = race_get_from_line(); if (r) { race_make_active_racer(r, s); n = race_set_next_in_line(); if (n && (n != r)) { G_sprint(n, 2, "You are %s in line!\n", redtext("next")); } race.racers_competing = 1; } } // set light on next checkpoint race_brighten_checkpoints(); // set proper move type for players race_set_players_movetype_and_etc(); // remove some projectiles remove_projectiles(); // autotrack - force switch pov to racer ktpro_autotrack_on_race_status_changed(); // create pacemaker entity and announce to players race_pacemaker_race_start(); race.last_completion_eq = race.racers_complete = 0; } static void race_make_active_racer(gedict_t *r, gedict_t *s) { int player_num = NUM_FOR_EDICT(r) - 1; // mark him as racer r->racer = r->race_participant = true; r->hideplayers = r->hideplayers_default; ktpro_autotrack_on_powerup_take(r); //G_bprint( 2, "%s is starting his race!\n", r->netname ); // make sure not hooked onto something at previous spot if (r->hook_out) { GrappleReset(r->hook); } r->hook_out = false; r->on_hook = false; // clear velocity SetVector(r->s.v.velocity, 0, 0, 0); // set proper angles VectorCopy(s->s.v.v_angle, r->s.v.angles); VectorCopy(s->s.v.v_angle, r->s.v.v_angle); r->s.v.fixangle = true; // set proper origin setorigin(r, PASSVEC3(s->s.v.origin)); // telefrag anyone at this origin teleport_player(r, r->s.v.origin, r->s.v.angles, TFLAGS_SND_DST); memset(&race.currentrace[player_num], 0, sizeof(race.currentrace[player_num])); } //============================================ // // RACE "THINK" // //============================================ // well, this set some fields on players which help to not block racer void race_set_one_player_movetype_and_etc(gedict_t *p) { if (match_over) { return; } if (race.status && p->race_chasecam && !p->racer) { setwepnone(p); } else { setwepall(p); } switch (race.status) { case raceNone: p->s.v.movetype = MOVETYPE_WALK; if (p->s.v.solid != SOLID_BBOX) { p->s.v.solid = SOLID_BBOX; setorigin(p, PASSVEC3(p->s.v.origin)); } p->muted = false; setmodel(p, "progs/player.mdl"); set_usercmd_trace(p, false); break; case raceCD: if (race.falsestart == raceFalseStartNo) { p->s.v.movetype = (p->racer ? MOVETYPE_NONE : MOVETYPE_WALK); } else { p->s.v.movetype = MOVETYPE_WALK; } if (p->s.v.solid != SOLID_NOT) { p->s.v.solid = SOLID_NOT; setorigin(p, PASSVEC3(p->s.v.origin)); } p->muted = (p->racer ? false : true); setmodel(p, (p->racer ? "progs/player.mdl" : "")); set_usercmd_trace(p, false); break; case raceActive: p->s.v.movetype = MOVETYPE_WALK; if (p->s.v.solid != SOLID_NOT) { p->s.v.solid = SOLID_NOT; setorigin(p, PASSVEC3(p->s.v.origin)); } p->muted = (p->racer ? false : true); setmodel(p, (p->racer ? "progs/player.mdl" : "")); set_usercmd_trace(p, p->racer); break; default: G_Error("race_set_one_player_movetype_and_etc: unknown race.status %d", race.status); } } void unmute_all_players(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { p->muted = false; } } void race_set_players_movetype_and_etc(void) { gedict_t *p; for (p = world; (p = find_plr(p));) { race_set_one_player_movetype_and_etc(p); } } void race_chasecam_freelook_change(void) { if (!race_command_checks()) { return; } self->race_chasecam_freelook = !self->race_chasecam_freelook; switch (self->race_chasecam_freelook) { case 0: G_sprint(self, 2, "Chasecam freelook %s\n", redtext("disabled")); return; case 1: G_sprint(self, 2, "Chasecam freelook %s\n", redtext("enabled")); return; default: return; } } void race_chasecam_change(void) { if (!race_command_checks()) { return; } if (self->racer) { return; } self->race_chasecam_view++; if (self->race_chasecam_view == NUM_CHASECAMS) { self->race_chasecam_view = 0; } switch (self->race_chasecam_view) { case 0: G_sprint(self, 2, "Chasecam is in %s view mode\n", redtext("1st person")); break; case 1: G_sprint(self, 2, "Chasecam is in %s view mode\n", redtext("3rd person")); break; case 2: G_sprint(self, 2, "Chasecam is in %s view mode\n", redtext("hawk eye")); break; case 3: G_sprint(self, 2, "Chasecam is in %s view mode\n", redtext("backpack ride")); break; default: G_sprint(self, 2, "Chasecam position has not beem defined, keep cycling\n"); } } static void race_advance_chasecam_for_plr(gedict_t *plr) { gedict_t *first_racer = race_get_racer(); gedict_t *racer = first_racer; if (!first_racer) { return; } if (plr->race_track && (g_edicts[plr->race_track].ct != ctPlayer)) { plr->race_track = NUM_FOR_EDICT(racer); } if (!plr->race_track) { plr->race_track = NUM_FOR_EDICT(racer); } else { racer = race_find_racer(&g_edicts[plr->race_track]); if (!racer) { racer = first_racer; } plr->race_track = NUM_FOR_EDICT(racer); } } static gedict_t* race_find_chasecam_for_plr(gedict_t *plr, gedict_t *racer) { if (plr->race_track) { int player_num = plr->race_track; if ((player_num >= 1) && (player_num <= MAX_CLIENTS)) { gedict_t *tracked = &g_edicts[player_num]; while (tracked && (tracked->ct == ctPlayer) && !tracked->racer) { tracked = race_find_racer(tracked); } if (tracked) { racer = tracked; } } } plr->race_track = NUM_FOR_EDICT(racer); return racer; } void race_follow(void) { gedict_t *racer = race_get_racer(); vec3_t delta; float vlen; int follow_distance; int upward_distance; if (!racer) { return; // no racer found } if (!self->racer && self->race_chasecam) { racer = race_find_chasecam_for_plr(self, racer); switch (self->race_chasecam_view) { case 1: // 3rd person follow_distance = -120; upward_distance = 50; self->hideentity = 0; VectorCopy(racer->s.v.v_angle, self->s.v.angles); break; case 2: // hawk eye follow_distance = -50; upward_distance = 300; self->hideentity = 0; self->s.v.angles[0] = 90; self->s.v.angles[1] = racer->s.v.angles[1]; break; case 3: // backpack ride follow_distance = -10; upward_distance = 0; self->hideentity = EDICT_TO_PROG(racer); self->s.v.angles[0] = -racer->s.v.angles[0]; self->s.v.angles[1] = 180; break; case 0: // 1st person - ok follow_distance = -10; upward_distance = 0; self->hideentity = EDICT_TO_PROG(racer); // in this mode we want to hide racer model for watcher's view VectorCopy(racer->s.v.v_angle, self->s.v.angles); break; default: return; } if (!self->race_chasecam_freelook) { self->s.v.fixangle = true; // force client v_angle } trap_makevectors(racer->s.v.angles); VectorMA(racer->s.v.origin, follow_distance, g_globalvars.v_forward, self->s.v.origin); VectorMA(self->s.v.origin, upward_distance, g_globalvars.v_up, self->s.v.origin); // avoid positionning in walls traceline(PASSVEC3(racer->s.v.origin), PASSVEC3(self->s.v.origin), false, racer); VectorCopy(g_globalvars.trace_endpos, self->s.v.origin); if (g_globalvars.trace_fraction == 1) { VectorCopy(g_globalvars.trace_endpos, self->s.v.origin); VectorMA(self->s.v.origin, 10, g_globalvars.v_forward, self->s.v.origin); } else { VectorSubtract(g_globalvars.trace_endpos, racer->s.v.origin, delta); vlen = VectorLength(delta); vlen = vlen - 40; VectorNormalize(delta); VectorScale(delta, vlen, delta); VectorAdd(racer->s.v.origin, delta, self->s.v.origin); } //if ( trap_pointcontents( PASSVEC3( self->s.v.origin ) ) == CONTENT_SKY ) // G_bprint( 2, "SKY!\n" ); // smooth playing for ezq / zq self->s.v.movetype = MOVETYPE_LOCK; } if (!self->racer && !self->race_chasecam) { // restore movement and show racer entity self->s.v.movetype = MOVETYPE_WALK; self->hideentity = 0; } else if (self->racer) { self->hideentity = 0; } } void race_think(void) { gedict_t *racer; gedict_t *p, *n = NULL; race_update_pacemaker(); if (match_over) { race.status = raceNone; return; } switch (race.status) { case raceNone: // can't start if (!race_can_go(!race.warned)) { return; } // advance race status to countdown race_start(true, "%s", ""); return; case raceCD: // something wrong if (!race_can_go(true)) { return; } if (!race.race_recording) { race_record(); } // countdown in progress if (race.cd_next_think >= g_globalvars.time) { return; } racer = race_get_racer(); // must not never happens because we have race_can_go() above if (!racer) { race_start(true, "Run aborted, racer vanished\n"); return; } // countdown still in progress if (race.cd_cnt > 0) { if (race.cd_next_think < g_globalvars.time) { char cp_buf[1024] = { 0 }, tmp[512] = { 0 }; gedict_t *racer = race_get_racer(); // ok, time for next "tick" in coutdown if (race_find_racer(racer)) { snprintf(cp_buf, sizeof(cp_buf), "Racing in: %s\n", dig3(race.cd_cnt)); } else { snprintf(cp_buf, sizeof(cp_buf), "%s racing in: %s\n", racer->netname, dig3(race.cd_cnt)); } snprintf(tmp, sizeof(tmp), "weapon: %s\n\n", redtext(race_weapon_mode(race.weapon))); strlcat(cp_buf, tmp, sizeof(cp_buf)); if (race_match_mode()) { strlcat(cp_buf, "round: ", sizeof(cp_buf)); if (race.round_number >= race.rounds) { strlcat(cp_buf, redtext("final\n"), sizeof(cp_buf)); } else { snprintf(tmp, sizeof(tmp), "%d/%d\n", race.round_number + 1, race.rounds); strlcat(cp_buf, tmp, sizeof(cp_buf)); } } else { if (!strnull(race.top_nick)) { snprintf(tmp, sizeof(tmp), "best run: %s%s (by %s)", dig3s("%.3f", race.top_time / 1000.0), redtext("s"), race.top_nick); strlcat(cp_buf, tmp, sizeof(cp_buf)); } if (!strnull(race.pacemaker_nick)) { snprintf(tmp, sizeof(tmp), "\npacemaker: %s%s (by %s)", dig3s("%.3f", race.pacemaker_time / 1000.0), redtext("s"), race.pacemaker_nick); strlcat(cp_buf, tmp, sizeof(cp_buf)); } } G_cp2all("%s", cp_buf); // check for falsestarts race_check_racer_falsestart(false); // FIXME: yeah, nice make some utility for that for (p = world; (p = find_client(p));) { stuffcmd(p, "play buttons/switch04.wav\n"); } race.cd_next_think = g_globalvars.time + 1; // set next think one second later race.cd_cnt--; } return; } G_cp2all("GO!"); // FIXME: yeah, nice make some utility for that for (p = world; (p = find_client(p));) { //stuffcmd (p, "play enforcer/enfire.wav\n"); stuffcmd(p, "play weapons/pkup.wav\n"); // I like this one better -- deurk. } race.status = raceActive; // countdown ends, now we ready for race memset(race.currentrace, 0, sizeof(race.currentrace)); // initiate distance race_init_capture(); // check for falsestarts race_check_racer_falsestart(true); race.start_time = g_globalvars.time; race.timeout = g_globalvars.time + max(1, race.timeout_setting); race.next_race_time = 500; // do not print race time for first 500 ms, so we can see "Go!" // set proper move type for players race_set_players_movetype_and_etc(); { char date[64]; if (!QVMstrftime(date, sizeof(date), "%Y%m%d%H%M%S", 0)) date[0] = '\0'; for (racer = world; (racer = race_find_racer(racer)); /**/) { stuffcmd(racer, "//ktx race start %d %d %s\n", race.weapon, race.falsestart, date); } } return; case raceActive: // anti-idling if ((race_time() > (race.start_time + 3000)) && (race_time() < (race.start_time + 4000))) { kill_race_idler(); } // something wrong if (!race_can_go(true)) { return; } race_save_position(); if (race_time() >= race.next_race_time) { vec3_t tmp; race.next_race_time = race_time() + 100; // update race time each 100 ms for (racer = world; (racer = race_find_racer(racer)); /**/) { int player_num = NUM_FOR_EDICT(racer) - 1; raceRecord_t *raceStats = &race.currentrace[player_num]; float current_velocity = vlen(racer->s.v.velocity); VectorSubtract(racer->s.v.origin, racer->s.v.oldorigin, tmp); raceStats->distance += vlen(tmp); raceStats->maxspeed = max(raceStats->maxspeed, current_velocity); raceStats->avgspeed += current_velocity; raceStats->avgcount++; } race_update_closest_positions(); if (race.racers_competing == 1) { racer = race_get_racer(); n = race_get_from_line(); for (p = world; (p = find_client(p));) { if (p->racer) { G_centerprint(p, "%s", dig3s("time: %.1f", race_time() / 1000.0)); } else { G_centerprint(p, "following %s\n%s\nspeed: %4.1f\ntime: %s", racer->netname, (n == p) ? redtext("== you're next in line-up ==") : "", race_vlen(racer->s.v.velocity), dig3s("%3.1f", race_time() / 1000.0)); } } } else { for (p = world; (p = find_client(p)); /**/) { if (p->racer) { G_centerprint(p, "%s", dig3s("time: %.1f", race_time() / 1000.0)); } else { int player_num = NUM_FOR_EDICT(p) - 1; qbool time_set = p->ct == ctPlayer && p->race_participant && race.currentrace[player_num].time; char *tracking_text = ""; char *tracking_speed = ""; if (p->race_chasecam && (p->race_track >= 1) && (p->race_track <= MAX_CLIENTS)) { gedict_t *chasing = &g_edicts[p->race_track]; if ((chasing->ct == ctPlayer) && chasing->racer) { tracking_text = va("following %s\n", chasing->netname); tracking_speed = va("speed: %4.1f\n", race_vlen(chasing->s.v.velocity)); } } if (time_set) { G_centerprint(p, "%s%s %.3f %s\n%stime: %s", tracking_text, redtext("== Race over: "), race.currentrace[player_num].time / 1000.0, redtext("=="), tracking_speed, dig3s("%3.1f", race_time() / 1000.0)); } else if ((p->ct == ctPlayer) && p->race_participant) { G_centerprint(p, "%s%s\n%stime: %s", tracking_text, redtext("== Race over: please wait =="), tracking_speed, dig3s("%3.1f", race_time() / 1000.0)); } else { G_centerprint(p, "%s%s\n%stime: %s", tracking_text, redtext("== Race in progress =="), tracking_speed, dig3s("%3.1f", race_time() / 1000.0)); } } } } } return; default: G_Error("race_think: unknown race.status %d", race.status); } } //============================================ // // race commands // //============================================ static void race_route_now_custom(void) { init_scores(); race.active_route = 0; // mark this is a custom route now race_clear_pacemaker(); cvar_fset(RACE_ROUTE_NUMBER_CVAR, -1); cvar_set(RACE_ROUTE_MAPNAME_CVAR, ""); } void r_Xset(float t) { gedict_t *e; raceRouteNode_t node; if (!race_command_checks()) { return; } if (race_is_started()) { return; } if (checkpoints_count() >= MAX_ROUTE_NODES) { G_sprint(self, 2, "Can't add more checkpoints!\n"); return; } // zeroing all fields memset(&node, 0, sizeof(node)); node.type = (raceRouteNodeType_t) t; // magic cast VectorCopy(self->s.v.v_angle, node.ang); VectorCopy(self->s.v.origin, node.org); e = spawn_race_node(&node); if (node.type == nodeCheckPoint) { G_bprint(2, "%s \220%d\221 set\n", redtext(name_for_nodeType(node.type)), e->race_id); G_bprint(2, "Coordinates: %6.1f %6.1f %6.1f\n", e->s.v.origin[0], e->s.v.origin[1], e->s.v.origin[2]); } else if (node.type == nodeStart) { G_bprint(2, "%s set\n", redtext(name_for_nodeType(node.type))); G_bprint(2, "Coordinates: %6.1f %6.1f %6.1f\n", e->s.v.origin[0], e->s.v.origin[1], e->s.v.origin[2]); G_bprint(2, "Direction: %6.1f %6.1f\n", e->s.v.v_angle[0], e->s.v.v_angle[1]); } else { G_bprint(2, "%s set\n", redtext(name_for_nodeType(node.type))); G_bprint(2, "Coordinates: %6.1f %6.1f %6.1f\n", e->s.v.origin[0], e->s.v.origin[1], e->s.v.origin[2]); } race_route_now_custom(); // mark this is a custom route now } void r_cdel(void) { gedict_t *e; int cnt, id; char *classname = classname_for_nodeType(nodeCheckPoint); if (!race_command_checks()) { return; } if (race_is_started()) { return; } cnt = find_cnt( FOFCLSN, classname); if (!cnt) { G_sprint(self, 2, "Can't find any %s\n", redtext(name_for_nodeType(nodeCheckPoint))); return; } // get highest id id = 0; for (e = world; (e = ez_find(e, classname));) { id = max(id, e->race_id); } // and now remove it for (e = world; (e = ez_find(e, classname));) { if (id == e->race_id) { ent_remove(e); break; } } // this will fix id for end checkpoint race_fix_end_checkpoint(); G_bprint(2, "%s \220%d\221 removed\n", redtext(name_for_nodeType(nodeCheckPoint)), id); race_route_now_custom(); // mark this is a custom route now } void set_player_race_follow(gedict_t *e, int follow) { if (follow) { if (e->race_chasecam) { return; } G_sprint(self, 2, "Your %s is now %s\n", redtext("chasecam"), redtext("enabled")); e->race_chasecam = 1; if (!e->racer) { setwepnone(e); } } else { if (!e->race_chasecam) { return; } G_sprint(self, 2, "Your %s is now %s\n", redtext("chasecam"), redtext("disabled")); e->race_chasecam = 0; setwepall(e); SetVector(e->s.v.velocity, 0, 0, 0); } } void set_player_race_ready(gedict_t *e, int ready) { if (ready) { if (e->race_ready) { return; } G_bprint(2, "%s %s the line-up\n", e->netname, redtext("joined")); e->race_ready = 1; e->race_afk = 0; race.warned = false; // so we get warning why race can't be started } else { if (!e->race_ready) { return; } G_bprint(2, "%s %s the line-up\n", e->netname, redtext("left")); e->race_ready = 0; } } qbool race_command_checks(void) { if (!isRACE()) { G_sprint(self, 2, "Command only available in %s mode (type /%s to activate it)\n", redtext("race"), redtext("race")); return false; } return true; } qbool race_is_started(void) { if (race.status) { G_sprint( self, 2, "Can't use that command while %s is in progress, wait for all players to leave the line-up\n", redtext("race")); return true; } return false; } void r_changefollowstatus(float t) { if (!race_command_checks()) { return; } if (self->racer) { return; } switch ((int)t) { case 1: // rfollow set_player_race_follow(self, 1); return; case 2: // rnofollow set_player_race_follow(self, 0); return; case 3: // rftoggle set_player_race_follow(self, !self->race_chasecam); return; default: return; } } void r_changestatus(float t) { qbool match_enabled = race_match_mode(); if (!race_command_checks()) { return; } if (self->ct == ctSpec) { return; } switch ((int)t) { case 1: // race_ready if (match_enabled && race.status) { G_sprint(self, PRINT_HIGH, "Cannot join match in progress\n"); return; } set_player_race_ready(self, 1); return; case 2: // race_break if (self->racer && race.status) { G_bprint(PRINT_HIGH, "%s has quit the race\n", self->netname); race_end(self, true, false); } set_player_race_ready(self, 0); return; case 3: // race_toggle if (self->racer && race.status) { G_bprint(PRINT_HIGH, "%s has quit the race\n", self->netname); race_end(self, true, false); } set_player_race_ready(self, !self->race_ready); return; case 4: // race_cancel if (!self->racer) { return; } if (!race.status) { return; } // do some sound sound(self, CHAN_ITEM, "boss2/idle.wav", 1, ATTN_NONE); G_bprint(PRINT_HIGH, "%s aborted %s run\n", self->netname, g_his(self)); race_end(self, true, false); return; default: return; } } void r_timeout(void) { char arg_1[64]; if (!race_command_checks()) { return; } if (race_is_started()) { return; } trap_CmdArgv(1, arg_1, sizeof(arg_1)); race.timeout_setting = atoi(arg_1); if (!race.timeout_setting) { race.timeout_setting = RACE_DEFAULT_TIMEOUT; } race.timeout_setting = bound(1, race.timeout_setting, RACE_MAX_TIMEOUT); G_bprint(2, "%s set race time limit to %ss\n", self->netname, dig3(race.timeout_setting)); } void race_download_record_demo(void) { int record = read_record_param(1); if (!race_command_checks()) { return; } if (!is_valid_record(&race.records[record])) { G_sprint(self, 2, "record not found\n"); return; } if (strnull(race.records[record].demoname)) { G_sprint(self, 2, "demo for record #%d is not available\n", record + 1); return; } stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "download \"demos/%s.mvd\"\n", race.records[record].demoname); } void display_record_details(void) { int record = read_record_param(1); if (!race_command_checks()) { return; } if (!is_valid_record(&race.records[record])) { G_sprint(self, 2, "record not found\n"); return; } G_sprint( self, 2, "\n\235\236\236\236\236\236\236\236\236\236\236\236\236\237%s %s\235\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("record"), dig3s("%02d", record + 1)); G_sprint(self, 2, "time: %s\n", dig3s("%7.3f%s", race.records[record].time / 1000, redtext("s"))); G_sprint(self, 2, "racer: %s\n", race.records[record].racername); G_sprint(self, 2, "demo: %s\n", redtext(race.records[record].demoname)); G_sprint(self, 2, "distance: %s\n", dig3s("%.1f", race.records[record].distance)); G_sprint(self, 2, "max speed: %s\n", dig3s("%.0f", race.records[record].maxspeed)); G_sprint(self, 2, "avg speed: %s\n", dig3s("%.0f", race.records[record].avgspeed)); G_sprint(self, 2, "date: %s\n", redtext(race.records[record].date)); G_sprint(self, 2, "weapon: %s\n", redtext(race_weapon_mode(race.records[record].weaponmode))); G_sprint(self, 2, "falsestart: %s\n", redtext(race_falsestart_mode(race.records[record].startmode))); } void r_falsestart(void) { if (!race_command_checks()) { return; } if (race_is_started()) { return; } race.falsestart++; if ((race.falsestart < raceFalseStartNo) || (race.falsestart >= raceFalseStartMAX)) { race.falsestart = raceFalseStartNo; } G_bprint(2, "%s set race start mode to %s\n", self->netname, redtext(race_falsestart_mode(race.falsestart))); read_topscores(); race_clear_pacemaker(); } void r_all_break(void) { if (!race_command_checks()) { return; } race_unready_all(); G_bprint(2, "%s has %s the race to stop\n", self->netname, redtext("forced")); } void r_clear_route(void) { gedict_t *p; if (!race_command_checks()) { return; } if (race_is_started()) { return; } for (p = world; (p = find_plr(p));) { setwepall(p); p->muted = 0; } race_remove_ent(); G_bprint(2, "%s cleared the current route\n", self->netname); race_clear_pacemaker(); } void r_mode(void) { if (!race_command_checks()) { return; } if (race_is_started()) { return; } race.weapon++; if ((race.weapon < raceWeaponNo) || (race.weapon >= raceWeaponMAX)) { race.weapon = raceWeaponNo; } G_bprint(2, "%s set race weapon mode to %s\n", self->netname, redtext(race_weapon_mode(race.weapon))); read_topscores(); race_clear_pacemaker(); race_route_now_custom(); } qbool race_load_route(int route) { int i; if ((route < 0) || (route >= race.cnt) || (route >= MAX_ROUTES)) { return false; } // remove all checkpoints before load race_remove_ent(); for (i = 0; i < race.route[route].cnt && i < MAX_ROUTE_NODES; i++) { spawn_race_node(&race.route[route].node[i]); } race.weapon = race.route[route].weapon; race.timeout_setting = bound(1, race.route[route].timeout, RACE_MAX_TIMEOUT); race.active_route = route + 1; // mark this is not custom route now read_topscores(); if (!strnull(cvar_string("sv_www_address"))) { localcmd("\nsv_web_postfile ServerApi/UploadTopFile \"\" %s\n", race_filename("top")); trap_executecmd(); } return true; } void race_print_route_info(gedict_t *p) { if (p) { G_sprint(p, 2, "\235\236\236\236\236\237 %s \235\236\236\236\236\237\n", race_route_name()); G_sprint(p, 2, "%s %2d \220tl: %ssec\221\n", redtext("route"), race.active_route, dig3(race.timeout_setting)); if (race.active_route) { G_sprint(p, 2, "\220%s\221\n", race_route_desc()); } G_sprint(p, 2, "%s: %s\n", redtext("weapon"), race_weapon_mode(race.weapon)); } else { G_bprint(2, "\235\236\236\236\236\237 %s \235\236\236\236\236\237\n", race_route_name()); G_bprint(2, "%s %2d \220tl: %ssec\221\n", redtext("route"), race.active_route, dig3(race.timeout_setting)); if (race.active_route) { G_bprint(2, "\220%s\221\n", race_route_desc()); } G_bprint(2, "%s: %s\n", redtext("weapon"), race_weapon_mode(race.weapon)); } } void r_route(void) { if (!race_command_checks()) { return; } if (race_is_started()) { return; } HideSpawnPoints(); race_cleanmap(); if (race.cnt < 1) { G_sprint(self, 2, "No routes defined for this map\n"); return; } // If server-side toggle and map matches, load correct route if ((self->ct != ctPlayer) && streq(cvar_string(RACE_ROUTE_MAPNAME_CVAR), mapname)) { next_route = cvar(RACE_ROUTE_NUMBER_CVAR); } else { next_route++; } if ((next_route < 0) || (next_route >= race.cnt)) { next_route = 0; } if (!race_load_route(next_route)) { // we failed to load, clean it a bit then race_remove_ent(); race_route_now_custom(); if (self->ct == ctPlayer) { G_bprint(2, "Failed to load route %d by %s\n", next_route + 1, self->netname); } else { G_bprint(2, "Server failed to load route %d\n", next_route + 1); } return; } if (self->ct == ctPlayer) { race_print_route_info( NULL); G_bprint(2, "route loaded by %s\n", self->netname); } else { race_print_route_info( NULL); G_bprint(2, "Server loaded route %d\n", next_route); } cvar_fset(RACE_ROUTE_NUMBER_CVAR, next_route); cvar_set(RACE_ROUTE_MAPNAME_CVAR, mapname); race_clear_pacemaker(); } void r_print(void) { if (!race_command_checks()) { return; } race_print_route_info(self); } void race_fclose(void) { if (race_fhandle < 0) { return; } trap_FS_CloseFile(race_fhandle); race_fhandle = -1; } static void race_fwopen(const char *fmt, ...) { va_list argptr; char text[MAX_TXTLEN] = { 0 }; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; if (trap_FS_OpenFile(text, &race_fhandle, FS_WRITE_BIN) < 0) { race_fhandle = -1; //G_bprint( 2, "Failed to open file: %s\n", text ); return; } //G_bprint( 2, "Succesfully opened file: %s\n", text ); } static void race_fropen(const char *fmt, ...) { va_list argptr; char text[MAX_TXTLEN] = { 0 }; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; if (trap_FS_OpenFile(text, &race_fhandle, FS_READ_BIN) < 0) { race_fhandle = -1; //G_bprint( 2, "Failed to open file: %s\n", text ); return; } //G_bprint( 2, "Succesfully opened file: %s\n", text ); } static void race_fprintf(const char *fmt, ...) { va_list argptr; char text[MAX_TXTLEN] = { 0 }; if (race_fhandle < 0) { return; } va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_FS_WriteFile(text, strlen(text), race_fhandle); } void write_topscores(void) { int i; if (!race.active_route) { return; } race_fwopen("%s", race_filename("top")); if (race_fhandle < 0) { return; } race_fprintf("version %d\n", TOP_FILE_VERSION); race_fprintf("%d\n", NUM_BESTSCORES); for (i = 0; i < NUM_BESTSCORES; i++) { race_fprintf("%f\n", race.records[i].time); race_fprintf("%s\n", race.records[i].racername); race_fprintf("%s\n", race.records[i].demoname); race_fprintf("%f\n", race.records[i].distance); race_fprintf("%f\n", race.records[i].maxspeed); race_fprintf("%f\n", race.records[i].avgspeed); race_fprintf("%s\n", race.records[i].date); race_fprintf("%d\n", race.records[i].weaponmode); race_fprintf("%d\n", race.records[i].startmode); race_fprintf("%d\n", race.records[i].playernumber); } race_fclose(); } int race_fgetc(void) { char c; int retval; if (race_fhandle < 0) { return -2; } retval = trap_FS_ReadFile(&c, 1, race_fhandle); //G_bprint( 2, "====> Read char: %d\n", c ); return ((retval == 1) ? c : -1); } char* race_fgets(char *buf, int limit) { int c = '\0'; char *string; if (race_fhandle < 0) { return NULL; } string = buf; while (--limit > 0 && ((c = race_fgetc()) != -1)) { if ((*string++ = c) == '\n') { break; } } *string = '\0'; //G_bprint( 2, "====> Read string: %s\n", buf ); return ((c == -1) && (string = buf)) ? NULL : buf; } void read_topscores(void) { char line[MAX_TXTLEN] = { 0 }; int cnt, max; int format_version = 1; if (!race.active_route) { return; } race_fropen("%s", race_filename("top")); if (race_fhandle >= 0) { race_fgets(line, MAX_TXTLEN); if (!strncmp(line, "version ", sizeof("version ") - 1)) { format_version = atoi(line + sizeof("version ") - 1); race_fgets(line, MAX_TXTLEN); } max = atoi(line); for (cnt = 0; cnt < max; cnt++) { race_fgets(line, MAX_TXTLEN); race.records[cnt].time = atof(line); race_fgets(line, MAX_TXTLEN); strlcpy(race.records[cnt].racername, line, sizeof(race.records[cnt].racername)); race_fgets(line, MAX_TXTLEN); strlcpy(race.records[cnt].demoname, line, sizeof(race.records[cnt].demoname)); race_fgets(line, MAX_TXTLEN); race.records[cnt].distance = atof(line); race_fgets(line, MAX_TXTLEN); race.records[cnt].maxspeed = atof(line); race_fgets(line, MAX_TXTLEN); race.records[cnt].avgspeed = atof(line); race_fgets(line, MAX_TXTLEN); strlcpy(race.records[cnt].date, line, sizeof(race.records[cnt].date)); race_fgets(line, MAX_TXTLEN); race.records[cnt].weaponmode = atoi(line); race_fgets(line, MAX_TXTLEN); race.records[cnt].startmode = atoi(line); if (format_version >= 2) { race_fgets(line, MAX_TXTLEN); race.records[cnt].playernumber = atoi(line); } else { race.records[cnt].playernumber = -1; } } race.top_time = race.records[0].time; strlcpy(race.top_nick, race.records[0].racername, sizeof(race.top_nick)); } else { init_scores(); race.top_nick[0] = 0; race.top_time = RACE_INVALID_RECORD_TIME; } race_fclose(); } void ChasecamToggleButton(void) { if (!(((int)(self->s.v.flags)) & FL_ATTACKRELEASED)) { return; } self->s.v.flags = (int)self->s.v.flags & ~FL_ATTACKRELEASED; r_changefollowstatus((float) 3); } void race_set_teleport_flags_by_name(const char *name, int flags) { gedict_t *ent; for (ent = world; (ent = ez_find(ent, "trigger_teleport"));) { if (streq(ent->target, name)) { ent->race_flags = flags; } } } void race_route_create(void) { gedict_t *route[MAX_ROUTE_NODES] = { 0 }; gedict_t *current = self; int route_nodes = 0; int i = 0; // If race mode not enabled, just ignore quietly if (!isRACE()) { return; } // Name & description are mandatory, ignore route if not specified if (strnull(self->race_route_name) || strnull(self->race_route_description)) { G_bprint(2, "Route name/description not specified\n"); return; } // weapon-mode must be valid if ((self->race_route_weapon_mode <= raceWeaponUnknown) || (self->race_route_weapon_mode >= raceWeaponMAX)) { G_bprint(2, "Route weapon mode not valid\n"); return; } // false-start-mode must be valid if ((self->race_route_falsestart_mode <= raceFalseStartUnknown) || (self->race_route_falsestart_mode >= raceFalseStartMAX)) { G_bprint(2, "Route falsestart mode not valid\n"); return; } while (current && current != world) { // flag current entity to be removed next frame if (streq(current->classname, "race_route_marker") || streq(current->classname, "race_route_start")) { SUB_RM_01(current); } // route is too long, ignore if (route_nodes >= (sizeof(route) / sizeof(route[0]))) { G_bprint(2, "Route too long\n"); return; } // route is circular? ignore for (i = 0; i < route_nodes; ++i) { if (route[i] == current) { G_bprint(2, "Circular route detected\n"); return; } } // add to route route[route_nodes++] = current; // no targetname => end if ((current->race_flags & RACEFLAG_TOUCH_RACEEND) || strnull(current->target)) { break; } // move to next target current = find(world, FOFS(targetname), current->target); // next target must be route marker, or end the race if (current && !((current->race_flags & RACEFLAG_TOUCH_RACEEND) || streq(current->classname, "race_route_marker"))) { G_bprint(2, "Expected route marker, found %s instead\n", current->classname); return; } } // must have at least start and end if (route_nodes < 2) { G_bprint(2, "Route too short (%d nodes)\n", route_nodes); return; } // Create route if (!race_route_add_start()) { G_bprint(2, "Couldn't create new route\n"); return; } // Add path for (i = 0; i < route_nodes; ++i) { raceRouteNodeType_t nodeType = nodeCheckPoint; raceRouteNode_t *node = NULL; if (i == 0) { nodeType = nodeStart; } else if (i == (route_nodes - 1)) { nodeType = nodeEnd; } node = race_add_route_node(route[i]->s.v.origin[0], route[i]->s.v.origin[1], route[i]->s.v.origin[2], route[i]->race_route_start_pitch, route[i]->race_route_start_yaw, nodeType); if (node) { VectorCopy(route[i]->s.v.size, node->sizes); } } race_set_route_name(self->race_route_name, self->race_route_description); race_set_route_timeout(self->race_route_timeout); race_set_route_weapon_mode((raceWeapoMode_t) self->race_route_weapon_mode); race_set_route_falsestart_mode((raceFalseStartMode_t) self->race_route_falsestart_mode); race_route_add_end(); if (next_route < 0) { r_route(); } } void SP_race_route_start(void) { self->s.v.nextthink = g_globalvars.time + 0.001f;// create route once all markers have spawned self->think = (func_t) race_route_create; } void race_spawn_intermission(float x, float y, float z, float ang_x, float ang_y, float ang_z) { gedict_t *intermission = spawn(); gedict_t *oldself = self; if (!intermission) { return; } intermission->classname = "info_intermission"; VectorSet(intermission->s.v.origin, x, y, z); VectorSet(intermission->mangle, ang_x, ang_y, ang_z); self = intermission; SP_info_intermission(); self = oldself; } void race_add_standard_routes(void) { char line[MAX_TXTLEN]; char token[MAX_TXTLEN]; qbool in_route_def = false; int lineNumber = 0; size_t i = 0; char *entityfile; qbool valid_file = true; entityfile = cvar_string("k_entityfile"); if (!strnull(entityfile)) { race_fropen("race/routes/%s.route", entityfile); } else { race_fropen("race/routes/%s.route", mapname); } if (race_fhandle >= 0) { while (race_fgets(line, MAX_TXTLEN)) { int args; ++lineNumber; trap_CmdTokenize(line); args = trap_CmdArgc(); if (!args) { continue; } trap_CmdArgv(0, token, MAX_TXTLEN); if (!strcmp(token, "race_route_add_start")) { if (in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_route_add_start in route definition\n", lineNumber); valid_file = false; break; } if (!(in_route_def = race_route_add_start())) { // Silently return, as previous G_bprint(PRINT_HIGH, "#%02d: Routes ignored, limit is %d routes/map\n", lineNumber, MAX_ROUTES); break; } } else if (!strcmp(token, "race_add_route_node")) { vec3_t position; vec3_t angles; if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_add_route_node outside of route definition\n", lineNumber); valid_file = false; break; } if (args != 6) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_add_route_node should have 5 arguments, found %d\n", lineNumber, args - 1); valid_file = false; break; } for (i = 1; i < 6; ++i) { trap_CmdArgv(i, token, MAX_TXTLEN); if (i <= 3) { position[i - 1] = atof(token); } else { angles[i - 4] = atof(token); } } if (race.route[race.cnt].cnt == 0) { race_add_route_node(PASSVEC3(position), angles[0], angles[1], nodeStart); } else { if (race.route[race.cnt].cnt > 1) { race.route[race.cnt].node[race.route[race.cnt].cnt - 1].type = nodeCheckPoint; } race_add_route_node(PASSVEC3(position), angles[0], angles[1], nodeEnd); } } else if (!strcmp(token, "race_set_route_name")) { char route_name[128]; char route_description[128]; int j; if (args != 3) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_name should have 2 arguments, found %d\n", lineNumber, args - 1); valid_file = false; break; } if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_name outside of route definition\n", lineNumber); valid_file = false; break; } trap_CmdArgv(1, token, MAX_TXTLEN); strlcpy(route_name, token, sizeof(route_name)); trap_CmdArgv(2, token, MAX_TXTLEN); for (i = 0, j = 0; i < strlen(token); ++i) { if (token[i] == '\\' && token[i + 1] == '\\') { token[j++] = '\\'; ++i; } else if (token[i] == '\\'&& isdigit(token[i + 1]) && isdigit(token[i + 2]) && isdigit(token[i + 3])) { token[j++] = 16 * (token[i + 1] - '0') + 8 * (token[i + 2] - '0') + (token[i + 3] - '0'); i += 3; } else { token[j++] = token[i]; } } token[j] = '\0'; strlcpy(route_description, token, sizeof(route_description)); race_set_route_name(route_name, route_description); } else if (!strcmp(token, "race_set_route_timeout")) { if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_timeout outside of route definition\n", lineNumber); valid_file = false; break; } if (args != 2) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_timeout: expected 1 argument, found %d\n", lineNumber, args); valid_file = false; break; } trap_CmdArgv(1, token, MAX_TXTLEN); if (atof(token) > 0) { race_set_route_timeout(atof(token)); } } else if (!strcmp(token, "race_set_route_weapon_mode")) { if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_weapon_mode outside of route definition\n", lineNumber); valid_file = false; break; } if (args != 2) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_weapon_mode: expected 1 argument, found %d\n", lineNumber, args); valid_file = false; break; } trap_CmdArgv(1, token, MAX_TXTLEN); if (!strcmp(token, "raceWeaponNo")) { race_set_route_weapon_mode(raceWeaponNo); } else if (!strcmp(token, "raceWeaponAllowed")) { race_set_route_weapon_mode(raceWeaponAllowed); } else if (!strcmp(token, "raceWeapon2s")) { race_set_route_weapon_mode(raceWeapon2s); } else { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_weapon_mode: invalid argument %s\n", lineNumber, token); valid_file = false; break; } } else if (!strcmp(token, "race_set_route_falsestart_mode")) { if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_falsestart_mode outside of route definition\n", lineNumber); valid_file = false; break; } if (args != 2) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_falsestart_mode: expected 1 argument, found %d\n", lineNumber, args); valid_file = false; break; } trap_CmdArgv(1, token, MAX_TXTLEN); if (!strcmp(token, "raceFalseStartNo")) { race_set_route_falsestart_mode(raceFalseStartNo); } else if (!strcmp(token, "raceFalseStartYes")) { race_set_route_falsestart_mode(raceFalseStartYes); } else { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_route_falsestart_mode: invalid argument %s\n", lineNumber, token); valid_file = false; break; } } else if (!strcmp(token, "race_route_add_end")) { if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_route_add_end outside of route definition\n", lineNumber); valid_file = false; break; } race_route_add_end(); in_route_def = false; } else if (!strcmp(token, "race_set_teleport_flags_by_name")) { char name[128]; if (in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_teleport_flags_by_name inside route definition\n", lineNumber); valid_file = false; break; } if (args != 3) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_teleport_flags_by_name: expected 2 arguments, found %d\n", lineNumber, args); valid_file = false; break; } trap_CmdArgv(1, name, sizeof(name)); trap_CmdArgv(2, token, sizeof(token)); if (!strcmp(token, "RACEFLAG_TOUCH_RACEFAIL")) { race_set_teleport_flags_by_name(name, RACEFLAG_TOUCH_RACEFAIL); } else if (!strcmp(token, "RACEFLAG_TOUCH_RACEEND")) { race_set_teleport_flags_by_name(name, RACEFLAG_TOUCH_RACEEND); } } else if (!strcmp(token, "race_set_node_size")) { if (!in_route_def) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_node_size outside of route definition\n", lineNumber); valid_file = false; break; } if (args != 4) { G_bprint( PRINT_HIGH, "#%02d: Invalid route file: race_set_node_size: expected 3 arguments, found %d\n", lineNumber, args); valid_file = false; break; } if (race.route[race.cnt].cnt == 0) { G_bprint(PRINT_HIGH, "#%02d: Invalid route file: race_set_node_size: no node to amend\n", lineNumber); valid_file = false; break; } for (i = 1; i < 4; ++i) { trap_CmdArgv(i, token, MAX_TXTLEN); race.route[race.cnt].node[race.route[race.cnt].cnt - 1].sizes[i - 1] = atof( token); } } else { G_bprint(PRINT_HIGH, "#%02d: Error: unknown route instruction %s\n", lineNumber, token); valid_file = false; break; } } if (!valid_file) { memset(&race, 0, sizeof(race)); } race_fclose(); } } qbool race_handle_event(gedict_t *player, gedict_t *entity, const char *eventName) { int player_num = NUM_FOR_EDICT(player) - 1; if (!player->racer) { return false; // can't touch if not the racer } if (streq(eventName, "touch")) { if (entity->race_flags & RACEFLAG_TOUCH_RACEFAIL) { // do some sound sound(player, CHAN_ITEM, "boss2/idle.wav", 1, ATTN_NONE); race_end(player, true, false); return true; } else if (entity->race_flags & RACEFLAG_TOUCH_RACEEND) { race_end_point_touched(entity, player); return true; } } else if (streq(eventName, "jump") && race.status == raceActive) { race_capture_t *capture = &player_captures[player_num]; if (capture->jump_count < (sizeof(capture->jumps) / sizeof(capture->jumps[0]))) { capture->jumps[capture->jump_count].race_time = g_globalvars.time - race.start_time; VectorCopy(player->s.v.origin, capture->jumps[capture->jump_count].origin); ++capture->jump_count; } } else if (streq(eventName, "watermove")) { if ((player->s.v.watertype == CONTENT_LAVA) || (player->s.v.watertype == CONTENT_SLIME)) { if (player->racer && race.status) { G_bprint(PRINT_HIGH, "%s failed %s run\n", player->netname, g_his(player)); race_end(player, true, false); return true; } } } else if (streq(eventName, "kill")) { if (player->racer && race.status) { if (!race_simultaneous() || (race.status >= raceActive)) { G_bprint(PRINT_HIGH, "%s canceled %s run\n", player->netname, g_his(player)); race_end(player, true, false); } return true; } else if (player->race_chasecam) { return true; } } return false; } static float race_toggle_incr_cvar(char *cvar_name, float incr, float min, float max) { float current = cvar(cvar_name); current += incr; if (current < min || current > max) { current = min; } cvar_fset(cvar_name, current); return current; } void race_pacemaker(void) { int position = 0; char buffer[128]; qbool ignoring_lines = false; int file_version = 1; if (!race_command_checks()) { return; } if (race.status) { G_sprint(self, PRINT_HIGH, "Cannot change pacemaker settings while race is active.\n"); return; } trap_CmdArgv(1, buffer, sizeof(buffer)); if (streq(buffer, "headstart")) { float new_headstart = race_toggle_incr_cvar(RACE_INCR_PARAMS(HEADSTART)); G_bprint(PRINT_HIGH, "%s changes pacemaker headstart to \20%.2fs\21\n", self->netname, new_headstart); return; } else if (streq(buffer, "trail")) { float new_resolution = race_toggle_incr_cvar(RACE_INCR_PARAMS(RESOLUTION)); if (new_resolution) { G_bprint(PRINT_HIGH, "%s changes pacemaker trail to \20%.2fs\21\n", self->netname, new_resolution / 10.0); } else { G_bprint(PRINT_HIGH, "%s changes pacemaker trail \20off\21\n", self->netname); } return; } else if (streq(buffer, "jumps")) { qbool enabled = !cvar(RACE_PACEMAKER_JUMPS_CVAR); G_bprint(PRINT_HIGH, "%s changes pacemaker jump indicators \20%s\21\n", self->netname, enabled ? "on" : "off"); cvar_fset(RACE_PACEMAKER_JUMPS_CVAR, enabled ? 1 : 0); return; } else if (streq(buffer, "off") || ((guide.capture.position_count != 0) && (trap_CmdArgc() == 1))) { G_bprint(PRINT_HIGH, "%s disables the pacemaker\n", self->netname); cvar_fset(RACE_PACEMAKER_ENABLED_CVAR, 0); memset(&guide, 0, sizeof(guide)); memset(&race.pacemaker_nick, 0, sizeof(race.pacemaker_nick)); return; } else { position = 0; } // Try and load race_fropen("%s", race_filename("pos")); if (race_fhandle < 0) { G_sprint(self, PRINT_HIGH, "Unable to load pacemaker record.\n"); return; } race_clear_pacemaker(); ignoring_lines = false; while (race_fgets(buffer, sizeof(buffer))) { char *ch = buffer; qbool error = false; int i; if (!strncmp(buffer, "version ", sizeof("version ") - 1)) { file_version = atoi(buffer + sizeof("version ") - 1); if (file_version > POS_FILE_VERSION) { G_sprint(self, PRINT_HIGH, "Position file is later version (expected %d, found %d)\n", POS_FILE_VERSION, file_version); guide.capture.position_count = 0; return; } ignoring_lines = true; } if (!strncmp(buffer, "player ", sizeof("player ") - 1)) { int this_player = atoi(buffer + sizeof("player ") - 1); ignoring_lines = (this_player != race.records[position].playernumber); } if (ignoring_lines) { continue; } if (!strncmp(buffer, "jump,", 5)) { race_capture_jump_t *jump; if (guide.capture.jump_count >= sizeof(guide.capture.jumps) / sizeof(guide.capture.jumps[0])) { continue; } jump = &guide.capture.jumps[guide.capture.jump_count]; ch = buffer + 5; jump->race_time = atof(ch); ch = strchr(ch, ','); for (i = 0; i < 3; ++i) { if ((error = !ch)) break; jump->origin[i] = atof(ch + 1); ch = strchr(ch + 1, ','); } if (!error) { ++guide.capture.jump_count; } } else { race_capture_pos_t *capture; if (guide.capture.position_count >= (sizeof(guide.capture.positions) / sizeof(guide.capture.positions[0]))) { continue; } capture = &guide.capture.positions[guide.capture.position_count]; capture->race_time = atof(ch); ch = strchr(ch, ','); for (i = 0; i < 3; ++i) { if ((error = !ch)) { break; } capture->origin[i] = atof(ch + 1); ch = strchr(ch + 1, ','); } for (i = 0; i < 2; ++i) { if ((error = !ch)) { break; } capture->angles[i] = atof(ch + 1); ch = strchr(ch + 1, ','); } if (!error) { ++guide.capture.position_count; } } } race_fclose(); guide.position = guide.jump = 0; strlcpy(race.pacemaker_nick, race.records[position].racername, sizeof(race.pacemaker_nick)); race.pacemaker_time = race.records[position].time; G_bprint(PRINT_HIGH, "%s sets pacemaker \20%s\21 (%.3f)\n", self->netname, race.records[position].racername, race.records[position].time / 1000.0f); cvar_fset(RACE_PACEMAKER_ENABLED_CVAR, 1); } qbool race_pacemaker_enabled(void) { return cvar(RACE_PACEMAKER_ENABLED_CVAR) && guide.capture.position_count; } static void race_pacemaker_announce(gedict_t *pacemaker) { gedict_t *p; for (p = world; (p = find_client(p)); /**/) { if (pacemaker) { stuffcmd(p, "//ktx race pm %d\n", NUM_FOR_EDICT(pacemaker)); } else { stuffcmd(p, "//ktx race pm 0\n"); } } } static gedict_t* race_pacemaker_entity(qbool create_if_needed) { gedict_t *ent = ez_find(world, "race_pacemaker"); if ((ent == NULL) && create_if_needed) { ent = spawn(); ent->classname = "race_pacemaker"; ent->walkframe = 0; ent->s.v.frame = 0; ent->s.v.movetype = MOVETYPE_NONE; ent->s.v.flags = 0; setmodel(ent, "progs/player.mdl"); setorigin(ent, 0, 0, 0); setsize(ent, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); } return ent; } static race_capture_pos_t* race_store_position(race_capture_t *capture, float time, float x, float y, float z, float angle_x, float angle_y) { race_capture_pos_t *pos; if (capture->position_count >= RACE_MAX_CAPTURES) { return NULL; } pos = &capture->positions[capture->position_count]; pos->race_time = time; VectorSet(pos->origin, x, y, z); pos->angles[0] = angle_x; pos->angles[1] = angle_y; ++capture->position_count; return pos; } static void race_save_position(void) { race_capture_pos_t *pos; float next_time; vec3_t diff, new_origin; gedict_t *racer; float race_time = g_globalvars.time - race.start_time; for (racer = world; (racer = race_find_racer(racer)); /**/) { int player_num = NUM_FOR_EDICT(racer) - 1; race_capture_t *capture = &player_captures[player_num]; if ((capture->position_count == 0) || (capture->position_count >= (RACE_MAX_CAPTURES - 1))) { return; } pos = &capture->positions[capture->position_count - 1]; next_time = pos->race_time + 1.0 / RACE_CAPTURE_FPS; while (pos && race_time > next_time) { float frac = (next_time - pos->race_time) / (race_time - pos->race_time); VectorSubtract(racer->s.v.origin, pos->origin, diff); VectorMA(pos->origin, frac, diff, new_origin); pos = race_store_position(capture, next_time, PASSVEC3(new_origin), racer->s.v.angles[0], racer->s.v.angles[1]); next_time += 1.0 / RACE_CAPTURE_FPS; } } } static void race_init_capture(void) { gedict_t *racer; memset(&player_captures, 0, sizeof(player_captures)); for (racer = world; (racer = race_find_racer(racer)); /**/) { int player_num = NUM_FOR_EDICT(racer) - 1; race_store_position(&player_captures[player_num], 0, PASSVEC3(racer->s.v.origin), racer->s.v.angles[0], racer->s.v.angles[1]); } } static void race_finish_capture(qbool store, int player_num) { if (store && player_num >= 0 && player_num < MAX_CLIENTS) { gedict_t *racer = &g_edicts[player_num + 1]; race_capture_t *capture = race_match_mode() ? &player_match_info[player_num].best_run_capture : &player_captures[player_num]; race_fwopen("%s", race_filename("pos")); race_fprintf("version %d\n", POS_FILE_VERSION); race_store_position(capture, g_globalvars.time - race.start_time, PASSVEC3(racer->s.v.origin), racer->s.v.angles[0], racer->s.v.angles[1]); race_fprintf("player %d\n", player_num); if (race_fhandle >= 0) { int i = 0; for (i = 0; i < capture->position_count; ++i) { race_capture_pos_t *pos = &capture->positions[i]; race_fprintf("%.3f,%.1f,%.1f,%.1f,%.1f,%.1f\n", pos->race_time, PASSVEC3(pos->origin), pos->angles[0], pos->angles[1]); } for (i = 0; i < capture->jump_count; ++i) { race_capture_jump_t *jump = &capture->jumps[i]; race_fprintf("jump,%.3f,%.1f,%.1f,%.1f\n", jump->race_time, PASSVEC3(jump->origin)); } } race_fclose(); } memset(&player_captures, 0, sizeof(player_captures)); } static void race_remove_jump_markers(void) { int i; for (i = 0; i < RACE_JUMP_INDICATORS; ++i) { if (race_jump_indicators[i]) { ent_remove(race_jump_indicators[i]); race_jump_indicators[i] = NULL; } } guide.jump = 0; } static void race_reset_pacemaker_route(void) { gedict_t *plr; race_remove_pacemaker_indicator(); for (plr = world; (plr = find_plr(plr)); /**/) { plr->race_closest_guide_pos = 0; } race_remove_jump_markers(); } static void race_pacemaker_race_start(void) { gedict_t *racer; for (racer = world; (racer = race_find_racer(racer)); /**/) { racer->race_closest_guide_pos = 0; } if (race_pacemaker_enabled()) { gedict_t *ent = race_pacemaker_entity(true); if (ent) { race_pacemaker_announce(ent); setorigin(ent, PASSVEC3(guide.capture.positions[0].origin)); } } else { race_remove_pacemaker_indicator(); } race_remove_jump_markers(); } // Sets race_closest_guide_pos to the nearest guide location for each racer static void race_update_closest_positions(void) { gedict_t *racer; int i; if (!guide.capture.position_count) { // No guide loaded return; } for (racer = world; (racer = race_find_racer(racer)); /**/) { if (racer->race_closest_guide_pos < guide.capture.position_count) { float closest_distance = 0.0f; vec3_t diff; int max_record; VectorSubtract(racer->s.v.origin, guide.capture.positions[racer->race_closest_guide_pos].origin, diff); closest_distance = VectorLength(diff); // Hmm - this could break if the fastest record goes backwards for more than 10 frames... // Previously it searched from the end, but with more than one racer?... max_record = min(racer->race_closest_guide_pos + 10, guide.capture.position_count); for (i = racer->race_closest_guide_pos + 1; i < max_record; ++i) { float distance; VectorSubtract(racer->s.v.origin, guide.capture.positions[i].origin, diff); distance = VectorLength(diff); if (distance <= closest_distance) { closest_distance = distance; racer->race_closest_guide_pos = i; max_record = min(racer->race_closest_guide_pos + 10, guide.capture.position_count); } } } } } static void race_update_pacemaker(void) { float race_time = 0; float frac; qbool advanced = false; int i; qbool removal_required = !race_pacemaker_enabled(); if (framecount < 5) { return; } switch (race.status) { case raceNone: race_time = -10.0f; removal_required = true; break; case raceActive: race_time = g_globalvars.time - race.start_time; break; case raceCD: if (race.cd_cnt) { guide.jump = guide.position = 0; } race_time = -(race.cd_cnt + (race.cd_next_think - g_globalvars.time)); break; } race_time += bound(RACE_PACEMAKER_HEADSTART_MIN, cvar(RACE_PACEMAKER_HEADSTART_CVAR), RACE_PACEMAKER_HEADSTART_MAX); // If we're finished or player disabled feature, remove the guide if (removal_required) { race_reset_pacemaker_route(); return; } // We want a guide, but haven't started racing yet if (race_time <= 0) { guide.position = 0; } // Advance pointer until at correct record while ((guide.position < (guide.capture.position_count - 1)) && (guide.capture.positions[guide.position + 1].race_time < race_time)) { ++guide.position; advanced = true; } // If the guide ends the map, remove pacemaker, leave the guides if (guide.position >= (guide.capture.position_count - 1)) { race_remove_pacemaker_indicator(); } // Guide capture position if ((race_time > 0) && (guide.position >= 0) && (guide.position < (guide.capture.position_count - 1))) { race_capture_pos_t *cur = &guide.capture.positions[guide.position]; race_capture_pos_t *next = &guide.capture.positions[guide.position + 1]; vec3_t direction; // Sanity... if (next->race_time > cur->race_time) { gedict_t *ent = race_pacemaker_entity(true); vec3_t new_origin; frac = (race_time - cur->race_time) / (next->race_time - cur->race_time); VectorSubtract(next->origin, cur->origin, direction); VectorMA(cur->origin, frac, direction, new_origin); setorigin(ent, PASSVEC3(new_origin)); vectoangles(direction, ent->s.v.angles); if (advanced) { if (ent->walkframe >= 6) { ent->walkframe = 0; } if (direction[0] < 0) { ent->s.v.frame = 11 - ent->walkframe; } else { ent->s.v.frame = 6 + ent->walkframe; } ++ent->walkframe; } } } if (race.status) { int guide_start = 0; int guide_end = 0; int resolution = (int)bound(RACE_PACEMAKER_RESOLUTION_MIN, cvar(RACE_PACEMAKER_RESOLUTION_CVAR), RACE_PACEMAKER_RESOLUTION_MAX); if (resolution) { // From the pacemaker's position backwards guide_start = max(0, guide.position - RACE_PACEMAKER_TRAIL_COUNT * resolution); if (race.racers_competing == 1) { // In single race, we draw from player forwards, up to the pacemaker gedict_t *racer = race_get_racer(); if (racer) { guide_start = min(guide_start, racer->race_closest_guide_pos); } } // Adjust for resolution, to stop LG jumping around as we move forwards guide_start = (guide_start / resolution) * resolution; guide_end = min( guide.position, min(guide_start + resolution * RACE_PACEMAKER_TRAIL_COUNT, guide.capture.position_count)); // Create lightning trail for next part of route if (guide_start >= 0 && guide_end > 0) { int num = 0; for (i = guide_start; i < guide_end; i += resolution, ++num) { int next = (int)bound(0, i + resolution, guide.capture.position_count - 1); WriteByte(MSG_MULTICAST, SVC_TEMPENTITY); WriteByte(MSG_MULTICAST, TE_LIGHTNING2); WriteShort(MSG_MULTICAST, RACE_GUIDE_BASE_ENT + num); WriteCoord(MSG_MULTICAST, guide.capture.positions[i].origin[0]); WriteCoord(MSG_MULTICAST, guide.capture.positions[i].origin[1]); WriteCoord(MSG_MULTICAST, guide.capture.positions[i].origin[2]); WriteCoord(MSG_MULTICAST, guide.capture.positions[next].origin[0]); WriteCoord(MSG_MULTICAST, guide.capture.positions[next].origin[1]); WriteCoord(MSG_MULTICAST, guide.capture.positions[next].origin[2]); trap_multicast(PASSVEC3(guide.capture.positions[i].origin), MULTICAST_PHS); } update_jump_markers(race_time, guide_start, resolution); } } } } static void update_jump_markers(float race_time, int guide_start, int resolution) { float guide_race_time = guide_start >= guide.capture.position_count ? 99999.9f : guide.capture.positions[guide_start].race_time; qbool jumps_enabled = cvar(RACE_PACEMAKER_JUMPS_CVAR) && resolution; int i; // Remove old indicators while (race_jump_indicators[0] && ((race_jump_indicator_times[0] < guide_race_time) || !jumps_enabled)) { if (race_jump_indicators[0]) { ent_remove(race_jump_indicators[0]); } memmove(race_jump_indicator_times, race_jump_indicator_times + 1, sizeof(race_jump_indicator_times[0]) * (RACE_JUMP_INDICATORS - 1)); memmove(race_jump_indicators, race_jump_indicators + 1, sizeof(race_jump_indicators[0]) * (RACE_JUMP_INDICATORS - 1)); race_jump_indicators[RACE_JUMP_INDICATORS - 1] = NULL; race_jump_indicator_times[RACE_JUMP_INDICATORS - 1] = -1.0f; } // Create new indicators if ((jumps_enabled && guide.jump < guide.capture.jump_count) && (guide.capture.jumps[guide.jump].race_time <= race_time)) { for (i = 0; i < RACE_JUMP_INDICATORS; ++i) { if (!race_jump_indicators[i]) { gedict_t *ent = spawn(); ent->classname = "race_pacemaker_jump"; ent->s.v.movetype = MOVETYPE_NONE; ent->s.v.solid = SOLID_NOT; if (k_ctf_custom_models) { setmodel(ent, "progs/star.mdl"); } else { setmodel(ent, "progs/lavaball.mdl"); } setorigin(ent, PASSVEC3(guide.capture.jumps[guide.jump].origin)); setsize(ent, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); droptofloor(ent); setorigin(ent, ent->s.v.origin[0], ent->s.v.origin[1], ent->s.v.origin[2] - 16); race_jump_indicators[i] = ent; race_jump_indicator_times[i] = guide.capture.jumps[guide.jump].race_time; ++guide.jump; break; } } } } static void race_clear_pacemaker(void) { memset(&guide, 0, sizeof(guide)); race_remove_pacemaker_indicator(); } static void race_remove_pacemaker_indicator(void) { gedict_t *ent; while ((ent = race_pacemaker_entity(false))) { ent_remove(ent); race_pacemaker_announce(NULL); } } static qbool race_end(gedict_t *racer, qbool valid, qbool complete) { racer->racer = false; racer->muted = true; race_set_one_player_movetype_and_etc(racer); if (valid && !strnull(cvar_string("sv_www_address")) && !strnull(racer->netname)) { const char *map = cvar_string(RACE_ROUTE_MAPNAME_CVAR); int route_number = cvar(RACE_ROUTE_NUMBER_CVAR); if (!strnull(map) && (route_number >= 0)) { localcmd( "\n" // why new line? "sv_web_post ServerApi/LogRaceAttempt \"\" map %s routeNumber %d weap %d fs %d racer %s time %.3f complete %s\n", map, route_number, race.weapon, race.falsestart, racer->netname, race_time() / 1000.0f, complete && !race_pacemaker_enabled() ? "true" : "false"); trap_executecmd(); } } if (race_get_racer() == NULL) { race_over(); return true; } return false; } static char* race_position_string(int position) { char *positions[] = { "1st place", "2nd place", "3rd place", "4th place", "5th place", "6th place", "7th place", "8th place", "9th place", "10th place" }; if ((position >= 1) && (position <= (sizeof(positions) / sizeof(positions[0])))) { return positions[position - 1]; } return ""; } static qbool race_simultaneous(void) { // We don't support matches where the players go turn about return (race_match_mode() || cvar(RACE_SIMULTANEOUS_CVAR)); } void race_player_post_think(void) { if (isRACE()) { // test for multirace self->s.v.solid = SOLID_NOT; setorigin(self, PASSVEC3(self->s.v.origin)); } race_follow(); } static int race_encode_user_command(gedict_t *player) { int result = (player->s.v.button0 ? 1 : 0) + (player->s.v.button2 ? 2 : 0); if (player->movement[0] > 0) { result += 4; } else if (player->movement[0] < 0) { result += 8; } if (player->movement[1] > 0) { result += 16; } else if (player->movement[1] < 0) { result += 32; } if (player->movement[2] > 0) { result += 64; } else if (player->movement[2] < 0) { result += 128; } return result; } void race_player_pre_think(void) { if (isRACE()) { // Set this player to solid so we trigger checkpoints & teleports during move self->s.v.solid = (race.status == raceNone || self->racer ? SOLID_SLIDEBOX : SOLID_NOT); if ((self->s.v.mins[0] == 0) || (self->s.v.mins[1] == 0)) { // This can happen if the world 'squashes' a SOLID_NOT entity, mvdsv will turn into corpse setsize(self, PASSVEC3(VEC_HULL_MIN), PASSVEC3(VEC_HULL_MAX)); } setorigin(self, PASSVEC3(self->s.v.origin)); if ((self->ct == ctPlayer) && !self->racer && race.status) { if (self->race_chasecam) { if (self->s.v.button2) { if (((int)(self->s.v.flags)) & FL_JUMPRELEASED) { self->s.v.flags = (int)self->s.v.flags & ~FL_JUMPRELEASED; race_advance_chasecam_for_plr(self); } } else { self->s.v.flags = ((int)(self->s.v.flags)) | FL_JUMPRELEASED; } } } else if ((self->ct == ctPlayer) && self->racer && race.status) { // If server supports storing user commands in hidden packets, don't bother with these if (!(sv_extensions & SV_EXTENSIONS_MVDHIDDEN)) { stuffcmd_flags(self, STUFFCMD_DEMOONLY, "//ucmd %f %d %d\n", g_globalvars.time, race_encode_user_command(self), NUM_FOR_EDICT(self)); } } } } void race_simultaneous_toggle(void) { if (!race_command_checks()) { return; } if (race_is_started()) { return; } cvar_toggle_msg(self, RACE_SIMULTANEOUS_CVAR, redtext("simultaneous racing")); } // match rules // ... scoring systems typedef struct race_score_system_s { char *name; // friendly name, appears in countdown (keep <= 9 characters) int positions[10]; // points allocated for being 1st, 2nd, 3rd etc int complete; // points allocated for completing the course int beating; // points allocated for each opponent beaten int dnf_penalty; // penalise anyone failing to finish (-1? - not use atm) int round_max_diff; // in duels, end early if frag_diff > round_max_diff * rounds_remaining } race_score_system_t; // These are very basic, no competitions to base systems on static race_score_system_t scoring_systems[] = { // Winner only: 1 frag for winning, for winner after x rounds (hoony-mode stylee) { "Win Only", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 1 }, // Scaled system: 1 frag for completing run, 1 frag for each opponent beaten, 1 bonus frag for winner // (better for more players... also gives penalty in duels to risky play, 3-0 instead of 3-1) { "Scaled", { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 1, 1, 0, 3 }, // Formula1: points allocated by position (winning-bonus/losing-penalty increases - for 4+ players really) { "Formula1", { 25, 18, 15, 12, 10, 8, 6, 4, 2, 1 }, 0, 0, 0, 25 } }; #define NUM_SCORING_SYSTEMS (sizeof(scoring_systems) / sizeof(scoring_systems[0])) void race_scoring_system_toggle(void) { int current = bound(0, (int)cvar(RACE_SCORINGSYSTEM_CVAR), NUM_SCORING_SYSTEMS - 1); if (!race_command_checks()) { return; } if (race_is_started() || match_in_progress) { return; } current = (current + 1) % NUM_SCORING_SYSTEMS; cvar_fset(RACE_SCORINGSYSTEM_CVAR, current); G_bprint(PRINT_HIGH, "%s enabled the \20%s\21 scoring system\n", self->netname, scoring_systems[current].name); } int race_award_points(int position, int participants) { int current = bound(0, (int)cvar(RACE_SCORINGSYSTEM_CVAR), NUM_SCORING_SYSTEMS - 1); race_score_system_t *system = &scoring_systems[current]; int points = 0; if (!race_match_mode()) { return 0; } if (position <= 0) { points += system->dnf_penalty; } else if (position >= 1 && position <= sizeof(system->positions) / sizeof(system->positions[0])) { points = system->complete; points += system->positions[position - 1]; // This also gives points for coming joint = with another player... change? points += (participants - position) * system->beating; } return points; } char* race_scoring_system_name(void) { int current = bound(0, (int)cvar(RACE_SCORINGSYSTEM_CVAR), NUM_SCORING_SYSTEMS - 1); if (!race_match_mode()) { return "???"; } return scoring_systems[current].name; } // configuration qbool race_match_mode(void) { return cvar(RACE_MATCH_CVAR); } void race_match_toggle(void) { if (!race_command_checks()) { return; } if (race_is_started()) { return; } cvar_toggle_msg(self, RACE_MATCH_CVAR, redtext("match mode")); cvar_fset("sv_silentrecord", cvar(RACE_MATCH_CVAR) ? 0 : 1); } static int TeamSorter(const void *lhs_, const void *rhs_) { const race_stats_score_t *lhs = (const race_stats_score_t*) lhs_; const race_stats_score_t *rhs = (const race_stats_score_t*) rhs_; if (lhs->score > rhs->score) { return -1; } if (rhs->score > lhs->score) { return 1; } return strcmp(lhs->name, rhs->name); } static void race_match_stats_print(char *title, race_stats_score_t *scores, int team_count) { int i; G_bprint( 2, "\n%s\n\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext(title)); for (i = 0; i < team_count; ++i) { G_bprint(PRINT_HIGH, "\20%s\21: %d points\n", scores[i].name, scores[i].score); G_bprint(PRINT_HIGH, " Completed %d rounds, won %d\n", scores[i].completions, scores[i].wins); if (scores[i].completions) { G_bprint(PRINT_HIGH, " Average time: %8.3f\n", (scores[i].total_time / 1000.0f) / scores[i].completions); G_bprint(PRINT_HIGH, " Average speed: %8.3f\n", (scores[i].total_distance / 1000.0f) / scores[i].completions); G_bprint(PRINT_HIGH, " Best time: %8.3f\n", scores[i].best_time / 1000.0f); } } } static void race_match_stats_apply(race_stats_score_t *stats, gedict_t *player) { int p_num = NUM_FOR_EDICT(player) - 1; stats->score += player->s.v.frags; stats->wins += player_match_info[p_num].wins; stats->completions += player_match_info[p_num].completions; if (player_match_info[p_num].best_time) { if (stats->best_time == 0) { stats->best_time = player_match_info[p_num].best_time; } else { stats->best_time = min(stats->best_time, player_match_info[p_num].best_time); } } if (player_match_info[p_num].completions) { stats->total_time += player_match_info[p_num].total_time; stats->total_distance += player_match_info[p_num].total_distance; } } static void race_sort_teams(race_stats_score_t *teams, int count) { #ifdef Q3_VM qbool any_changes = true; // bubble-sort, lovely while (any_changes) { int i; any_changes = false; for (i = 0; i < count - 1; ++i) { int comp = TeamSorter(&teams[i], &teams[i + 1]); if (comp > 0) { race_stats_score_t temp = teams[i]; teams[i] = teams[i + 1]; teams[i + 1] = temp; any_changes = true; } } } #else qsort(teams, count, sizeof(teams[0]), TeamSorter); #endif } static void race_match_team_stats(void) { gedict_t *p, *p2; int teams_found = 0; race_stats_score_t teams[MAX_CLIENTS] = { { 0 } }; // keep track of players we've processed for (p = world; (p = race_find_race_participants(p)); /**/) { p->cnt = 0; } for (p = world; (p = race_find_race_participants(p)); /**/) { if (!p->cnt) { char *team = getteam(p); teams[teams_found].name = team; race_match_stats_apply(&teams[teams_found], p); for (p2 = p; (p2 = race_find_race_participants(p2)); /**/) { if (!p2->cnt) { char *team2 = getteam(p2); if (streq(team, team2)) { race_match_stats_apply(&teams[teams_found], p2); p2->cnt = 1; } } } ++teams_found; } } race_sort_teams(teams, teams_found); race_match_stats_print("Team scores", teams, teams_found); } static race_stats_score_t player_stats[MAX_CLIENTS] = { { 0 } }; static int players_found = 0; static void race_match_player_stats(void) { gedict_t *p; memset(player_stats, 0, sizeof(player_stats)); players_found = 0; for (p = world; (p = race_find_race_participants(p)); /**/) { player_stats[players_found].name = p->netname; race_match_stats_apply(&player_stats[players_found], p); ++players_found; } race_match_stats_print("Player scores", player_stats, players_found); } race_stats_score_t* race_get_player_stats(int *players) { *players = players_found; return player_stats; } void race_match_stats(void) { // TODO: Think up and keep track of stats we want summarised/match if (teamplay) { race_match_team_stats(); } race_match_player_stats(); } void race_match_start(void) { gedict_t *p; // convert all match-ready players to race-ready for (p = world; (p = find_plr(p)); /**/) { p->race_ready = p->ready; } race.round_number = 0; memset(player_match_info, 0, sizeof(player_match_info)); race_start(false, "%s", ""); } qbool race_match_started(void) { return (race_match_mode() && (race.status || match_in_progress)); } void race_switch_usermode(const char *displayName, int players_per_team) { int maxClients = (players_per_team < 0 ? 26 : players_per_team * 2); if (!race_command_checks()) { return; } if (race_is_started()) { return; } if (players_per_team == 0) { G_sprint(self, 2, "%s is not a supported race mode\n", displayName); return; } if (match_in_progress) { G_sprint(self, 2, "Command is locked while %s is in progress\n", redtext("match")); return; } if (!race_match_mode()) { race_match_toggle(); } cvar_fset("maxclients", maxClients); cvar_fset("k_maxclients", maxClients); cvar_fset("teamplay", players_per_team > 0 ? 3 : 0); if (players_per_team < 0) { cvar_fset("k_mode", gtFFA); } else if (players_per_team == 1) { cvar_fset("k_mode", gtDuel); } else { cvar_fset("k_mode", gtTeam); } G_bprint(PRINT_HIGH, "%s %s %s\n", displayName, redtext("settings enabled by"), self->netname); } // Return true if new countdown should be started static void race_match_round_end(void) { gedict_t *racer; gedict_t *ed1, *ed2; int score1, score2; int sc; // Award points for this round for (racer = world; (racer = race_find_race_participants(racer)); /**/) { int player_num = NUM_FOR_EDICT(racer) - 1; racer->s.v.frags += race_award_points(race.currentrace[player_num].position, race.racers_competing); if (race.currentrace[player_num].time) { ++player_match_info[player_num].completions; if ((player_match_info[player_num].best_time == 0) || (player_match_info[player_num].best_time > race.currentrace[player_num].time)) { memcpy(&player_match_info[player_num].best_run_capture, &player_captures[player_num], sizeof(race_capture_t)); player_match_info[player_num].best_time = race.currentrace[player_num].time; } player_match_info[player_num].total_time += race.currentrace[player_num].time; player_match_info[player_num].total_distance += race.currentrace[player_num].distance; if (race.currentrace[player_num].position == 1) { ++player_match_info[player_num].wins; } } } ed1 = get_ed_scores1(); ed2 = get_ed_scores2(); score1 = get_scores1(); score2 = get_scores2(); if ((isDuel() || isFFA()) && ed1 && ed2) { score1 = ed1->s.v.frags; score2 = ed2->s.v.frags; } sc = score1 - score2; // Advance round pointer race.round_number = min(race.round_number + 1, race.rounds); k_nochange = false; if (race.round_number >= race.rounds) { if (sc == 0) { if (!teamplay) { // Remove anyone apart from the top-scorers for deciding round for (racer = world; (racer = race_find_race_participants(racer)); /**/) { racer->race_ready = (racer->s.v.frags == score1); } } else { // Remove members of all teams not currently on top score... // TODO: Support more than 2 teams, consistently with match mode in KTX // Can't see anything to remove losing teams on sudden death mode in // standard teamplay, so leaving them here too... Does mean that a // third place team could win the match in final round } } else { // We have a winner, end the race race_finish_capture(false, -1); EndMatch(false); return; } } else if (!teamplay) { // Standard round... in duels and ffa, can finish as soon as leading player has unassailable lead int rounds_remaining = (race.rounds - race.round_number); int system_no = bound(0, (int)cvar(RACE_SCORINGSYSTEM_CVAR), NUM_SCORING_SYSTEMS - 1); race_score_system_t *system = &scoring_systems[system_no]; if (system->round_max_diff && ((rounds_remaining * system->round_max_diff) < sc)) { // We have winner, end the race G_bprint(PRINT_HIGH, "%d points (%d rounds) available... ending match\n", rounds_remaining * system->round_max_diff, rounds_remaining); race_finish_capture(false, -1); EndMatch(false); return; } } // Start next run race_start(false, "%s", ""); } qbool race_can_cancel_demo(void) { if (!isRACE()) { return true; } // Always save demos as soon as a run is completed return ((race.round_number == 0) && (race.racers_complete == 0)); } int race_count_votes_req(float percentage) { int racers_ready; // No-one ready or map recently started, so behave as normal if ((g_globalvars.time < 10) || !(racers_ready = race_count_ready_players())) { return ceil(percentage * CountPlayers()); } return racers_ready; } qbool race_allow_map_vote(gedict_t *player) { int racers_ready; // No-one ready or map recently started, so behave as normal if ((g_globalvars.time < 10) || !(racers_ready = race_count_ready_players())) { return true; } return ((racers_ready == 0) || player->race_ready); } void race_hide_players_toggle(void) { if (!race_command_checks()) { return; } self->hideplayers_default = !self->hideplayers_default; G_sprint(self, PRINT_HIGH, "Racers %s during race\n", self->hideplayers_default ? redtext("hidden") : redtext("shown")); if (race.status) { self->hideplayers = self->hideplayers_default; } } QW-Group-ktx-d05d6ca/src/rng.c000066400000000000000000000021101475442401000161430ustar00rootroot00000000000000#include "rng.h" #include "rng_gen_impl.h" #include "rng_seed_impl.h" /* Seed the PRNG. Since the main game loop only provides 4 bytes of entropy, but the xoroshiro128** PRNG expects 16 bytes of entropy, this function uses the splitmix64 algorithm to expand the seed. This approach is recommended by the authors of xoroshiro128**, as described here: https://prng.di.unimi.it . You must initialize your RngStates with rng_seed/rng_seed_global! (The all-zeros state has bad statistics.) */ void rng_seed(RngState* s, int seed) { rng_seed_t x = (rng_seed_t)(seed); s->s[0] = (unsigned int)rng_seed_impl_next(&x); s->s[1] = (unsigned int)rng_seed_impl_next(&x); s->s[2] = (unsigned int)rng_seed_impl_next(&x); s->s[3] = (unsigned int)rng_seed_impl_next(&x); } unsigned int rng_next(RngState* state) { return rng_gen_impl_next(state); } // You must initialize this with rng_seed/rng_seed_global! static RngState global_rng = { 0 }; void rng_seed_global(int seed) { rng_seed(&global_rng, seed); } unsigned int rng_next_global(void) { return rng_next(&global_rng); } QW-Group-ktx-d05d6ca/src/rng_gen_impl.c000066400000000000000000000032301475442401000200210ustar00rootroot00000000000000#include "rng_gen_impl.h" //// Start imported code. // Code in this section copied from // https://prng.di.unimi.it/xoshiro128starstar.c // It was lightly edited to change a global variable to a local variable. /* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) To the extent possible under law, the author has dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. See . */ /* This is xoshiro128** 1.1, one of our 32-bit all-purpose, rock-solid generators. It has excellent speed, a state size (128 bits) that is large enough for mild parallelism, and it passes all tests we are aware of. Note that version 1.0 had mistakenly s[0] instead of s[1] as state word passed to the scrambler. For generating just single-precision (i.e., 32-bit) floating-point numbers, xoshiro128+ is even faster. The state must be seeded so that it is not everywhere zero. */ #ifdef Q3_VM # define Q_INLINE #else # define Q_INLINE inline #endif static Q_INLINE unsigned int rotl(const unsigned int x, int k) { return (x << k) | (x >> (32 - k)); } static Q_INLINE unsigned int next(RngState* s) { const unsigned int result = rotl(s->s[1] * 5, 7) * 9; const unsigned int t = s->s[1] << 9; s->s[2] ^= s->s[0]; s->s[3] ^= s->s[1]; s->s[1] ^= s->s[2]; s->s[0] ^= s->s[3]; s->s[2] ^= t; s->s[3] = rotl(s->s[3], 11); return result; } //// End imported code. // Code in this section wraps the PRNG implementation. unsigned int rng_gen_impl_next(RngState* state) { return next(state); } QW-Group-ktx-d05d6ca/src/rng_seed_impl.c000066400000000000000000000026021475442401000201720ustar00rootroot00000000000000//// Start imported code. // Code in this section was copied from // https://prng.di.unimi.it/splitmix64.c // then lightly edited to remove a global variable and rename a function. /* Written in 2015 by Sebastiano Vigna (vigna@acm.org) To the extent possible under law, the author has dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty. See . */ #include "rng_seed_impl.h" /* This is a fixed-increment version of Java 8's SplittableRandom generator See http://dx.doi.org/10.1145/2714064.2660195 and http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html It is a very fast generator passing BigCrush, and it can be useful if for some reason you absolutely want 64 bits of state. */ #ifdef Q3_VM # define C1 0x9e3779b9 # define C2 0xbf58476d # define C3 0x94d049bb #else # define C1 0x9e3779b97f4a7c15 # define C2 0xbf58476d1ce4e5b9 # define C3 0x94d049bb133111eb #endif #define SHIFT1 (sizeof(rng_seed_t) == 8 ? 30 : 15) #define SHIFT2 (sizeof(rng_seed_t) == 8 ? 27 : 13) #define SHIFT3 (sizeof(rng_seed_t) == 8 ? 31 : 16) rng_seed_t rng_seed_impl_next(rng_seed_t* x) { rng_seed_t z = (*x += C1); z = (z ^ (z >> SHIFT1)) * C2; z = (z ^ (z >> SHIFT2)) * C3; return z ^ (z >> SHIFT3); } //// End imported code. QW-Group-ktx-d05d6ca/src/route_calc.c000066400000000000000000000407371475442401000175160ustar00rootroot00000000000000/* route_calc.qc Copyright (C) 1997-1999 Robert 'Frog' Field Copyright (C) 1998-2000 Matt 'asdf' McChesney Copyright (C) 2000-2007 ParboiL */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT // After markers have been created and zone/subzone set, this calculates travel time // between different markers & goals etc. // Single entry point InitialiseMarkerRoutes() // TODO: 5/6/10 have near-identical body, can be ForAllZones(func) #include "g_local.h" typedef qbool (*fb_path_calc_funcref_t)(gedict_t *m, fb_path_t *path); extern gedict_t *markers[]; static void Calc_G_time_12(void); // static float runaway_score = 0; static float min_traveltime = 0; static float runaway_time = 0; static float P_time = 0; static void TravelTimeForPath(gedict_t *m, int i) { gedict_t *m_P = m->fb.paths[i].next_marker; vec3_t m_pos; VectorAdd(m->s.v.absmin, m->s.v.view_ofs, m_pos); if (m->fb.paths[i].flags & ROCKET_JUMP) { vec3_t m_P_pos; vec3_t distance; vec3_t hor_distance; float player_speed; float total_distance; VectorAdd(m_P->s.v.absmin, m_P->s.v.view_ofs, m_P_pos); VectorSubtract(m_P_pos, m_pos, distance); VectorCopy(distance, hor_distance); total_distance = VectorNormalize(distance); VectorNormalize(hor_distance); player_speed = sv_maxspeed * (1 + max(0, DotProduct(distance, hor_distance))); // FIXME: RJ time is guideline, but we can do better than this? m->fb.paths[i].time = 100000; m->fb.paths[i].rj_time = (total_distance / player_speed); return; } if (m->fb.paths[i].flags & JUMP_LEDGE) { m->fb.paths[i].flags |= NO_DODGE; } // Distance irrelevant if teleporting if (streq(m->classname, "trigger_teleport")) { m->fb.paths[i].time = 0; } else { vec3_t m_P_pos; VectorAdd(m_P->s.v.absmin, m_P->s.v.view_ofs, m_P_pos); if ((m->fb.T & T_WATER) || (m_P->fb.T & T_WATER)) { m->fb.paths[i].flags |= WATER_PATH; m->fb.paths[i].rj_time = m->fb.paths[i].time = (VectorDistance(m_P_pos, m_pos) / sv_maxwaterspeed); } else { m->fb.paths[i].rj_time = m->fb.paths[i].time = (VectorDistance(m_P_pos, m_pos) / sv_maxspeed); } } } // Was: Calc_G_time_3_path_apply static qbool IdentifyFastestSubzoneRoute(gedict_t *m, fb_path_t *path) { qbool no_change = true; gedict_t *m_P = path->next_marker; int m_D = path->flags; if (!m || (m == world) || !m_P || (m_P == world)) { return no_change; } if (m->fb.Z_ == m_P->fb.Z_) { int i = 0; for (i = 0; i < NUMBER_SUBZONES; ++i) { fb_subzone_t *sub = &m->fb.subzones[i]; fb_subzone_t *next_sub = &m_P->fb.subzones[i]; // Standard travel time if (sub->time > (path->time + next_sub->time)) { no_change = false; sub->time = path->time + next_sub->time; sub->next_marker = path->next_marker; } if (m_D & ROCKET_JUMP) { // RJ this link, then standard path if (sub->rj_time > (path->rj_time + sub->time)) { no_change = false; sub->rj_time = path->rj_time + sub->time; sub->next_marker_rj = path->next_marker; } // TODO: What about sub->rj_time? Paths with multiple rocket jumps? // Could simplify with sub->times[X] where X is number of rocket jumps in path // ... not for now... } // If it's faster to walk than RJ, do that instead if (sub->rj_time > sub->time) { no_change = false; sub->rj_time = sub->time; sub->next_marker_rj = sub->next_marker; } } } return no_change; } // Calc_G_time_4_path_apply static qbool IdentifyFastestGoalRoute(gedict_t *m, fb_path_t *path) { qbool no_change = true; int i = 0; if (!m || (m == world) || !path->next_marker || (path->next_marker == world)) { return no_change; } for (i = 0; i < NUMBER_GOALS; ++i) { fb_goal_t *goal = &m->fb.goals[i]; fb_goal_t *next_goal = &path->next_marker->fb.goals[i]; // faster route to goal by standard travel if (goal->time > (path->time + next_goal->time)) { goal->next_marker = next_goal->next_marker; goal->time = path->time + next_goal->time; no_change = false; } // rocket jump routes if (goal->rj_time > (path->rj_time + next_goal->rj_time)) { goal->next_marker_rj = next_goal->next_marker_rj; goal->rj_time = path->rj_time + next_goal->rj_time; no_change = false; } } return no_change; } // Was: Calc_G_time_5_path_apply static qbool IdentifyFastestZoneRoute(gedict_t *m, fb_path_t *path) { qbool no_change = true; int i = 0; if (!m || (m == world) || !path->next_marker || (path->next_marker == world)) { return no_change; } for (i = 0; i < NUMBER_ZONES; ++i) { fb_zone_t *zone = &m->fb.zones[i]; fb_zone_t *next_zone = &path->next_marker->fb.zones[i]; if (zone->time > (path->time + next_zone->time)) { zone->time = path->time + next_zone->time; zone->next = path->next_marker; zone->marker = next_zone->marker; zone->next_zone = next_zone->next_zone; if (i == 0) { zone->task |= path->flags; } no_change = false; } if (zone->rj_time > (path->rj_time + next_zone->rj_time)) { zone->rj_time = path->rj_time + next_zone->rj_time; zone->marker_rj = next_zone->marker_rj; zone->next_rj = path->next_marker; no_change = false; } if (zone->rj_time > zone->time) { zone->rj_time = zone->time; zone->marker_rj = zone->marker; zone->next_rj = zone->next; no_change = false; } } return no_change; } // was: Calc_G_time_6_path_apply static qbool Calc_G_time_6_path_apply(gedict_t *m, fb_path_t *path) { qbool no_change = true; int i = 0; if (!m || (m == world) || !path->next_marker || (path->next_marker == world)) { return no_change; } for (i = 0; i < NUMBER_ZONES; ++i) { fb_zone_t *zone = &m->fb.zones[i]; fb_zone_t *nextzone = &path->next_marker->fb.zones[i]; if (nextzone->from_time > (zone->from_time + path->time)) { nextzone->from_time = zone->from_time + path->time; no_change = false; } } return no_change; } static int CheckReversible(gedict_t *m, gedict_t *from_marker) { gedict_t *next_marker = from_marker->fb.zones[m->fb.Z_ - 1].next_zone; if ((next_marker != NULL) && (next_marker->fb.Z_ == m->fb.Z_)) { return REVERSIBLE; } else { return 0; } } // if path from m1->m2 and m2->m1, set the reversible flag static void Calc_G_time_7(void) { int i; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; int j; if (!m) { continue; } for (j = 0; j < NUMBER_PATHS; ++j) { gedict_t *from_marker = m->fb.paths[j].next_marker; if (from_marker && (from_marker != world)) { m->fb.paths[j].flags |= CheckReversible(m, from_marker); } } } } static qbool ZoneReverseTimeAdjust(gedict_t *m, gedict_t *m_P, int x, int m_D) { if (m->fb.zones[x].reverse_time > (P_time + m_P->fb.zones[x].reverse_time)) { m->fb.zones[x].reverse_marker = m_P->fb.zones[x].reverse_marker; m->fb.zones[x].reverse_time = P_time + m_P->fb.zones[x].reverse_time; m->fb.zones[x].reverse_next = m_P; return false; } return true; } static qbool Calc_G_time_8_path_apply(gedict_t *m, fb_path_t *path) { qbool no_change = true; gedict_t *m_P = path->next_marker; int m_D = path->flags; int i = 0; if (!m || (m == world) || !m_P || (m_P == world)) { return no_change; } if (m_D & REVERSIBLE) { for (i = 0; i < NUMBER_ZONES; ++i) { no_change &= ZoneReverseTimeAdjust(m, m_P, i, m_D); } } return (qbool)no_change; } static void ZoneSightFromMarkerCalculate(gedict_t *m, gedict_t *m_2, int x) { if (m->fb.zones[x].sight_from_time > m_2->fb.zones[x].from_time) { m->fb.zones[x].sight_from_time = m_2->fb.zones[x].from_time; m->fb.zones[x].sight_from = m_2; } else if (!m_2->fb.zones[x].from_time) { m->fb.zones[x].sight_from = NULL; } } static void ZoneHigherSightFromMarkerCalculate(gedict_t *m, gedict_t *m_2, int x) { if (m->fb.zones[x].higher_sight_from_time > m_2->fb.zones[x].from_time) { m->fb.zones[x].higher_sight_from_time = m_2->fb.zones[x].from_time; m->fb.zones[x].higher_sight_from = m_2; } else if (!m_2->fb.zones[x].from_time) { m->fb.zones[x].higher_sight_from = NULL; } } static void Calc_G_time_9_apply(gedict_t *m, gedict_t *m_2, vec3_t m_pos, vec3_t m2_pos) { int i = 0; for (i = 0; i < NUMBER_ZONES; ++i) { ZoneSightFromMarkerCalculate(m, m_2, i); } if ((m2_pos[2] - m_pos[2]) >= 40) { if (VectorDistance(m2_pos, m_pos) <= 1000) { for (i = 0; i < NUMBER_ZONES; ++i) { ZoneHigherSightFromMarkerCalculate(m, m_2, i); } } } } static void Calc_G_time_9(void) { int i; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; int j; if (!m) { continue; } for (j = 0; j < NUMBER_MARKERS; ++j) { gedict_t *m2 = markers[j]; vec3_t m_pos, m2_pos; if (!m2) { continue; } VectorAdd(m->s.v.absmin, m->s.v.view_ofs, m_pos); m_pos[2] += 32; VectorAdd(m2->s.v.absmin, m2->s.v.view_ofs, m2_pos); m2_pos[2] += 32; traceline(m_pos[0], m_pos[1], m_pos[2], m2_pos[0], m2_pos[1], m2_pos[2], true, world); if (g_globalvars.trace_fraction == 1) { if (strneq(m2->classname, "trigger_teleport")) { Calc_G_time_9_apply(m, m2, m_pos, m2_pos); } } } } } static qbool ZoneMinSightFromTimeCalc(gedict_t *m, gedict_t *m_P, int x, int m_D) { if (m->fb.zones[x].sight_from_time < (m_P->fb.zones[x].sight_from_time - P_time)) { m->fb.zones[x].sight_from_time = m_P->fb.zones[x].sight_from_time - P_time; return false; } return true; } static qbool Calc_G_time_10_path_apply(gedict_t *m, fb_path_t *path) { qbool no_change = true; gedict_t *m_P = path->next_marker; int m_D = path->flags; int i = 0; if (!m || (m == world) || !m_P || (m_P == world)) { return no_change; } for (i = 0; i < NUMBER_ZONES; ++i) { no_change &= ZoneMinSightFromTimeCalc(m, m_P, i, m_D); } return no_change; } static void Calc_G_time_11_apply(gedict_t *m, gedict_t *next_marker) { int i = 0; int found = -1; min_traveltime = min_traveltime + 1.25; runaway_score = runaway_score * 0.125; for (i = 0; i < NUMBER_PATHS; ++i) { if (m->fb.runaway[i].next_marker == next_marker) { if (m->fb.runaway[i].score >= runaway_score) { return; } m->fb.runaway[i].prev_marker = prev_marker; m->fb.runaway[i].score = runaway_score; m->fb.runaway[i].time = runaway_time; found = i; break; } } if (found < 0) { return; } // Sort so highest score is first in array (subsequent indexes don't matter) for (i = found; i > 0; --i) { if (m->fb.runaway[i - 1].score < m->fb.runaway[i].score) { fb_runaway_route_t temp; memcpy(&temp, &m->fb.runaway[i - 1], sizeof(temp)); memcpy(&m->fb.runaway[i - 1], &m->fb.runaway[i], sizeof(temp)); memcpy(&m->fb.runaway[i], &temp, sizeof(temp)); } } } static void Calc_G_time_11(void) { gedict_t *m_zone; int i; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; int zone; if (!m) { continue; } for (zone = 0; zone < NUMBER_ZONES; ++zone) { m_zone = FirstZoneMarker(zone); if (m_zone == NULL) { continue; } from_marker = m; ZoneMarker(m, m_zone, path_normal, false); if ((middle_marker != dropper) && (middle_marker != m)) { gedict_t *runaway_dest = middle_marker; runaway_time = path_normal ? zone_time : zone_time + 5; runaway_score = runaway_time; next_marker = m; min_traveltime = 1.25; do { from_marker = prev_marker = next_marker; next_marker = ZonePathMarker(from_marker, runaway_dest, path_normal, false); from_marker = m; ZoneMarker(m, next_marker, path_normal, false); traveltime = SubZoneArrivalTime(zone_time, middle_marker, next_marker, false); if (traveltime >= min_traveltime) { if (strneq(next_marker->classname, "trigger_teleport")) { Calc_G_time_11_apply(m, next_marker); } } } while (next_marker != runaway_dest); } } } if (path_normal) { path_normal = false; } else { path_normal = true; Calc_G_time_12(); } } static void Calc_G_time_12(void) { gedict_t *runaway_dest; int i; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; vec3_t m_pos; if (!m) { continue; } middle_marker = m; zone_time = 0; VectorAdd(m->s.v.absmin, m->s.v.view_ofs, m_pos); m_pos[2] += 32; for (runaway_dest = m->fb.Z_head; runaway_dest && runaway_dest != world; runaway_dest = runaway_dest->fb.Z_next) { if (runaway_dest != m) { from_marker = m; traveltime = SubZoneArrivalTime(zone_time, middle_marker, runaway_dest, false); if (traveltime < 1000000) { runaway_score = runaway_time = traveltime; next_marker = m; min_traveltime = 1.25; do { from_marker = prev_marker = next_marker; next_marker = SubZoneNextPathMarker(from_marker, runaway_dest); traceline(m_pos[0], m_pos[1], m_pos[2], next_marker->s.v.absmin[0] + next_marker->s.v.view_ofs[0], next_marker->s.v.absmin[1] + next_marker->s.v.view_ofs[1], next_marker->s.v.absmin[2] + next_marker->s.v.view_ofs[2] + 32, true, world); if (g_globalvars.trace_fraction != 1) { from_marker = m; traveltime = SubZoneArrivalTime(zone_time, middle_marker, next_marker, false); if (traveltime >= min_traveltime) { if (strneq(next_marker->classname, "trigger_teleport")) { Calc_G_time_11_apply(m, next_marker); } } } } while (next_marker != runaway_dest); } } } } } // Repeatedly calls func(x, y) until func returns true for every path in the system static void PathCalculation(fb_path_calc_funcref_t func) { qbool no_change = false; while (!no_change) { int i, j; no_change = true; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; if (!m) { continue; } for (j = 0; j < NUMBER_PATHS; ++j) { //no_change &= func(m, m->fb.paths[j].next_marker, m->fb.paths[j].time, m->fb.paths[j].flags); no_change &= func(m, &m->fb.paths[j]); } } } } void InitialiseMarkerRoutes(void) { int i; self = dropper; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t *m = markers[i]; vec3_t point, m_pos; int content; int j = 0; if (!m) { continue; } // Calc_G_time_1: This calculates water columns (if marker is in water, can the player go straight up to get air?) VectorAdd(m->s.v.absmin, m->s.v.view_ofs, m_pos); m->fb.touch_marker = m; VectorCopy(m_pos, point); point[2] += 4; content = trap_pointcontents(PASSVEC3(point)); if (content >= CONTENT_LAVA && content <= CONTENT_WATER) { vec3_t testplace; CheckWaterColumn(m, m_pos, testplace); if (testplace[2] - m_pos[2] > 0) { setsize(m, m->s.v.mins[0], m->s.v.mins[1], m->s.v.mins[2], m->s.v.maxs[0] + testplace[0] - m_pos[0], m->s.v.maxs[1] + testplace[1] - m_pos[1], m->s.v.maxs[2] + testplace[2] - m_pos[2]); } } // Calc_G_time_2 for (j = 0; j < NUMBER_PATHS; ++j) { gedict_t *m_P = m->fb.paths[j].next_marker; if (m_P && m_P->fb.fl_marker) { TravelTimeForPath(m, j); } else { m->fb.paths[j].next_marker = 0; } } for (j = 0; j < NUMBER_GOALS; ++j) { if (!m->fb.goals[j].next_marker) { m->fb.goals[j].rj_time = m->fb.goals[j].time = 1000000; m->fb.goals[j].next_marker_rj = m->fb.goals[j].next_marker = dropper; } } for (j = 0; j < NUMBER_ZONES; ++j) { if (!m->fb.zones[j].marker) { m->fb.zones[j].rj_time = m->fb.zones[j].time = m->fb.zones[j].reverse_time = m->fb.zones[j].from_time = 1000000; m->fb.zones[j].marker_rj = m->fb.zones[j].marker = m->fb.zones[j].reverse_marker = dropper; } m->fb.zones[j].sight_from_time = 1000000; } for (j = 0; j < NUMBER_SUBZONES; ++j) { if (m->fb.S_ != j) { m->fb.subzones[j].rj_time = m->fb.subzones[j].time = 1000000; } } } PathCalculation(IdentifyFastestSubzoneRoute); PathCalculation(IdentifyFastestGoalRoute); PathCalculation(IdentifyFastestZoneRoute); PathCalculation(Calc_G_time_6_path_apply); Calc_G_time_7(); PathCalculation(Calc_G_time_8_path_apply); Calc_G_time_9(); PathCalculation(Calc_G_time_10_path_apply); Calc_G_time_11(); /*{ extern gedict_t* markers[]; int i = 0, j = 0; for (i = 0; i < NUMBER_MARKERS; ++i) { gedict_t* m = markers[i]; if (m) { G_Printf ("M %d %d %d \"%s\" %d %d %d %d %d %d\n", m->fb.index, m->fb.Z_, m->fb.G_, m->classname, PASSINTVEC3 (m->s.v.absmin), PASSINTVEC3 (m->s.v.absmax) ); for (j = 0; j < NUMBER_PATHS; ++j) { if (m->fb.paths[j].next_marker) { G_Printf ("P %d %d %d %d\n", m->fb.index, j, m->fb.paths[j].next_marker->fb.index, m->fb.paths[j].flags); } } } } }*/ return; } #endif QW-Group-ktx-d05d6ca/src/route_fields.c000066400000000000000000000104031475442401000200450ustar00rootroot00000000000000/* route_fields.qc Copyright (C) 1997-1999 Robert 'Frog' Field */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" static int subzone_indexes[NUMBER_ZONES] = { 0 }; // FIXME: Map-specific hack for existing map-specific logic... extern gedict_t *dm6_door; gedict_t* spawn_marker(float x, float y, float z); // FIXME: globals extern gedict_t *markers[]; void SetGoalForMarker(int goal, gedict_t *marker) { if ((goal <= 0) || (goal > NUMBER_GOALS) || (marker == NULL)) { return; } marker->fb.goals[goal - 1].next_marker_rj = marker->fb.goals[goal - 1].next_marker = marker; marker->fb.G_ = goal; } void SetGoal(int goal, int marker_number) { gedict_t *marker = NULL; --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } marker = markers[marker_number]; SetGoalForMarker(goal, marker); } void SetZone(int zone, int marker_number) { gedict_t *marker; fb_zone_t *z; // old frogbot code was 1-based --zone; --marker_number; if ((zone < 0) || (zone >= NUMBER_ZONES)) { return; } if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } marker = markers[marker_number]; if (marker == NULL) { return; } z = &marker->fb.zones[zone]; marker->fb.S_ = subzone_indexes[zone]++; z->marker_rj = z->next_rj = z->marker = z->reverse_marker = z->next = z->reverse_next = marker; marker->fb.Z_ = zone + 1; AddZoneMarker(marker); } void SetMarkerFlag(int marker_number, int flags) { --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } markers[marker_number]->fb.T |= flags; if (flags & MARKER_IS_DM6_DOOR) { dm6_door = markers[marker_number]; } if (flags & (MARKER_IS_DM6_DOOR | MARKER_DOOR_TOUCHABLE)) { markers[marker_number]->s.v.solid = SOLID_TRIGGER; } } void SetMarkerFixedSize(int marker_number, int size_x, int size_y, int size_z) { --marker_number; if ((marker_number < 0) || (marker_number >= NUMBER_MARKERS)) { return; } if (!markers[marker_number]) { return; } VectorSet(markers[marker_number]->fb.fixed_size, size_x, size_y, size_z); } void RemoveMarker(gedict_t *marker) { int i, j; if (!streq(marker->classname, "marker")) { G_sprint(self, 2, "Cannot remove non-marker\n"); return; } for (i = 0; i < NUMBER_MARKERS; ++i) { if (!markers[i]) { continue; } // Remove from linked paths for (j = 0; j < NUMBER_PATHS; ++j) { if (markers[i]->fb.paths[j].next_marker == marker) { markers[i]->fb.paths[j].next_marker = NULL; } } // Remove marker if (markers[i] == marker) { ent_remove(markers[i]); markers[i] = NULL; } } } gedict_t* CreateNewMarker(vec3_t origin) { gedict_t *new_marker = spawn_marker(PASSVEC3(origin)); int i; for (i = 0; i < NUMBER_MARKERS; ++i) { if (markers[i] == NULL) { markers[i] = new_marker; new_marker->fb.index = i; return new_marker; } } AddToQue(new_marker); return new_marker; } void MoveMarker(gedict_t *selected, vec3_t move_to) { //selected-> } qbool CreateNewPath(gedict_t *current, gedict_t *next) { int i; for (i = 0; i < NUMBER_PATHS; ++i) { if (current->fb.paths[i].next_marker == NULL) { current->fb.paths[i].next_marker = next; current->fb.paths[i].flags = 0; current->fb.paths[i].time = 0; return true; } } G_sprint(self, 2, "Source marker already has %d paths, cannot add any more.", NUMBER_PATHS); return false; } void RemovePath(gedict_t *source, int path_number) { if ((path_number < 0) || (path_number >= NUMBER_PATHS)) { return; } source->fb.paths[path_number].flags = 0; source->fb.paths[path_number].next_marker = NULL; source->fb.paths[path_number].time = 0; source->fb.paths[path_number].rj_time = 0; } int AddPath(gedict_t *source, gedict_t *next) { int i = 0; int place = -1; if ((source == NULL) || (next == NULL) || (source == next)) { return -1; } for (i = 0; i < NUMBER_PATHS; ++i) { if (source->fb.paths[i].next_marker == next) { return i; } if (place < 0 && source->fb.paths[i].next_marker == NULL) { place = i; } } if (place >= 0) { source->fb.paths[place].next_marker = next; source->fb.paths[place].flags = 0; source->fb.paths[place].time = 0; source->fb.paths[place].rj_time = 0; } return place; } #endif QW-Group-ktx-d05d6ca/src/route_lookup.c000066400000000000000000000077371475442401000201300ustar00rootroot00000000000000/* route_lookup.qc Copyright (C) 1997-1999 Robert 'Frog' Field */ // Converted from .qc on 05/02/2016 #ifdef BOT_SUPPORT #include "g_local.h" float SubZoneArrivalTime(float zone_time, gedict_t *middle_marker, gedict_t *from_marker, qbool rl_routes) { if (rl_routes) { return (zone_time + middle_marker->fb.subzones[from_marker->fb.S_].rj_time); } else { return (zone_time + middle_marker->fb.subzones[from_marker->fb.S_].time); } } gedict_t* SubZoneNextPathMarker(gedict_t *from_marker, gedict_t *to_marker) { return (from_marker && to_marker ? from_marker->fb.subzones[to_marker->fb.S_].next_marker : NULL); } gedict_t* SightFromMarkerFunction(gedict_t *from_marker, gedict_t *to_marker) { return (to_marker && from_marker && from_marker->fb.Z_ ? to_marker->fb.zones[from_marker->fb.Z_ - 1].sight_from : NULL); } gedict_t* HigherSightFromFunction(gedict_t *from_marker, gedict_t *to_marker) { return (to_marker && from_marker && from_marker->fb.Z_ ? to_marker->fb.zones[from_marker->fb.Z_ - 1].higher_sight_from : NULL); } float SightFromTime(gedict_t *from_marker, gedict_t *to_marker) { return (to_marker && from_marker && from_marker->fb.Z_ ? to_marker->fb.zones[from_marker->fb.Z_ - 1].sight_from_time : 0.0f); } void ZoneMarker(gedict_t *from_marker, gedict_t *to_marker, qbool path_normal, qbool rl_jump_routes) { fb_zone_t *zone; if ((from_marker == NULL) || (to_marker == NULL)) { middle_marker = dropper; zone_time = 1000000; return; } if (!to_marker->fb.Z_) { return; } zone = &from_marker->fb.zones[to_marker->fb.Z_ - 1]; if (path_normal) { middle_marker = rl_jump_routes ? zone->marker_rj : zone->marker; zone_time = rl_jump_routes ? zone->rj_time : zone->time; } else { middle_marker = from_marker->fb.zones[to_marker->fb.Z_ - 1].reverse_marker; zone_time = from_marker->fb.zones[to_marker->fb.Z_ - 1].reverse_time; } } gedict_t* ZonePathMarker(gedict_t *from_marker, gedict_t *to_marker, qbool path_normal, qbool rl_jump_routes) { if ((from_marker == NULL) || (to_marker == NULL) || (to_marker->fb.Z_ == 0)) { return NULL; } if (path_normal) { if (rl_jump_routes) { return from_marker->fb.zones[to_marker->fb.Z_ - 1].next_rj; } return from_marker->fb.zones[to_marker->fb.Z_ - 1].next; } return from_marker->fb.zones[to_marker->fb.Z_ - 1].reverse_next; } // This is called when the standard highersight calculation has failed // Difference in 'higher' is that they must be on different heights (>=40) // Otherwise no difference? // from_marker = zone with all markers to be checked, marker->to_marker must be visible, marker must be higher gedict_t* SightMarker(gedict_t *from_marker, gedict_t *to_marker, float max_distance, float min_height_diff) { gedict_t *marker_; vec3_t marker_pos; vec3_t to_marker_pos; gedict_t *look_marker = NULL; look_traveltime = 1000000; middle_marker = from_marker; zone_time = 0; VectorAdd(to_marker->s.v.absmin, to_marker->s.v.view_ofs, to_marker_pos); to_marker_pos[2] += 32; // Forall markers in this zone... marker_ = from_marker->fb.Z_head; while (marker_) { VectorAdd(marker_->s.v.absmin, marker_->s.v.view_ofs, marker_pos); marker_pos[2] += 32; // Only check markers where this marker is higher than target if ((min_height_diff == 0) || ((marker_pos[2] - to_marker_pos[2]) >= min_height_diff)) { if ((max_distance == 0) || VectorDistance(marker_pos, to_marker_pos) <= max_distance) { // Must be able to draw straight line between the two traceline(PASSVEC3(to_marker_pos), PASSVEC3(marker_pos), true, world); if (g_globalvars.trace_fraction == 1) { // traveltime = SubZoneArrivalTime(zone_time, middle_marker, marker_, false); if (look_traveltime > traveltime) { // Teleports don't count if (strneq(marker_->classname, "trigger_teleport")) { look_traveltime = traveltime; look_marker = marker_; } } } } } marker_ = marker_->fb.Z_next; } return look_marker; } #endif QW-Group-ktx-d05d6ca/src/runes.c000066400000000000000000000246471475442401000165340ustar00rootroot00000000000000/* * $Id$ */ #include "g_local.h" void RegenLostRot(void); void RuneRespawn(void); void RuneTouch(void); void RuneResetOwner(void); char* GetRuneSpawnName(void); void DoDropRune(int rune, qbool on_respawn) { gedict_t *item, *pos = NULL; float movetype = MOVETYPE_NONE; cl_refresh_plus_scores(self); if (on_respawn) { if (rune & CTF_RUNE_RES) { pos = ez_find(world, "item_rune_res"); } else if (rune & CTF_RUNE_STR) { pos = ez_find(world, "item_rune_str"); } else if (rune & CTF_RUNE_HST) { pos = ez_find(world, "item_rune_hst"); } else if (rune & CTF_RUNE_RGN) { pos = ez_find(world, "item_rune_rgn"); } } // No dedicated rune position found, just toss on self if (pos == NULL) { pos = self; if (on_respawn) { // Rune respawn, bounce adds randomization. movetype = (int) cvar("k_ctf_rune_bounce") & 1 ? MOVETYPE_BOUNCE : MOVETYPE_TOSS; } else { // Drop rune due to player died. movetype = MOVETYPE_TOSS; } } item = spawn(); setorigin(item, pos->s.v.origin[0], pos->s.v.origin[1], pos->s.v.origin[2] - 24); item->classname = "rune"; item->ctf_flag = rune; item->s.v.velocity[0] = i_rnd(-100, 100); item->s.v.velocity[1] = i_rnd(-100, 100); item->s.v.velocity[2] = 400; item->s.v.flags = FL_ITEM; item->s.v.solid = SOLID_TRIGGER; item->s.v.movetype = movetype; if (rune & CTF_RUNE_RES) { setmodel(item, "progs/end1.mdl"); } else if (rune & CTF_RUNE_STR) { setmodel(item, "progs/end2.mdl"); } else if (rune & CTF_RUNE_HST) { setmodel(item, "progs/end3.mdl"); } else if (rune & CTF_RUNE_RGN) { setmodel(item, "progs/end4.mdl"); } setsize(item, -16, -16, 0, 16, 16, 56); item->touch = (func_t) RuneTouch; item->s.v.nextthink = g_globalvars.time + 90; item->think = (func_t) RuneRespawn; // qqshka, add spawn sound to rune if rune respawned, not for player dropped from corpse rune if (on_respawn) { sound(item, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM); // play respawn sound } } void DoTossRune(int rune) { gedict_t *item; cl_refresh_plus_scores(self); item = spawn(); item->ctf_flag = rune; item->classname = "rune"; item->s.v.flags = FL_ITEM; item->s.v.solid = SOLID_TRIGGER; item->s.v.movetype = (int) cvar("k_ctf_rune_bounce") & 2 ? MOVETYPE_BOUNCE : MOVETYPE_TOSS; trap_makevectors(self->s.v.v_angle); if (self->s.v.v_angle[0]) { item->s.v.velocity[0] = g_globalvars.v_forward[0] * 300 + g_globalvars.v_up[0] * 200; item->s.v.velocity[1] = g_globalvars.v_forward[1] * 300 + g_globalvars.v_up[1] * 200; item->s.v.velocity[2] = g_globalvars.v_forward[2] * 300 + g_globalvars.v_up[2] * 200; } else { aim(item->s.v.velocity); VectorScale(item->s.v.velocity, 300, item->s.v.velocity); item->s.v.velocity[2] = 200; } if (rune & CTF_RUNE_RES) { setmodel(item, "progs/end1.mdl"); } else if (rune & CTF_RUNE_STR) { setmodel(item, "progs/end2.mdl"); } else if (rune & CTF_RUNE_HST) { setmodel(item, "progs/end3.mdl"); } else if (rune & CTF_RUNE_RGN) { setmodel(item, "progs/end4.mdl"); } setorigin(item, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] - 24); setsize(item, -16, -16, 0, 16, 16, 56); item->s.v.owner = EDICT_TO_PROG(self); item->touch = (func_t) RuneTouch; item->s.v.nextthink = g_globalvars.time + 0.75; item->think = (func_t) RuneResetOwner; } void DropRune(void) { if (self->ctf_flag & CTF_RUNE_RES) { DoDropRune( CTF_RUNE_RES, false); self->ps.res_time += g_globalvars.time - self->rune_pickup_time; } if (self->ctf_flag & CTF_RUNE_STR) { DoDropRune( CTF_RUNE_STR, false); self->ps.str_time += g_globalvars.time - self->rune_pickup_time; } if (self->ctf_flag & CTF_RUNE_HST) { DoDropRune( CTF_RUNE_HST, false); self->ps.hst_time += g_globalvars.time - self->rune_pickup_time; } if (self->ctf_flag & CTF_RUNE_RGN) { DoDropRune( CTF_RUNE_RGN, false); self->ps.rgn_time += g_globalvars.time - self->rune_pickup_time; } self->ctf_flag -= (self->ctf_flag & (CTF_RUNE_MASK)); // self->s.v.items -= ( (int)self->s.v.items & (CTF_RUNE_MASK) ); } void TossRune(void) { if (self->ctf_flag & CTF_RUNE_RES) { DoTossRune( CTF_RUNE_RES); self->ps.res_time += g_globalvars.time - self->rune_pickup_time; } if (self->ctf_flag & CTF_RUNE_STR) { DoTossRune( CTF_RUNE_STR); self->ps.str_time += g_globalvars.time - self->rune_pickup_time; } if (self->ctf_flag & CTF_RUNE_HST) { DoTossRune( CTF_RUNE_HST); self->ps.hst_time += g_globalvars.time - self->rune_pickup_time; self->maxspeed = cvar("sv_maxspeed"); } if (self->ctf_flag & CTF_RUNE_RGN) { gedict_t *regenrot = spawn(); DoTossRune( CTF_RUNE_RGN); self->ps.rgn_time += g_globalvars.time - self->rune_pickup_time; regenrot->s.v.nextthink = g_globalvars.time + 5; regenrot->think = (func_t) RegenLostRot; regenrot->s.v.owner = EDICT_TO_PROG(self); } self->ctf_flag -= (self->ctf_flag & (CTF_RUNE_MASK)); //self->s.v.items -= ( (int)self->s.v.items & (CTF_RUNE_MASK) ); } void RegenLostRot(void) { other = PROG_TO_EDICT(self->s.v.owner); if ((other->s.v.health < 101) || (other->ctf_flag & CTF_RUNE_RGN) || ((int)other->s.v.items & IT_SUPERHEALTH)) { ent_remove(self); return; } other->s.v.health--; self->s.v.nextthink = g_globalvars.time + 1; } void RuneResetOwner(void) { self->s.v.owner = EDICT_TO_PROG(self); self->think = (func_t) RuneRespawn; self->s.v.nextthink = g_globalvars.time + 90; } void RuneRespawn(void) { int rune = self->ctf_flag; ent_remove(self); self = SelectSpawnPoint(GetRuneSpawnName()); DoDropRune(rune, true); } void RuneTouch(void) { if (other->ct != ctPlayer) { return; } if (ISDEAD(other)) { return; } if (!k_practice) { if (match_in_progress != 2) { return; } } if (other == PROG_TO_EDICT(self->s.v.owner)) { return; } if (self->think == (func_t)RuneRespawn) { self->s.v.nextthink = g_globalvars.time + 90; } if (other->ctf_flag & CTF_RUNE_MASK) { if (g_globalvars.time > other->rune_notify_time) { other->rune_notify_time = g_globalvars.time + 10; G_sprint(other, 1, "You already have a rune. Use \"%s\" to drop\n", redtext("tossrune")); } return; } cl_refresh_plus_scores(other); other->ctf_flag |= self->ctf_flag; other->rune_pickup_time = g_globalvars.time; if (other->ctf_flag & CTF_RUNE_RES) { // other->s.v.items = (int)other->s.v.items | IT_SIGIL1; G_sprint(other, 2, "You got the %s rune\n", redtext("resistance")); } if (other->ctf_flag & CTF_RUNE_STR) { // other->s.v.items = (int)other->s.v.items | IT_SIGIL2; G_sprint(other, 2, "You got the %s rune\n", redtext("strength")); } if (other->ctf_flag & CTF_RUNE_HST) { other->maxspeed *= (cvar("k_ctf_rune_power_hst") / 8) + 1; // other->s.v.items = (int)other->s.v.items | CTF_RUNE_HST; G_sprint(other, 2, "You got the %s rune\n", redtext("haste")); } if (other->ctf_flag & CTF_RUNE_RGN) { // other->s.v.items = (int)other->s.v.items | CTF_RUNE_RGN; G_sprint(other, 2, "You got the %s rune\n", redtext("regeneration")); } sound(other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM); stuffcmd(other, "bf\n"); ent_remove(self); } char* GetRuneSpawnName(void) { char *runespawn; if (cvar("k_ctf_based_spawn") == 1) { runespawn = g_random() < 0.5 ? "info_player_team1" : "info_player_team2"; } else { // we'll just use the player spawn point selector for runes as well runespawn = "info_player_deathmatch"; } return runespawn; } // try to find a unique spawn position for a rune given the NULL-terminated // list of other runes gedict_t* UniqueRuneSpawn(int rune_type, int nrunes, gedict_t **runes) { char *spawnname; int i, nspawns; qbool unique; gedict_t *e; spawnname = GetRuneSpawnName(); for (e = world, nspawns = 0; (e = ez_find(e, spawnname)); nspawns++); for (i = 0; i < nspawns; i++) { self = SelectSpawnPoint(spawnname); unique = true; for (i = 0; i < nrunes; i++) { if (runes && self == runes[i]) { unique = false; break; } } if (unique) { DoDropRune(rune_type, true); return self; } } // Unable to find a unique spawn, drop anyway DoDropRune(rune_type, true); return self; } // spawn/remove runes void SpawnRunes(qbool yes) { gedict_t *oself, *e, *runes[4]; int nrunes = 0; for (e = world; (e = find(e, FOFCLSN, "rune"));) { ent_remove(e); } if (!yes) { return; } oself = self; memset(runes, 0, sizeof(runes)); if (cvar("k_ctf_rune_power_res") > 0) { runes[nrunes] = UniqueRuneSpawn(CTF_RUNE_RES, nrunes, runes); nrunes++; } if (cvar("k_ctf_rune_power_str") > 0) { runes[nrunes] = UniqueRuneSpawn(CTF_RUNE_STR, nrunes, runes); nrunes++; } if (cvar("k_ctf_rune_power_hst") > 0) { runes[nrunes] = UniqueRuneSpawn(CTF_RUNE_HST, nrunes, runes); nrunes++; } if (cvar("k_ctf_rune_power_rgn") > 0) { UniqueRuneSpawn(CTF_RUNE_RGN, nrunes, runes); } self = oself; } void ResistanceSound(gedict_t *player) { if (player->ctf_flag & CTF_RUNE_RES) { if (player->rune_sound_time < g_globalvars.time) { player->rune_sound_time = g_globalvars.time + 1; sound(player, CHAN_ITEM, "rune/rune1.wav", 1, ATTN_NORM); } } } void HasteSound(gedict_t *player) { if (player->ctf_flag & CTF_RUNE_HST) { if (player->rune_sound_time < g_globalvars.time) { player->rune_sound_time = g_globalvars.time + 1; sound(player, CHAN_ITEM, "rune/rune3.wav", 1, ATTN_NORM); } } } void RegenerationSound(gedict_t *player) { if (player->ctf_flag & CTF_RUNE_RGN) { if (player->rune_sound_time < g_globalvars.time) { player->rune_sound_time = g_globalvars.time + 1; sound(player, CHAN_ITEM, "rune/rune4.wav", 1, ATTN_NORM); } } } void CheckStuffRune(void) { char *rune = ""; if (cvar("k_instagib")) { if (self->i_agmr) { self->items2 = (int)self->items2 | (CTF_RUNE_RES << 5); return; } } if (!isCTF()) { self->items2 = 0; // no runes/sigils in HUD if (self->last_rune && iKey(self, "runes")) { self->last_rune = NULL; stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "set rune \"\"\n"); } return; } self->items2 = (self->ctf_flag & CTF_RUNE_MASK) << 5; if (!iKey(self, "runes")) { return; } if (self->ctf_flag & CTF_RUNE_RES) { rune = "res"; } else if (self->ctf_flag & CTF_RUNE_STR) { rune = "str"; } else if (self->ctf_flag & CTF_RUNE_HST) { rune = "hst"; } else if (self->ctf_flag & CTF_RUNE_RGN) { rune = "rgn"; } else { rune = ""; } if (!self->last_rune || strneq(rune, self->last_rune)) { self->last_rune = rune; stuffcmd_flags(self, STUFFCMD_IGNOREINDEMO, "set rune \"%s\"\n", rune); } } QW-Group-ktx-d05d6ca/src/server.c000066400000000000000000000056671475442401000167070ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" /* ============================================================================== MOVETARGET CODE The angle of the movetarget effects standing and bowing direction, but has no effect on movement, which allways heads to the next target. targetname must be present. The name of this movetarget. target the next spot to move to. If not present, stop here for good. pausetime The number of seconds to spend standing or bowing for path_stand or path_bow ============================================================================== */ /* ============= t_movetarget Something has bumped into a movetarget. If it is a monster moving towards it, change the next destination and continue. ============== */ void t_movetarget(void) { gedict_t *temp; vec3_t tmpv; if (other->movetarget != self) { return; } if (other->s.v.enemy) { return; // fighting, not following a path } temp = self; self = other; other = temp; if (streq(self->classname, "monster_ogre")) { sound(self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE); // play chainsaw drag sound } // dprint ("t_movetarget\n"); if (other->target) { self->movetarget = find(world, FOFS(targetname), other->target); } else { self->movetarget = NULL; } if (!self->movetarget) // NOTE: this is a damn difference with qc { self->movetarget = world; } self->s.v.goalentity = EDICT_TO_PROG(self->movetarget); VectorSubtract(self->movetarget->s.v.origin, self->s.v.origin, tmpv); self->s.v.ideal_yaw = vectoyaw(tmpv); if (!self->movetarget || (self->movetarget == world)) { self->pausetime = g_globalvars.time + 999999; if (self->th_stand) { self->th_stand(); //monster code } return; } } void movetarget_f(void) { if (!self->targetname) { G_Error("monster_movetarget: no targetname"); } self->s.v.solid = SOLID_TRIGGER; self->touch = (func_t) t_movetarget; setsize(self, -8, -8, -8, 8, 8, 8); } /*QUAKED path_corner (0.5 0.3 0) (-8 -8 -8) (8 8 8) Monsters will continue walking towards the next target corner. */ void SP_path_corner(void) { movetarget_f(); } QW-Group-ktx-d05d6ca/src/sp_ai.c000066400000000000000000000470761475442401000164740ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ #include "g_local.h" /* .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 its path. .huntt_ime 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 its stand state and head towards its .movetarget when time > .pausetime. walkmove(angle, speed) primitive is all or nothing */ // // globals // // when a monster becomes angry at a player, that monster will be used // as the sight target the next frame so that monsters near that one // will wake up even if they wouldn't have noticed the player // static gedict_t *sight_entity; static float sight_entity_time; static float movedist; float enemy_vis, enemy_infront, enemy_range; float enemy_yaw; //============================================================================ /* ============= range 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 ============= */ float range(gedict_t *targ) { vec3_t spot1, spot2, org; float r; VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); VectorSubtract(spot1, spot2, org); r = vlen(org); if (r < 120) { return RANGE_MELEE; } if (r < 500) { return RANGE_NEAR; } if (r < 1000) { return RANGE_MID; } // so monsters notice player father/faster in bloodfest mode. if (k_bloodfest) { return RANGE_MID; } return RANGE_FAR; } /* ============= visible returns 1 if the entity is visible to self, even if not infront (void) ============= */ float visible(gedict_t *targ) { vec3_t spot1, spot2; VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); traceline(PASSVEC3(spot1), PASSVEC3(spot2), true, self); // see through other monsters if (g_globalvars.trace_inopen && g_globalvars.trace_inwater) { return false; // sight line crossed contents } if (g_globalvars.trace_fraction == 1) { return true; } return false; } /* ============= infront returns 1 if the entity is in front (in sight) of self ============= */ float infront(gedict_t *targ) { vec3_t vec; float dot; trap_makevectors(self->s.v.angles); VectorSubtract(targ->s.v.origin, self->s.v.origin, vec); VectorNormalize(vec); dot = DotProduct(vec, g_globalvars.v_forward); if (dot > 0.3) { return true; } return false; } //============================================================================ /* in nightmare mode, all attack_finished times become 0 some monsters refire twice automatically */ void SUB_AttackFinished(float normal) { self->cnt = 0; // refire count for nightmare if (skill != 3) { self->attack_finished = g_globalvars.time + normal; } } void SUB_CheckRefire(func_t thinkst) { if (skill != 3) { return; } if (self->cnt == 1) { return; } if (!visible(PROG_TO_EDICT(self->s.v.enemy))) { return; } self->cnt = 1; self->think = thinkst; } //============================================================================ void HuntTarget(void) { vec3_t tmpv; self->s.v.goalentity = self->s.v.enemy; self->think = (func_t) self->th_run; VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, tmpv); self->s.v.ideal_yaw = vectoyaw(tmpv); self->s.v.nextthink = g_globalvars.time + 0.1; SUB_AttackFinished(1); // wait a while before first attack } void SightSound(void) { if (streq(self->classname, "monster_ogre")) { sound(self, CHAN_VOICE, "ogre/ogwake.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_knight")) { sound(self, CHAN_VOICE, "knight/ksight.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_shambler")) { sound(self, CHAN_VOICE, "shambler/ssight.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_demon1")) { sound(self, CHAN_VOICE, "demon/sight2.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_wizard")) { sound(self, CHAN_VOICE, "wizard/wsight.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_zombie")) { sound(self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_dog")) { sound(self, CHAN_VOICE, "dog/dsight.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_hell_knight")) { sound(self, CHAN_VOICE, "hknight/sight1.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_tarbaby")) { sound(self, CHAN_VOICE, "blob/sight1.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_vomit")) { sound(self, CHAN_VOICE, "vomitus/v_sight1.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_enforcer")) { float rsnd = Q_rint(g_random() * 3); if (rsnd == 1) { sound(self, CHAN_VOICE, "enforcer/sight1.wav", 1, ATTN_NORM); } else if (rsnd == 2) { sound(self, CHAN_VOICE, "enforcer/sight2.wav", 1, ATTN_NORM); } else if (rsnd == 0) { sound(self, CHAN_VOICE, "enforcer/sight3.wav", 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, "enforcer/sight4.wav", 1, ATTN_NORM); } } else if (streq(self->classname, "monster_army")) { sound(self, CHAN_VOICE, "soldier/sight1.wav", 1, ATTN_NORM); } else if (streq(self->classname, "monster_shalrath")) { sound(self, CHAN_VOICE, "shalrath/sight.wav", 1, ATTN_NORM); } } void FoundTarget(void) { if (PROG_TO_EDICT(self->s.v.enemy)->ct == ctPlayer) { // let other monsters see this monster for a while sight_entity = self; sight_entity_time = g_globalvars.time; } self->show_hostile = g_globalvars.time + 1; // wake up other monsters SightSound(); HuntTarget(); } /* =========== FindTarget 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. ============ */ float FindTarget(void) { gedict_t *client = NULL; // if the first spawnflag bit is set, the monster will only wake up on // really seeing the player, not another monster getting angry // spawnflags & 3 is a big hack, because zombie crucified used the first // spawn flag prior to the ambush flag, and I forgot about it, so the second // spawn flag works as well if (((sight_entity_time + 0.1) >= g_globalvars.time) && !((int)self->s.v.spawnflags & 3)) { client = sight_entity; // NOTE: may be NULL, so be careful if (!client || (client == world)) { return false; } if (client->s.v.enemy == self->s.v.enemy) { return false; // not sure I understand this, both have same enemy? } } else { client = checkclient(); if (!client || (client == world)) { return false; // current check entity isn't in PVS } } if (client == PROG_TO_EDICT(self->s.v.enemy)) { return false; } if ((int)client->s.v.flags & FL_NOTARGET) { return false; } if ((int)client->s.v.items & IT_INVISIBILITY) { return false; } // in bloodfest mode monsters spot players always. if (!k_bloodfest) { float r = range(client); if (r == RANGE_FAR) { return false; } if (!visible(client)) { return false; } if (r == RANGE_NEAR) { if ((client->show_hostile < g_globalvars.time) && !infront(client)) { return false; } } else if (r == RANGE_MID) { if ( /* client->show_hostile < g_globalvars.time || */!infront(client)) { return false; } } } // // got one // self->s.v.enemy = EDICT_TO_PROG(client); if ((PROG_TO_EDICT(self->s.v.enemy)->ct != ctPlayer) || ((int)PROG_TO_EDICT(self->s.v.enemy)->s.v.flags & FL_NOTARGET)) { self->s.v.enemy = PROG_TO_EDICT(self->s.v.enemy)->s.v.enemy; if ((PROG_TO_EDICT(self->s.v.enemy)->ct != ctPlayer) || ((int)PROG_TO_EDICT(self->s.v.enemy)->s.v.flags & FL_NOTARGET)) { self->s.v.enemy = EDICT_TO_PROG(world); return false; } } FoundTarget(); return true; } //============================================================================= /* ============= GetMadAtAttacker T_Damage calls this when a monster is hurt ============= */ void GetMadAtAttacker(gedict_t *attacker) { if (!attacker || (attacker == world)) { return; // ignore world attacks } if (k_bloodfest && (attacker->ct != ctPlayer)) { return; // in bloodfest mode get mad only on players. } if (attacker == self) { return; // do not mad on self. } if (attacker == PROG_TO_EDICT(self->s.v.enemy)) { return; // alredy mad on this. } // get mad unless of the same class (except for soldiers) if (streq(self->classname, attacker->classname) && strneq(self->classname, "monster_army")) { return; } // OK, we are MAD! // remember current enemy if it was "player enemy", later we restore it if (PROG_TO_EDICT(self->s.v.enemy)->ct == ctPlayer) { self->oldenemy = PROG_TO_EDICT(self->s.v.enemy); } // set new enemy self->s.v.enemy = EDICT_TO_PROG(attacker); FoundTarget(); } //============================================================================= /* ============= ai_melee ============= */ void ai_melee(void) { vec3_t delta; float ldmg; if (!self->s.v.enemy) { return; // removed before stroke } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 60) { return; } ldmg = (g_random() + g_random() + g_random()) * 3; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); } void ai_melee_side(void) { vec3_t delta; float ldmg; if (!self->s.v.enemy) { return; // removed before stroke } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 60) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } ldmg = (g_random() + g_random() + g_random()) * 3; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); } //============================================================================= void ai_forward(float dist) { walkmove(self, self->s.v.angles[1], dist); } void ai_back(float dist) { walkmove(self, self->s.v.angles[1] + 180, dist); } /* ============= ai_pain stagger back a bit ============= */ void ai_pain(float dist) { ai_back(dist); /* float away; away = anglemod (vectoyaw (self.origin - self.enemy.origin) + 180*(g_random()- 0.5) ); walkmove (away, dist); */ } /* ============= ai_painforward stagger back a bit ============= */ void ai_painforward(float dist) { walkmove(self, self->s.v.ideal_yaw, dist); } /* ============= ai_walk The monster is walking its beat ============= */ void ai_walk(float dist) { movedist = dist; if (streq(self->classname, "monster_dragon")) { movetogoal(dist); return; } // check for noticing a player if (FindTarget()) { return; } movetogoal(dist); } /* ============= ai_stand The monster is staying in one place for a while, with slight angle turns ============= */ void ai_stand(void) { if (FindTarget()) { return; } if (g_globalvars.time > self->pausetime) { if (self->th_walk) { self->th_walk(); } return; } // change angle slightly } /* ============= ai_turn don't move, but turn towards ideal_yaw ============= */ void ai_turn(void) { if (FindTarget()) { return; } changeyaw(self); } /* ============ FacingIdeal ============ */ float FacingIdeal(void) { float delta; delta = anglemod(self->s.v.angles[1] - self->s.v.ideal_yaw); if ((delta > 45) && (delta < 315)) { return false; } return true; } //============================================================================= /* ============= ai_face Stay facing the enemy ============= */ void ai_face(void) { vec3_t tmpv; VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, tmpv); self->s.v.ideal_yaw = vectoyaw(tmpv); changeyaw(self); } /* ============= ai_charge The monster is in a melee attack, so get as close as possible to .enemy ============= */ void ai_charge(float d) { if (k_bloodfest) { if ((int)self->s.v.flags & FL_SWIM) { d *= 5; // let fish swim faster in bloodfest mode. } else if (self->bloodfest_boss) { d *= 2; // let boss move faster } } ai_face(); movetogoal(d); // done in C code... } void ai_charge_side(void) { vec3_t tmpv; float heading; // aim to the left of the enemy for a flyby VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, tmpv); self->s.v.ideal_yaw = vectoyaw(tmpv); changeyaw(self); trap_makevectors(self->s.v.angles); VectorMA( PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, -30, g_globalvars.v_right, tmpv); VectorSubtract(tmpv, self->s.v.origin, tmpv); heading = vectoyaw(tmpv); walkmove(self, heading, 20); } //============================================================================= /* =========== CheckAttack The player is in view, so decide to move or launch an attack Returns false if movement should continue ============ */ float CheckAttack(void) { vec3_t spot1, spot2; gedict_t *targ; float chance; targ = PROG_TO_EDICT(self->s.v.enemy); // see if any entities are in the way of the shot VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); traceline(PASSVEC3(spot1), PASSVEC3(spot2), false, self); if (PROG_TO_EDICT(g_globalvars.trace_ent) != targ) { return false; // don't have a clear shot } if (g_globalvars.trace_inopen && g_globalvars.trace_inwater) { return false; // sight line crossed contents } if (enemy_range == RANGE_MELEE) { // melee attack if (self->th_melee) { self->th_melee(); return true; } } // missile attack if (!self->th_missile) { return false; } if (g_globalvars.time < self->attack_finished) { return false; } if (enemy_range == RANGE_FAR) { return false; } if (enemy_range == RANGE_MELEE) { chance = 0.9; self->attack_finished = 0; } else if (enemy_range == RANGE_NEAR) { if (self->th_melee) { chance = 0.2; } else { chance = 0.4; } } else if (enemy_range == RANGE_MID) { if (self->th_melee) { chance = 0.05; } else { chance = 0.1; } } else chance = 0; if (g_random() < chance) { if (self->th_missile) { self->th_missile(); } SUB_AttackFinished(2 * g_random()); return true; } return false; } float CheckAnyAttack(void) { if (!enemy_vis) { return false; } if (streq(self->classname, "monster_dog")) { return DogCheckAttack(); } if (streq(self->classname, "monster_army")) { return SoldierCheckAttack(); } if (streq(self->classname, "monster_ogre")) { return OgreCheckAttack(); } if (streq(self->classname, "monster_shambler")) { return ShamCheckAttack(); } if (streq(self->classname, "monster_demon1")) { return DemonCheckAttack(); } if (streq(self->classname, "monster_wizard")) { return WizardCheckAttack(); } return CheckAttack(); } /* ============= ai_run_melee Turn and close until within an angle to launch a melee attack ============= */ void ai_run_melee(void) { self->s.v.ideal_yaw = enemy_yaw; changeyaw(self); if (FacingIdeal()) { if (self->th_melee) { self->th_melee(); } self->attack_state = AS_STRAIGHT; } } /* ============= ai_run_missile Turn in place until within an angle to launch a missile attack ============= */ void ai_run_missile(void) { self->s.v.ideal_yaw = enemy_yaw; changeyaw(self); if (FacingIdeal()) { if (self->th_missile) { self->th_missile(); } self->attack_state = AS_STRAIGHT; } } /* ============= ai_run_slide Strafe sideways, but stay at aproximately the same range ============= */ void ai_run_slide(void) { float ofs; self->s.v.ideal_yaw = enemy_yaw; changeyaw(self); if (self->lefty) { ofs = 90; } else { ofs = -90; } if (walkmove(self, self->s.v.ideal_yaw + ofs, movedist)) { return; } self->lefty = 1 - self->lefty; walkmove(self, self->s.v.ideal_yaw - ofs, movedist); } /* ============= ai_run The monster has an enemy it is trying to kill ============= */ void ai_run(float dist) { vec3_t tmpv; if (k_bloodfest) { if ((int)self->s.v.flags & FL_SWIM) { dist *= 5; // let fish swim faster in bloodfest mode. } else if (self->bloodfest_boss) { dist *= 2; // let boss move faster } } movedist = dist; // see if the enemy is dead if (ISDEAD(PROG_TO_EDICT(self->s.v.enemy)) || ((int)PROG_TO_EDICT(self->s.v.enemy)->s.v.flags & FL_NOTARGET)) { self->s.v.enemy = EDICT_TO_PROG(world); // FIXME: look all around for other targets if (self->oldenemy && ISLIVE(self->oldenemy) && !((int)self->oldenemy->s.v.flags & FL_NOTARGET)) { self->s.v.enemy = EDICT_TO_PROG(self->oldenemy); HuntTarget(); } else { if (!self->movetarget || (self->movetarget == world)) { if (self->th_stand) { self->th_stand(); } } else { if (self->th_walk) { self->th_walk(); } } return; } } self->show_hostile = g_globalvars.time + 1; // wake up other monsters // check knowledge of enemy enemy_vis = visible(PROG_TO_EDICT(self->s.v.enemy)); if (enemy_vis) { self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds } // look for other coop players if (coop && self->search_time < g_globalvars.time) { if (FindTarget()) { // this is fix for too frequent enemy sighting, required for bloodfest mode. if (!visible(PROG_TO_EDICT(self->s.v.enemy))) { self->search_time = g_globalvars.time + 5; // does not search for enemy next 5 seconds } return; } } enemy_infront = infront(PROG_TO_EDICT(self->s.v.enemy)); enemy_range = range(PROG_TO_EDICT(self->s.v.enemy)); VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, tmpv); enemy_yaw = vectoyaw(tmpv); if (self->attack_state == AS_MISSILE) { //dprint ("ai_run_missile\n"); ai_run_missile(); return; } if (self->attack_state == AS_MELEE) { //dprint ("ai_run_melee\n"); ai_run_melee(); return; } if (CheckAnyAttack()) { return; // beginning an attack } if (self->attack_state == AS_SLIDING) { ai_run_slide(); return; } // head straight in movetogoal(dist); // done in C code... } QW-Group-ktx-d05d6ca/src/sp_boss.c000066400000000000000000000412221475442401000170340ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== BOSS-ONE ============================================================================== */ #include "g_local.h" enum { rise1, rise2, rise3, rise4, rise5, rise6, rise7, rise8, rise9, rise10, rise11, rise12, rise13, rise14, rise15, rise16, rise17, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, walk17, walk18, walk19, walk20, walk21, walk22, walk23, walk24, walk25, walk26, walk27, walk28, walk29, walk30, walk31, death1, death2, death3, death4, death5, death6, death7, death8, death9, attack1, attack2, attack3, attack4, attack5, attack6, attack7, attack8, attack9, attack10, attack11, attack12, attack13, attack14, attack15, attack16, attack17, attack18, attack19, attack20, attack21, attack22, attack23, shocka1, shocka2, shocka3, shocka4, shocka5, shocka6, shocka7, shocka8, shocka9, shocka10, shockb1, shockb2, shockb3, shockb4, shockb5, shockb6, shockc1, shockc2, shockc3, shockc4, shockc5, shockc6, shockc7, shockc8, shockc9, shockc10, }; void boss_rise1(void); void boss_rise2(void); void boss_rise3(void); void boss_rise4(void); void boss_rise5(void); void boss_rise6(void); void boss_rise7(void); void boss_rise8(void); void boss_rise9(void); void boss_rise10(void); void boss_rise11(void); void boss_rise12(void); void boss_rise13(void); void boss_rise14(void); void boss_rise15(void); void boss_rise16(void); void boss_rise17(void); void boss_idle1(void); void boss_idle2(void); void boss_idle3(void); void boss_idle4(void); void boss_idle5(void); void boss_idle6(void); void boss_idle7(void); void boss_idle8(void); void boss_idle9(void); void boss_idle10(void); void boss_idle11(void); void boss_idle12(void); void boss_idle13(void); void boss_idle14(void); void boss_idle15(void); void boss_idle16(void); void boss_idle17(void); void boss_idle18(void); void boss_idle19(void); void boss_idle20(void); void boss_idle21(void); void boss_idle22(void); void boss_idle23(void); void boss_idle24(void); void boss_idle25(void); void boss_idle26(void); void boss_idle27(void); void boss_idle28(void); void boss_idle29(void); void boss_idle30(void); void boss_idle31(void); void boss_missile1(void); void boss_missile2(void); void boss_missile3(void); void boss_missile4(void); void boss_missile5(void); void boss_missile6(void); void boss_missile7(void); void boss_missile8(void); void boss_missile9(void); void boss_missile10(void); void boss_missile11(void); void boss_missile12(void); void boss_missile13(void); void boss_missile14(void); void boss_missile15(void); void boss_missile16(void); void boss_missile17(void); void boss_missile18(void); void boss_missile19(void); void boss_missile20(void); void boss_missile21(void); void boss_missile22(void); void boss_missile23(void); void boss_shocka1(void); void boss_shocka2(void); void boss_shocka3(void); void boss_shocka4(void); void boss_shocka5(void); void boss_shocka6(void); void boss_shocka7(void); void boss_shocka8(void); void boss_shocka9(void); void boss_shocka10(void); void boss_shockb1(void); void boss_shockb2(void); void boss_shockb3(void); void boss_shockb4(void); void boss_shockb5(void); void boss_shockb6(void); void boss_shockb7(void); void boss_shockb8(void); void boss_shockb9(void); void boss_shockb10(void); void boss_shockc1(void); void boss_shockc2(void); void boss_shockc3(void); void boss_shockc4(void); void boss_shockc5(void); void boss_shockc6(void); void boss_shockc7(void); void boss_shockc8(void); void boss_shockc9(void); void boss_shockc10(void); void boss_death1(void); void boss_death2(void); void boss_death3(void); void boss_death4(void); void boss_death5(void); void boss_death6(void); void boss_death7(void); void boss_death8(void); void boss_death9(void); void boss_death10(void); //============================================================================= ANIM(boss_rise1, rise1, boss_rise2; sound( self, CHAN_WEAPON, "boss1/out1.wav", 1, ATTN_NORM);) ANIM(boss_rise2, rise2, boss_rise3; sound( self, CHAN_VOICE, "boss1/sight1.wav", 1, ATTN_NORM);) ANIM(boss_rise3, rise3, boss_rise4;) ANIM(boss_rise4, rise4, boss_rise5;) ANIM(boss_rise5, rise5, boss_rise6;) ANIM(boss_rise6, rise6, boss_rise7;) ANIM(boss_rise7, rise7, boss_rise8;) ANIM(boss_rise8, rise8, boss_rise9;) ANIM(boss_rise9, rise9, boss_rise10;) ANIM(boss_rise10, rise10, boss_rise11;) ANIM(boss_rise11, rise11, boss_rise12;) ANIM(boss_rise12, rise12, boss_rise13;) ANIM(boss_rise13, rise13, boss_rise14;) ANIM(boss_rise14, rise14, boss_rise15;) ANIM(boss_rise15, rise15, boss_rise16;) ANIM(boss_rise16, rise16, boss_rise17;) ANIM(boss_rise17, rise17, boss_missile1;) void boss_face(void) { gedict_t *e = PROG_TO_EDICT(self->s.v.enemy); // go for another player if multi player if ((e == world) || ISDEAD(e) || (g_random() < 0.02)) { // FIXME: search alive players... but its minor, since on next frame boss start searching for new player if (!(e = find_plr(e))) // first attempt { e = find_plr(world); // last resort } e = (e ? e : world); self->s.v.enemy = EDICT_TO_PROG(e); } ai_face(); } void _boss_idle1(void) { boss_face(); if (ISLIVE(PROG_TO_EDICT(self->s.v.enemy))) { boss_missile1(); } } ANIM(boss_idle1, walk1, boss_idle2; _boss_idle1();) ANIM(boss_idle2, walk2, boss_idle3; boss_face();) ANIM(boss_idle3, walk3, boss_idle4; boss_face();) ANIM(boss_idle4, walk4, boss_idle5; boss_face();) ANIM(boss_idle5, walk5, boss_idle6; boss_face();) ANIM(boss_idle6, walk6, boss_idle7; boss_face();) ANIM(boss_idle7, walk7, boss_idle8; boss_face();) ANIM(boss_idle8, walk8, boss_idle9; boss_face();) ANIM(boss_idle9, walk9, boss_idle10; boss_face();) ANIM(boss_idle10, walk10, boss_idle11; boss_face();) ANIM(boss_idle11, walk11, boss_idle12; boss_face();) ANIM(boss_idle12, walk12, boss_idle13; boss_face();) ANIM(boss_idle13, walk13, boss_idle14; boss_face();) ANIM(boss_idle14, walk14, boss_idle15; boss_face();) ANIM(boss_idle15, walk15, boss_idle16; boss_face();) ANIM(boss_idle16, walk16, boss_idle17; boss_face();) ANIM(boss_idle17, walk17, boss_idle18; boss_face();) ANIM(boss_idle18, walk18, boss_idle19; boss_face();) ANIM(boss_idle19, walk19, boss_idle20; boss_face();) ANIM(boss_idle20, walk20, boss_idle21; boss_face();) ANIM(boss_idle21, walk21, boss_idle22; boss_face();) ANIM(boss_idle22, walk22, boss_idle23; boss_face();) ANIM(boss_idle23, walk23, boss_idle24; boss_face();) ANIM(boss_idle24, walk24, boss_idle25; boss_face();) ANIM(boss_idle25, walk25, boss_idle26; boss_face();) ANIM(boss_idle26, walk26, boss_idle27; boss_face();) ANIM(boss_idle27, walk27, boss_idle28; boss_face();) ANIM(boss_idle28, walk28, boss_idle29; boss_face();) ANIM(boss_idle29, walk29, boss_idle30; boss_face();) ANIM(boss_idle30, walk30, boss_idle31; boss_face();) ANIM(boss_idle31, walk31, boss_idle1; boss_face();) extern void T_MissileTouch(void); void boss_missile(float p_x, float p_y, float p_z) { vec3_t offang; vec3_t org, vec, d; float t; VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, offang); vectoangles(offang, offang); trap_makevectors(offang); //org = self->s.v.origin + p[0]*v_forward + p[1]*v_right + p[2]*'0 0 1'; VectorMA(self->s.v.origin, p_x, g_globalvars.v_forward, org); VectorMA(org, p_y, g_globalvars.v_right, org); org[2] += p_z; // lead the player on hard mode if (skill > 1) { VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, org, vec); t = vlen(vec) / 300; VectorCopy(PROG_TO_EDICT(self->s.v.enemy)->s.v.velocity, vec); vec[2] = 0; VectorMA( PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, t, vec, d); } else { VectorCopy(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, d); } VectorSubtract(d, org, vec); normalize(vec, vec); launch_spike(org, vec); setmodel(newmis, "progs/lavaball.mdl"); SetVector(newmis->s.v.avelocity, 200, 100, 300); setsize(newmis, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); VectorScale(vec, 300, newmis->s.v.velocity); newmis->touch = (func_t) T_MissileTouch; // rocket explosion sound(self, CHAN_WEAPON, "boss1/throw.wav", 1, ATTN_NORM); // check for dead enemy if (ISDEAD(PROG_TO_EDICT(self->s.v.enemy))) { boss_idle1(); } } ANIM(boss_missile1, attack1, boss_missile2; boss_face();) ANIM(boss_missile2, attack2, boss_missile3; boss_face();) ANIM(boss_missile3, attack3, boss_missile4; boss_face();) ANIM(boss_missile4, attack4, boss_missile5; boss_face();) ANIM(boss_missile5, attack5, boss_missile6; boss_face();) ANIM(boss_missile6, attack6, boss_missile7; boss_face();) ANIM(boss_missile7, attack7, boss_missile8; boss_face();) ANIM(boss_missile8, attack8, boss_missile9; boss_face();) ANIM(boss_missile9, attack9, boss_missile10; boss_missile( 100, 100, 200 );) ANIM(boss_missile10, attack10, boss_missile11; boss_face();) ANIM(boss_missile11, attack11, boss_missile12; boss_face();) ANIM(boss_missile12, attack12, boss_missile13; boss_face();) ANIM(boss_missile13, attack13, boss_missile14; boss_face();) ANIM(boss_missile14, attack14, boss_missile15; boss_face();) ANIM(boss_missile15, attack15, boss_missile16; boss_face();) ANIM(boss_missile16, attack16, boss_missile17; boss_face();) ANIM(boss_missile17, attack17, boss_missile18; boss_face();) ANIM(boss_missile18, attack18, boss_missile19; boss_face();) ANIM(boss_missile19, attack19, boss_missile20; boss_face();) ANIM(boss_missile20, attack20, boss_missile21; boss_missile( 100, -100, 200 );) ANIM(boss_missile21, attack21, boss_missile22; boss_face();) ANIM(boss_missile22, attack22, boss_missile23; boss_face();) ANIM(boss_missile23, attack23, boss_missile1; boss_face();) ANIM(boss_shocka1, shocka1, boss_shocka2;) ANIM(boss_shocka2, shocka2, boss_shocka3;) ANIM(boss_shocka3, shocka3, boss_shocka4;) ANIM(boss_shocka4, shocka4, boss_shocka5;) ANIM(boss_shocka5, shocka5, boss_shocka6;) ANIM(boss_shocka6, shocka6, boss_shocka7;) ANIM(boss_shocka7, shocka7, boss_shocka8;) ANIM(boss_shocka8, shocka8, boss_shocka9;) ANIM(boss_shocka9, shocka9, boss_shocka10;) ANIM(boss_shocka10, shocka10, boss_missile1;) ANIM(boss_shockb1, shockb1, boss_shockb2;) ANIM(boss_shockb2, shockb2, boss_shockb3;) ANIM(boss_shockb3, shockb3, boss_shockb4;) ANIM(boss_shockb4, shockb4, boss_shockb5;) ANIM(boss_shockb5, shockb5, boss_shockb6;) ANIM(boss_shockb6, shockb6, boss_shockb7;) ANIM(boss_shockb7, shockb1, boss_shockb8;) ANIM(boss_shockb8, shockb2, boss_shockb9;) ANIM(boss_shockb9, shockb3, boss_shockb10;) ANIM(boss_shockb10, shockb4, boss_missile1;) ANIM(boss_shockc1, shockc1, boss_shockc2;) ANIM(boss_shockc2, shockc2, boss_shockc3;) ANIM(boss_shockc3, shockc3, boss_shockc4;) ANIM(boss_shockc4, shockc4, boss_shockc5;) ANIM(boss_shockc5, shockc5, boss_shockc6;) ANIM(boss_shockc6, shockc6, boss_shockc7;) ANIM(boss_shockc7, shockc7, boss_shockc8;) ANIM(boss_shockc8, shockc8, boss_shockc9;) ANIM(boss_shockc9, shockc9, boss_shockc10;) ANIM(boss_shockc10, shockc10, boss_death1;) void _boss_death9(void) { sound(self, CHAN_BODY, "boss1/out1.wav", 1, ATTN_NORM); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_LAVASPLASH); WriteCoord( MSG_BROADCAST, self->s.v.origin[0]); WriteCoord( MSG_BROADCAST, self->s.v.origin[1]); WriteCoord( MSG_BROADCAST, self->s.v.origin[2]); } void _boss_death10(void) { g_globalvars.killed_monsters++; WriteByte( MSG_ALL, SVC_KILLEDMONSTER); // FIXME: reliable broadcast SUB_UseTargets(); ent_remove(self); } ANIM(boss_death1, death1, boss_death2; sound( self, CHAN_VOICE, "boss1/death.wav", 1, ATTN_NORM );) ANIM(boss_death2, death2, boss_death3;) ANIM(boss_death3, death3, boss_death4;) ANIM(boss_death4, death4, boss_death5;) ANIM(boss_death5, death5, boss_death6;) ANIM(boss_death6, death6, boss_death7;) ANIM(boss_death7, death7, boss_death8;) ANIM(boss_death8, death8, boss_death9;) ANIM(boss_death9, death9, boss_death10; _boss_death9();) ANIM(boss_death10, death9, boss_death10; _boss_death10();) void boss_awake(void) { self->s.v.solid = SOLID_SLIDEBOX; self->s.v.movetype = MOVETYPE_STEP; self->s.v.takedamage = DAMAGE_NO; setmodel(self, "progs/boss.mdl"); setsize(self, -128, -128, -24, 128, 128, 256); self->s.v.health = (!skill ? 1 : 3); self->s.v.enemy = EDICT_TO_PROG(activator); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_LAVASPLASH); WriteCoord( MSG_BROADCAST, self->s.v.origin[0]); WriteCoord( MSG_BROADCAST, self->s.v.origin[1]); WriteCoord( MSG_BROADCAST, self->s.v.origin[2]); self->s.v.yaw_speed = 20; boss_rise1(); } //============================================================================= /*QUAKED monster_boss (1 0 0) (-128 -128 -24) (128 128 256) */ void SP_monster_boss(void) { if (!AllowMonster(self)) { ent_remove(self); return; } trap_precache_model("progs/boss.mdl"); trap_precache_model("progs/lavaball.mdl"); trap_precache_sound("weapons/rocket1i.wav"); trap_precache_sound("boss1/out1.wav"); trap_precache_sound("boss1/sight1.wav"); trap_precache_sound("misc/power.wav"); trap_precache_sound("boss1/throw.wav"); trap_precache_sound("boss1/pain.wav"); trap_precache_sound("boss1/death.wav"); g_globalvars.total_monsters++; self->use = (func_t) boss_awake; } //=========================================================================== static float lightning_end; extern void door_go_down(void); void lightning_fire(void) { gedict_t *le1, *le2, *oself; vec3_t p1, p2, tmpv; le1 = le2 = NULL; le1 = find(world, FOFS(target), "lightning"); if (le1) { le2 = find(le1, FOFS(target), "lightning"); } if (!le1 || !le2) { // G_bprint( 2, "missing lightning targets\n"); return; } if (g_globalvars.time >= lightning_end) { // done here, put the terminals back up oself = self; // save self self = le1; door_go_down(); self = le2; door_go_down(); self = oself; // restore self return; } //p1 = (le1.mins + le1.maxs) * 0.5; VectorAdd(le1->s.v.mins, le1->s.v.maxs, p1); VectorScale(p1, 0.5, p1); p1[2] = le1->s.v.absmin[2] - 16; //p2 = (le2.mins + le2.maxs) * 0.5; VectorAdd(le2->s.v.mins, le2->s.v.maxs, p2); VectorScale(p2, 0.5, p2); p2[2] = le2->s.v.absmin[2] - 16; // compensate for length of bolt //p2 = p2 - normalize( p2 - p1 ) * 100; VectorSubtract(p2, p1, tmpv); normalize(tmpv, tmpv); VectorMA(p2, -100, tmpv, p2); self->s.v.nextthink = g_globalvars.time + 0.1; self->think = (func_t) lightning_fire; WriteByte( MSG_ALL, SVC_TEMPENTITY); WriteByte( MSG_ALL, TE_LIGHTNING3); WriteEntity( MSG_ALL, world); WriteCoord( MSG_ALL, p1[0]); WriteCoord( MSG_ALL, p1[1]); WriteCoord( MSG_ALL, p1[2]); WriteCoord( MSG_ALL, p2[0]); WriteCoord( MSG_ALL, p2[1]); WriteCoord( MSG_ALL, p2[2]); } void lightning_use(void) { gedict_t *le1, *le2, *oself, *boss; if (lightning_end >= (g_globalvars.time + 1)) { return; } le1 = le2 = NULL; le1 = find(world, FOFS(target), "lightning"); if (le1) { le2 = find(le1, FOFS(target), "lightning"); } if (!le1 || !le2) { // G_bprint( 2, "missing lightning targets\n"); return; } if ((le1->state != STATE_TOP && le1->state != STATE_BOTTOM) || (le2->state != STATE_TOP && le2->state != STATE_BOTTOM) || (le1->state != le2->state)) { // dprint ("not aligned\n"); return; } // don't let the electrodes go back up until the bolt is done le1->s.v.nextthink = -1; le2->s.v.nextthink = -1; lightning_end = g_globalvars.time + 1; sound(self, CHAN_VOICE, "misc/power.wav", 1, ATTN_NORM); lightning_fire(); // advance the boss pain if down boss = ez_find(world, "monster_boss"); if (!boss) { return; } oself = self; // save self self = boss; self->s.v.enemy = EDICT_TO_PROG(activator); if (le1->state == STATE_TOP && ISLIVE(self)) { sound(self, CHAN_VOICE, "boss1/pain.wav", 1, ATTN_NORM); self->s.v.health--; if (self->s.v.health >= 2) { boss_shocka1(); } else if (self->s.v.health == 1) { boss_shockb1(); } else { boss_shockc1(); } } self = oself; // restore self } /*QUAKED event_lightning (0 1 1) (-16 -16 -16) (16 16 16) Just for boss level. */ void SP_event_lightning(void) { self->use = (func_t)lightning_use; } QW-Group-ktx-d05d6ca/src/sp_client.c000066400000000000000000000145621475442401000173530ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ // sp_client.c - single player specific functions #include "g_local.h" void ExitIntermission(void) { // skip any text in deathmatch if (deathmatch) { GotoNextMap(); return; } intermission_exittime = g_globalvars.time + 1; intermission_running++; // // run some text if at the end of an episode // if (intermission_running == 2) { if (streq(mapname, "e1m7")) { WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 2); WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "As the corpse of the monstrous entity\n" "Chthon sinks back into the lava whence\n" "it rose, you grip the Rune of Earth\n" "Magic tightly. Now that you have\n" "conquered the Dimension of the Doomed,\n" "realm of Earth Magic, you are ready to\n" "complete your task. A Rune of magic\n" "power lies at the end of each haunted\n" "land of Quake. Go forth, seek the\n" "totality of the four Runes!"); return; } else if (streq(mapname, "e2m6")) { WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 2); WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "The Rune of Black Magic throbs evilly in\n" "your hand and whispers dark thoughts\n" "into your brain. You learn the inmost\n" "lore of the Hell-Mother; Shub-Niggurath!\n" "You now know that she is behind all the\n" "terrible plotting which has led to so\n" "much death and horror. But she is not\n" "inviolate! Armed with this Rune, you\n" "realize that once all four Runes are\n" "combined, the gate to Shub-Niggurath's\n" "Pit will open, and you can face the\n" "Witch-Goddess herself in her frightful\n" "otherworld cathedral."); return; } else if (streq(mapname, "e3m6")) { WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 2); WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "The charred viscera of diabolic horrors\n" "bubble viscously as you seize the Rune\n" "of Hell Magic. Its heat scorches your\n" "hand, and its terrible secrets blight\n" "your mind. Gathering the shreds of your\n" "courage, you shake the devil's shackles\n" "from your soul, and become ever more\n" "hard and determined to destroy the\n" "hideous creatures whose mere existence\n" "threatens the souls and psyches of all\n" "the population of Earth."); return; } else if (streq(mapname, "e4m7")) { WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 2); WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "Despite the awful might of the Elder\n" "World, you have achieved the Rune of\n" "Elder Magic, capstone of all types of\n" "arcane wisdom. Beyond good and evil,\n" "beyond life and death, the Rune\n" "pulsates, heavy with import. Patient and\n" "potent, the Elder Being Shub-Niggurath\n" "weaves her dire plans to clear off all\n" "life from the Earth, and bring her own\n" "foul offspring to our world! For all the\n" "dwellers in these nightmare dimensions\n" "are her descendants! Once all Runes of\n" "magic power are united, the energy\n" "behind them will blast open the Gateway\n" "to Shub-Niggurath, and you can travel\n" "there to foil the Hell-Mother's plots\n" "in person."); return; } GotoNextMap(); } if (intermission_running == 3) { if (((int)g_globalvars.serverflags & 15) == 15) { WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "Now, you have all four Runes. You sense\n" "tremendous invisible forces moving to\n" "unseal ancient barriers. Shub-Niggurath\n" "had hoped to use the Runes Herself to\n" "clear off the Earth, but now instead,\n" "you will use them to enter her home and\n" "confront her as an avatar of avenging\n" "Earth-life. If you defeat her, you will\n" "be remembered forever as the savior of\n" "the planet. If she conquers, it will be\n" "as if you had never been born."); return; } } GotoNextMap(); } char* ObituaryForMonster(char *attacker_class) { if (streq(attacker_class, "monster_army")) { return " was shot by a Grunt\n"; } if (streq(attacker_class, "monster_demon1")) { return " was eviscerated by a Fiend\n"; } if (streq(attacker_class, "monster_dog")) { return " was mauled by a Rottweiler\n"; } if (streq(attacker_class, "monster_dragon")) { return " was fried by a Dragon\n"; } if (streq(attacker_class, "monster_enforcer")) { return " was blasted by an Enforcer\n"; } if (streq(attacker_class, "monster_fish")) { return " was fed to the Rotfish\n"; } if (streq(attacker_class, "monster_hell_knight")) { return " was slain by a Death Knight\n"; } if (streq(attacker_class, "monster_knight")) { return " was slashed by a Knight\n"; } if (streq(attacker_class, "monster_ogre")) { return " was destroyed by an Ogre\n"; } if (streq(attacker_class, "monster_oldone")) { return " became one with Shub-Niggurath\n"; } if (streq(attacker_class, "monster_shalrath")) { return " was exploded by a Vore\n"; } if (streq(attacker_class, "monster_shambler")) { return " was smashed by a Shambler\n"; } if (streq(attacker_class, "monster_tarbaby")) { return " was slimed by a Spawn\n"; } if (streq(attacker_class, "monster_vomit")) { return " was vomited on by a Vomitus\n"; } if (streq(attacker_class, "monster_wizard")) { return " was scragged by a Scrag\n"; } if (streq(attacker_class, "monster_zombie")) { return " joins the Zombies\n"; } return " killed by monster? :)\n\n"; } QW-Group-ktx-d05d6ca/src/sp_demon.c000066400000000000000000000310111475442401000171630ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== DEMON ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, stand10, stand11, stand12, stand13, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, run1, run2, run3, run4, run5, run6, leap1, leap2, leap3, leap4, leap5, leap6, leap7, leap8, leap9, leap10, leap11, leap12, pain1, pain2, pain3, pain4, pain5, pain6, death1, death2, death3, death4, death5, death6, death7, death8, death9, attacka1, attacka2, attacka3, attacka4, attacka5, attacka6, attacka7, attacka8, attacka9, attacka10, attacka11, attacka12, attacka13, attacka14, attacka15, }; void demon1_stand1(void); void demon1_stand2(void); void demon1_stand3(void); void demon1_stand4(void); void demon1_stand5(void); void demon1_stand6(void); void demon1_stand7(void); void demon1_stand8(void); void demon1_stand9(void); void demon1_stand10(void); void demon1_stand11(void); void demon1_stand12(void); void demon1_stand13(void); void demon1_walk1(void); void demon1_walk2(void); void demon1_walk3(void); void demon1_walk4(void); void demon1_walk5(void); void demon1_walk6(void); void demon1_walk7(void); void demon1_walk8(void); void demon1_run1(void); void demon1_run2(void); void demon1_run3(void); void demon1_run4(void); void demon1_run5(void); void demon1_run6(void); void demon1_jump1(void); void demon1_jump2(void); void demon1_jump3(void); void demon1_jump4(void); void demon1_jump5(void); void demon1_jump6(void); void demon1_jump7(void); void demon1_jump8(void); void demon1_jump9(void); void demon1_jump10(void); void demon1_jump11(void); void demon1_jump12(void); void demon1_atta1(void); void demon1_atta2(void); void demon1_atta3(void); void demon1_atta4(void); void demon1_atta5(void); void demon1_atta6(void); void demon1_atta7(void); void demon1_atta8(void); void demon1_atta9(void); void demon1_atta10(void); void demon1_atta11(void); void demon1_atta12(void); void demon1_atta13(void); void demon1_atta14(void); void demon1_atta15(void); void demon1_pain1(void); void demon1_pain2(void); void demon1_pain3(void); void demon1_pain4(void); void demon1_pain5(void); void demon1_pain6(void); void demon1_die1(void); void demon1_die2(void); void demon1_die3(void); void demon1_die4(void); void demon1_die5(void); void demon1_die6(void); void demon1_die7(void); void demon1_die8(void); void demon1_die9(void); //============================================================================ ANIM(demon1_stand1, stand1, demon1_stand2; ai_stand();) ANIM(demon1_stand2, stand2, demon1_stand3; ai_stand();) ANIM(demon1_stand3, stand3, demon1_stand4; ai_stand();) ANIM(demon1_stand4, stand4, demon1_stand5; ai_stand();) ANIM(demon1_stand5, stand5, demon1_stand6; ai_stand();) ANIM(demon1_stand6, stand6, demon1_stand7; ai_stand();) ANIM(demon1_stand7, stand7, demon1_stand8; ai_stand();) ANIM(demon1_stand8, stand8, demon1_stand9; ai_stand();) ANIM(demon1_stand9, stand9, demon1_stand10; ai_stand();) ANIM(demon1_stand10, stand10, demon1_stand11; ai_stand();) ANIM(demon1_stand11, stand11, demon1_stand12; ai_stand();) ANIM(demon1_stand12, stand12, demon1_stand13; ai_stand();) ANIM(demon1_stand13, stand13, demon1_stand1; ai_stand();) void _demon1_walk1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_IDLE); } ai_walk(8); } ANIM(demon1_walk1, walk1, demon1_walk2; _demon1_walk1();) ANIM(demon1_walk2, walk2, demon1_walk3; ai_walk(6);) ANIM(demon1_walk3, walk3, demon1_walk4; ai_walk(6);) ANIM(demon1_walk4, walk4, demon1_walk5; ai_walk(7);) ANIM(demon1_walk5, walk5, demon1_walk6; ai_walk(4);) ANIM(demon1_walk6, walk6, demon1_walk7; ai_walk(6);) ANIM(demon1_walk7, walk7, demon1_walk8; ai_walk(10);) ANIM(demon1_walk8, walk8, demon1_walk1; ai_walk(10);) void _demon1_run1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "demon/idle1.wav", 1, ATTN_IDLE); } ai_run(20); } ANIM(demon1_run1, run1, demon1_run2; _demon1_run1();) ANIM(demon1_run2, run2, demon1_run3; ai_run(15);) ANIM(demon1_run3, run3, demon1_run4; ai_run(36);) ANIM(demon1_run4, run4, demon1_run5; ai_run(20);) ANIM(demon1_run5, run5, demon1_run6; ai_run(15);) ANIM(demon1_run6, run6, demon1_run1; ai_run(36);) void Demon_JumpTouch(void) { float ldmg; if (ISDEAD(self)) { return; } if (other->s.v.takedamage) { if (vlen(self->s.v.velocity) > 400) { ldmg = 40 + 10 * g_random(); other->deathtype = dtSQUISH; // FIXME T_Damage(other, self, self, ldmg); } } if (!checkbottom(self)) { if ((int)self->s.v.flags & FL_ONGROUND) { // jump randomly to not get hung up //dprint ("popjump\n"); self->touch = (func_t) SUB_Null; self->think = (func_t) demon1_jump1; self->s.v.nextthink = g_globalvars.time + FRAMETIME; // self.velocity_x = (g_random() - 0.5) * 600; // self.velocity_y = (g_random() - 0.5) * 600; // self.velocity_z = 200; // self.flags = self.flags - FL_ONGROUND; } return; // not on ground yet } self->touch = (func_t) SUB_Null; self->think = (func_t) demon1_jump11; self->s.v.nextthink = g_globalvars.time + FRAMETIME; } void _demon1_jump4(void) { ai_face(); self->touch = (func_t) Demon_JumpTouch; trap_makevectors(self->s.v.angles); self->s.v.origin[2] += 1; // FIXME: possibile stuck in walls, right? VectorScale(g_globalvars.v_forward, 600, self->s.v.velocity); self->s.v.velocity[2] += 250; self->s.v.flags = (int)self->s.v.flags & ~FL_ONGROUND; } void _demon1_jump10(void) { // if three seconds pass, assume demon is stuck and jump again // FIXME: qqshka: is it actually working any how? self->s.v.nextthink = g_globalvars.time + 3; } ANIM(demon1_jump1, leap1, demon1_jump2; ai_face(); sound( self, CHAN_VOICE, "demon/djump.wav", 1, ATTN_NORM );) ANIM(demon1_jump2, leap2, demon1_jump3; ai_face();) ANIM(demon1_jump3, leap3, demon1_jump4; ai_face();) ANIM(demon1_jump4, leap4, demon1_jump5; _demon1_jump4();) ANIM(demon1_jump5, leap5, demon1_jump6;) ANIM(demon1_jump6, leap6, demon1_jump7;) ANIM(demon1_jump7, leap7, demon1_jump8;) ANIM(demon1_jump8, leap8, demon1_jump9;) ANIM(demon1_jump9, leap9, demon1_jump10;) ANIM(demon1_jump10, leap10, demon1_jump1 /* NOTE it demon1_jump1 not demon1_jump11 */; _demon1_jump10();) ANIM(demon1_jump11, leap11, demon1_jump12;) ANIM(demon1_jump12, leap12, demon1_run1;) void Demon_Melee(float side) { float ldmg; vec3_t tmpv, tmpv2; ai_face(); walkmove(self, self->s.v.ideal_yaw, 12); // allow a little closing VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, tmpv); if (vlen(tmpv) > 100) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } sound(self, CHAN_WEAPON, "demon/dhit2.wav", 1, ATTN_NORM); ldmg = 10 + 5 * g_random(); PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); trap_makevectors(self->s.v.angles); VectorMA(self->s.v.origin, 16, g_globalvars.v_forward, tmpv); VectorScale(g_globalvars.v_right, side, tmpv2); SpawnMeatSpray(tmpv, tmpv2); } ANIM(demon1_atta1, attacka1, demon1_atta2; ai_charge(4);) ANIM(demon1_atta2, attacka2, demon1_atta3; ai_charge(0);) ANIM(demon1_atta3, attacka3, demon1_atta4; ai_charge(0);) ANIM(demon1_atta4, attacka4, demon1_atta5; ai_charge(1);) ANIM(demon1_atta5, attacka5, demon1_atta6; ai_charge(2); Demon_Melee(200);) ANIM(demon1_atta6, attacka6, demon1_atta7; ai_charge(1);) ANIM(demon1_atta7, attacka7, demon1_atta8; ai_charge(6);) ANIM(demon1_atta8, attacka8, demon1_atta9; ai_charge(8);) ANIM(demon1_atta9, attacka9, demon1_atta10; ai_charge(4);) ANIM(demon1_atta10, attacka10, demon1_atta11; ai_charge(2);) ANIM(demon1_atta11, attacka11, demon1_atta12; Demon_Melee(-200);) ANIM(demon1_atta12, attacka12, demon1_atta13; ai_charge(5);) ANIM(demon1_atta13, attacka13, demon1_atta14; ai_charge(8);) ANIM(demon1_atta14, attacka14, demon1_atta15; ai_charge(4);) ANIM(demon1_atta15, attacka15, demon1_run1; ai_charge(4);) ANIM(demon1_pain1, pain1, demon1_pain2) ANIM(demon1_pain2, pain2, demon1_pain3) ANIM(demon1_pain3, pain3, demon1_pain4) ANIM(demon1_pain4, pain4, demon1_pain5) ANIM(demon1_pain5, pain5, demon1_pain6) ANIM(demon1_pain6, pain6, demon1_run1) void demon1_pain(struct gedict_s *attacker, float damage) { if (self->touch == (func_t)Demon_JumpTouch) { return; } if (self->pain_finished > g_globalvars.time) { return; } self->pain_finished = g_globalvars.time + 1; sound(self, CHAN_VOICE, "demon/dpain1.wav", 1, ATTN_NORM); if (g_random() * 200 > damage) { return; // didn't flinch } demon1_pain1(); } ANIM(demon1_die1, death1, demon1_die2; sound( self, CHAN_VOICE, "demon/ddeath.wav", 1, ATTN_NORM );) ANIM(demon1_die2, death2, demon1_die3) ANIM(demon1_die3, death3, demon1_die4) ANIM(demon1_die4, death4, demon1_die5) ANIM(demon1_die5, death5, demon1_die6) ANIM(demon1_die6, death6, demon1_die7; self->s.v.solid = SOLID_NOT;) ANIM(demon1_die7, death7, demon1_die8) ANIM(demon1_die8, death8, demon1_die9) ANIM(demon1_die9, death9, demon1_die9) void demon_die(void) { // check for gib if (self->s.v.health < -80) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_demon.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death demon1_die1(); } //============================================================================== /* ============== CheckDemonMelee Returns true if a melee attack would hit right now ============== */ float CheckDemonMelee(void) { if (enemy_range == RANGE_MELEE) { // FIXME: check canreach self->attack_state = AS_MELEE; return true; } return false; } /* ============== CheckDemonJump ============== */ float CheckDemonJump(void) { vec3_t dist; float d; if ((self->s.v.origin[2] + self->s.v.mins[2]) > (PROG_TO_EDICT(self->s.v.enemy)->s.v.origin[2] + PROG_TO_EDICT(self->s.v.enemy)->s.v.mins[2] + (0.75 * PROG_TO_EDICT(self->s.v.enemy)->s.v.size[2]))) { return false; } if ((self->s.v.origin[2] + self->s.v.maxs[2]) < (PROG_TO_EDICT(self->s.v.enemy)->s.v.origin[2] + PROG_TO_EDICT(self->s.v.enemy)->s.v.mins[2] + (0.25 * PROG_TO_EDICT(self->s.v.enemy)->s.v.size[2]))) { return false; } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, dist); dist[2] = 0; d = vlen(dist); if (d < 100) { return false; } if (d > 200) { if (g_random() < 0.9) { return false; } } return true; } float DemonCheckAttack(void) { // if close enough for slashing, go for it if (CheckDemonMelee()) { self->attack_state = AS_MELEE; return true; } if (CheckDemonJump()) { self->attack_state = AS_MISSILE; return true; } return false; } //=========================================================================== /*QUAKED monster_demon1 (1 0 0) (-32 -32 -24) (32 32 64) Ambush */ void SP_monster_demon1(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/demon.mdl"); safe_precache_model("progs/h_demon.mdl"); safe_precache_sound("demon/ddeath.wav"); safe_precache_sound("demon/dhit2.wav"); safe_precache_sound("demon/djump.wav"); safe_precache_sound("demon/dpain1.wav"); safe_precache_sound("demon/idle1.wav"); safe_precache_sound("demon/sight2.wav"); setsize(self, PASSVEC3(VEC_HULL2_MIN), PASSVEC3(VEC_HULL2_MAX)); self->s.v.health = 300; self->th_stand = demon1_stand1; self->th_walk = demon1_walk1; self->th_run = demon1_run1; self->th_die = demon_die; self->th_melee = demon1_atta1; self->th_missile = demon1_jump1; // jump attack self->th_pain = demon1_pain; self->th_respawn = SP_monster_demon1; walkmonster_start("progs/demon.mdl"); } QW-Group-ktx-d05d6ca/src/sp_dog.c000066400000000000000000000301061475442401000166360ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== DOG ============================================================================== */ #include "g_local.h" enum { attack1, attack2, attack3, attack4, attack5, attack6, attack7, attack8, death1, death2, death3, death4, death5, death6, death7, death8, death9, deathb1, deathb2, deathb3, deathb4, deathb5, deathb6, deathb7, deathb8, deathb9, pain1, pain2, pain3, pain4, pain5, pain6, painb1, painb2, painb3, painb4, painb5, painb6, painb7, painb8, painb9, painb10, painb11, painb12, painb13, painb14, painb15, painb16, run1, run2, run3, run4, run5, run6, run7, run8, run9, run10, run11, run12, leap1, leap2, leap3, leap4, leap5, leap6, leap7, leap8, leap9, stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, }; void dog_stand1(void); void dog_stand2(void); void dog_stand3(void); void dog_stand4(void); void dog_stand5(void); void dog_stand6(void); void dog_stand7(void); void dog_stand8(void); void dog_stand9(void); void dog_walk1(void); void dog_walk2(void); void dog_walk3(void); void dog_walk4(void); void dog_walk5(void); void dog_walk6(void); void dog_walk7(void); void dog_walk8(void); void dog_run1(void); void dog_run2(void); void dog_run3(void); void dog_run4(void); void dog_run5(void); void dog_run6(void); void dog_run7(void); void dog_run8(void); void dog_run9(void); void dog_run10(void); void dog_run11(void); void dog_run12(void); void dog_atta1(void); void dog_atta2(void); void dog_atta3(void); void dog_atta4(void); void dog_atta5(void); void dog_atta6(void); void dog_atta7(void); void dog_atta8(void); void dog_leap1(void); void dog_leap2(void); void dog_leap3(void); void dog_leap4(void); void dog_leap5(void); void dog_leap6(void); void dog_leap7(void); void dog_leap8(void); void dog_leap9(void); void dog_pain1(void); void dog_pain2(void); void dog_pain3(void); void dog_pain4(void); void dog_pain5(void); void dog_pain6(void); void dog_painb1(void); void dog_painb2(void); void dog_painb3(void); void dog_painb4(void); void dog_painb5(void); void dog_painb6(void); void dog_painb7(void); void dog_painb8(void); void dog_painb9(void); void dog_painb10(void); void dog_painb11(void); void dog_painb12(void); void dog_painb13(void); void dog_painb14(void); void dog_painb15(void); void dog_painb16(void); void dog_die1(void); void dog_die2(void); void dog_die3(void); void dog_die4(void); void dog_die5(void); void dog_die6(void); void dog_die7(void); void dog_die8(void); void dog_die9(void); void dog_dieb1(void); void dog_dieb2(void); void dog_dieb3(void); void dog_dieb4(void); void dog_dieb5(void); void dog_dieb6(void); void dog_dieb7(void); void dog_dieb8(void); void dog_dieb9(void); ANIM(dog_stand1, stand1, dog_stand2; ai_stand();) ANIM(dog_stand2, stand2, dog_stand3; ai_stand();) ANIM(dog_stand3, stand3, dog_stand4; ai_stand();) ANIM(dog_stand4, stand4, dog_stand5; ai_stand();) ANIM(dog_stand5, stand5, dog_stand6; ai_stand();) ANIM(dog_stand6, stand6, dog_stand7; ai_stand();) ANIM(dog_stand7, stand7, dog_stand8; ai_stand();) ANIM(dog_stand8, stand8, dog_stand9; ai_stand();) ANIM(dog_stand9, stand9, dog_stand1; ai_stand();) ANIM(dog_walk1, walk1, dog_walk2; if (g_random() < 0.2) sound (self, CHAN_VOICE, "dog/idle.wav", 1, ATTN_IDLE); ai_walk(8);) ANIM(dog_walk2, walk2, dog_walk3; ai_walk(8);) ANIM(dog_walk3, walk3, dog_walk4; ai_walk(8);) ANIM(dog_walk4, walk4, dog_walk5; ai_walk(8);) ANIM(dog_walk5, walk5, dog_walk6; ai_walk(8);) ANIM(dog_walk6, walk6, dog_walk7; ai_walk(8);) ANIM(dog_walk7, walk7, dog_walk8; ai_walk(8);) ANIM(dog_walk8, walk8, dog_walk1; ai_walk(8);) ANIM(dog_run1, run1, dog_run2; if (g_random() < 0.2) sound (self, CHAN_VOICE, "dog/idle.wav", 1, ATTN_IDLE); ai_run(16);) ANIM(dog_run2, run2, dog_run3; ai_run(32);) ANIM(dog_run3, run3, dog_run4; ai_run(32);) ANIM(dog_run4, run4, dog_run5; ai_run(32);) ANIM(dog_run5, run5, dog_run6; ai_run(32);) ANIM(dog_run6, run6, dog_run7; ai_run(32);) ANIM(dog_run7, run7, dog_run8; ai_run(32);) ANIM(dog_run8, run8, dog_run9; ai_run(32);) ANIM(dog_run9, run9, dog_run10; ai_run(32);) ANIM(dog_run10, run10, dog_run11; ai_run(32);) ANIM(dog_run11, run11, dog_run12; ai_run(32);) ANIM(dog_run12, run12, dog_run1; ai_run(32);) void dog_bite(void) { vec3_t delta; float ldmg; sound(self, CHAN_VOICE, "dog/dattack1.wav", 1, ATTN_NORM); if (!self->s.v.enemy) { return; } ai_charge(10); if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 100) { return; } ldmg = (g_random() + g_random() + g_random()) * 8; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); } ANIM(dog_atta1, attack1, dog_atta2; ai_charge(10);) ANIM(dog_atta2, attack2, dog_atta3; ai_charge(10);) ANIM(dog_atta3, attack3, dog_atta4; ai_charge(10);) ANIM(dog_atta4, attack4, dog_atta5; dog_bite();) ANIM(dog_atta5, attack5, dog_atta6; ai_charge(10);) ANIM(dog_atta6, attack6, dog_atta7; ai_charge(10);) ANIM(dog_atta7, attack7, dog_atta8; ai_charge(10);) ANIM(dog_atta8, attack8, dog_run1; ai_charge(10);) void Dog_JumpTouch(void) { float ldmg; if (ISDEAD(self)) { return; } if (other->s.v.takedamage) { if (vlen(self->s.v.velocity) > 300) { ldmg = 10 + 10 * g_random(); other->deathtype = dtSQUISH; // FIXME T_Damage(other, self, self, ldmg); } } if (!checkbottom(self)) { if ((int)self->s.v.flags & FL_ONGROUND) { // jump randomly to not get hung up // dprint ("popjump\n"); self->touch = (func_t) SUB_Null; self->think = (func_t) dog_leap1; self->s.v.nextthink = g_globalvars.time + FRAMETIME; // self.velocity_x = (g_random() - 0.5) * 600; // self.velocity_y = (g_random() - 0.5) * 600; // self.velocity_z = 200; // self.flags = self.flags - FL_ONGROUND; } return; // not on ground yet } self->touch = (func_t) SUB_Null; self->think = (func_t) dog_run1; self->s.v.nextthink = g_globalvars.time + FRAMETIME; } void _dog_leap2(void) { ai_face(); self->touch = (func_t) Dog_JumpTouch; trap_makevectors(self->s.v.angles); self->s.v.origin[2] += 1; // FIXME: possibile stuck in walls, right? VectorScale(g_globalvars.v_forward, 300, self->s.v.velocity); self->s.v.velocity[2] += 200; self->s.v.flags = (int)self->s.v.flags & ~FL_ONGROUND; } void _dog_leap9(void) { // put monster back in run state after 3 seconds, actually it should never/rare happend self->s.v.nextthink = g_globalvars.time + 3; } ANIM(dog_leap1, leap1, dog_leap2; ai_face();) ANIM(dog_leap2, leap2, dog_leap3; _dog_leap2();) ANIM(dog_leap3, leap3, dog_leap4) ANIM(dog_leap4, leap4, dog_leap5) ANIM(dog_leap5, leap5, dog_leap6) ANIM(dog_leap6, leap6, dog_leap7) ANIM(dog_leap7, leap7, dog_leap8) ANIM(dog_leap8, leap8, dog_leap9) ANIM(dog_leap9, leap9, dog_run1; _dog_leap9();) ANIM(dog_pain1, pain1, dog_pain2) ANIM(dog_pain2, pain2, dog_pain3) ANIM(dog_pain3, pain3, dog_pain4) ANIM(dog_pain4, pain4, dog_pain5) ANIM(dog_pain5, pain5, dog_pain6) ANIM(dog_pain6, pain6, dog_run1) ANIM(dog_painb1, painb1, dog_painb2) ANIM(dog_painb2, painb2, dog_painb3) ANIM(dog_painb3, painb3, dog_painb4; ai_pain(4);) ANIM(dog_painb4, painb4, dog_painb5; ai_pain(12);) ANIM(dog_painb5, painb5, dog_painb6; ai_pain(12);) ANIM(dog_painb6, painb6, dog_painb7; ai_pain(2);) ANIM(dog_painb7, painb7, dog_painb8) ANIM(dog_painb8, painb8, dog_painb9; ai_pain(4);) ANIM(dog_painb9, painb9, dog_painb10) ANIM(dog_painb10, painb10, dog_painb11; ai_pain(10);) ANIM(dog_painb11, painb11, dog_painb12) ANIM(dog_painb12, painb12, dog_painb13) ANIM(dog_painb13, painb13, dog_painb14) ANIM(dog_painb14, painb14, dog_painb15) ANIM(dog_painb15, painb15, dog_painb16) ANIM(dog_painb16, painb16, dog_run1) void dog_pain(struct gedict_s *attacker, float damage) { sound(self, CHAN_VOICE, "dog/dpain1.wav", 1, ATTN_NORM); if (g_random() > 0.5) { dog_pain1(); } else { dog_painb1(); } } ANIM(dog_die1, death1, dog_die2) ANIM(dog_die2, death2, dog_die3) ANIM(dog_die3, death3, dog_die4) ANIM(dog_die4, death4, dog_die5) ANIM(dog_die5, death5, dog_die6) ANIM(dog_die6, death6, dog_die7) ANIM(dog_die7, death7, dog_die8) ANIM(dog_die8, death8, dog_die9) ANIM(dog_die9, death9, dog_die9) ANIM(dog_dieb1, deathb1, dog_dieb2) ANIM(dog_dieb2, deathb2, dog_dieb3) ANIM(dog_dieb3, deathb3, dog_dieb4) ANIM(dog_dieb4, deathb4, dog_dieb5) ANIM(dog_dieb5, deathb5, dog_dieb6) ANIM(dog_dieb6, deathb6, dog_dieb7) ANIM(dog_dieb7, deathb7, dog_dieb8) ANIM(dog_dieb8, deathb8, dog_dieb9) ANIM(dog_dieb9, deathb9, dog_dieb9) void dog_die(void) { // check for gib if (self->s.v.health < -35) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowGib("progs/gib3.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); ThrowHead("progs/h_dog.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "dog/ddeath.wav", 1, ATTN_NORM); self->s.v.solid = SOLID_NOT; if (g_random() > 0.5) { dog_die1(); } else { dog_dieb1(); } } //============================================================================ /* ============== CheckDogMelee Returns true if a melee attack would hit right now ============== */ float CheckDogMelee(void) { if (enemy_range == RANGE_MELEE) { // FIXME: check canreach self->attack_state = AS_MELEE; return true; } return false; } /* ============== CheckDogJump ============== */ float CheckDogJump(void) { vec3_t dist; float d; if ((self->s.v.origin[2] + self->s.v.mins[2]) > (PROG_TO_EDICT(self->s.v.enemy)->s.v.origin[2] + PROG_TO_EDICT(self->s.v.enemy)->s.v.mins[2] + (0.75 * PROG_TO_EDICT(self->s.v.enemy)->s.v.size[2]))) { return false; } if ((self->s.v.origin[2] + self->s.v.maxs[2]) < (PROG_TO_EDICT(self->s.v.enemy)->s.v.origin[2] + PROG_TO_EDICT(self->s.v.enemy)->s.v.mins[2] + (0.25 * PROG_TO_EDICT(self->s.v.enemy)->s.v.size[2]))) { return false; } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, dist); dist[2] = 0; d = vlen(dist); if (d < 80) { return false; } if (d > 150) { return false; } return true; } float DogCheckAttack(void) { // if close enough for slashing, go for it if (CheckDogMelee()) { self->attack_state = AS_MELEE; return true; } if (CheckDogJump()) { self->attack_state = AS_MISSILE; return true; } return false; } //=========================================================================== /*QUAKED monster_dog (1 0 0) (-32 -32 -24) (32 32 40) Ambush */ void SP_monster_dog(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/h_dog.mdl"); safe_precache_model("progs/dog.mdl"); safe_precache_sound("dog/dattack1.wav"); safe_precache_sound("dog/ddeath.wav"); safe_precache_sound("dog/dpain1.wav"); safe_precache_sound("dog/dsight.wav"); safe_precache_sound("dog/idle.wav"); setsize(self, -32, -32, -24, 32, 32, 40); self->s.v.health = 25; self->th_stand = dog_stand1; self->th_walk = dog_walk1; self->th_run = dog_run1; self->th_pain = dog_pain; self->th_die = dog_die; self->th_melee = dog_atta1; self->th_missile = dog_leap1; self->th_respawn = SP_monster_dog; walkmonster_start("progs/dog.mdl"); } QW-Group-ktx-d05d6ca/src/sp_enforcer.c000066400000000000000000000276411475442401000177020ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== SOLDIER / PLAYER ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, run1, run2, run3, run4, run5, run6, run7, run8, attack1, attack2, attack3, attack4, attack5, attack6, attack7, attack8, attack9, attack10, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, death11, death12, death13, death14, fdeath1, fdeath2, fdeath3, fdeath4, fdeath5, fdeath6, fdeath7, fdeath8, fdeath9, fdeath10, fdeath11, paina1, paina2, paina3, paina4, painb1, painb2, painb3, painb4, painb5, painc1, painc2, painc3, painc4, painc5, painc6, painc7, painc8, paind1, paind2, paind3, paind4, paind5, paind6, paind7, paind8, paind9, paind10, paind11, paind12, paind13, paind14, paind15, paind16, paind17, paind18, paind19, }; void enf_stand1(void); void enf_stand2(void); void enf_stand3(void); void enf_stand4(void); void enf_stand5(void); void enf_stand6(void); void enf_stand7(void); void enf_walk1(void); void enf_walk2(void); void enf_walk3(void); void enf_walk4(void); void enf_walk5(void); void enf_walk6(void); void enf_walk7(void); void enf_walk8(void); void enf_walk9(void); void enf_walk10(void); void enf_walk11(void); void enf_walk12(void); void enf_walk13(void); void enf_walk14(void); void enf_walk15(void); void enf_walk16(void); void enf_run1(void); void enf_run2(void); void enf_run3(void); void enf_run4(void); void enf_run5(void); void enf_run6(void); void enf_run7(void); void enf_run8(void); void enf_atk1(void); void enf_atk2(void); void enf_atk3(void); void enf_atk4(void); void enf_atk5(void); void enf_atk6(void); void enf_atk7(void); void enf_atk8(void); void enf_atk9(void); void enf_atk10(void); void enf_atk11(void); void enf_atk12(void); void enf_atk13(void); void enf_atk14(void); void enf_paina1(void); void enf_paina2(void); void enf_paina3(void); void enf_paina4(void); void enf_painb1(void); void enf_painb2(void); void enf_painb3(void); void enf_painb4(void); void enf_painb5(void); void enf_painc1(void); void enf_painc2(void); void enf_painc3(void); void enf_painc4(void); void enf_painc5(void); void enf_painc6(void); void enf_painc7(void); void enf_painc8(void); void enf_paind1(void); void enf_paind2(void); void enf_paind3(void); void enf_paind4(void); void enf_paind5(void); void enf_paind6(void); void enf_paind7(void); void enf_paind8(void); void enf_paind9(void); void enf_paind10(void); void enf_paind11(void); void enf_paind12(void); void enf_paind13(void); void enf_paind14(void); void enf_paind15(void); void enf_paind16(void); void enf_paind17(void); void enf_paind18(void); void enf_paind19(void); void enf_die1(void); void enf_die2(void); void enf_die3(void); void enf_die4(void); void enf_die5(void); void enf_die6(void); void enf_die7(void); void enf_die8(void); void enf_die9(void); void enf_die10(void); void enf_die11(void); void enf_die12(void); void enf_die13(void); void enf_die14(void); void enf_fdie1(void); void enf_fdie2(void); void enf_fdie3(void); void enf_fdie4(void); void enf_fdie5(void); void enf_fdie6(void); void enf_fdie7(void); void enf_fdie8(void); void enf_fdie9(void); void enf_fdie10(void); void enf_fdie11(void); //============================================================================ ANIM(enf_stand1, stand1, enf_stand2; ai_stand();) ANIM(enf_stand2, stand2, enf_stand3; ai_stand();) ANIM(enf_stand3, stand3, enf_stand4; ai_stand();) ANIM(enf_stand4, stand4, enf_stand5; ai_stand();) ANIM(enf_stand5, stand5, enf_stand6; ai_stand();) ANIM(enf_stand6, stand6, enf_stand7; ai_stand();) ANIM(enf_stand7, stand7, enf_stand1; ai_stand();) void _enf_walk1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE); } ai_walk(2); } ANIM(enf_walk1, walk1, enf_walk2; _enf_walk1();) ANIM(enf_walk2, walk2, enf_walk3; ai_walk(4);) ANIM(enf_walk3, walk3, enf_walk4; ai_walk(4);) ANIM(enf_walk4, walk4, enf_walk5; ai_walk(3);) ANIM(enf_walk5, walk5, enf_walk6; ai_walk(1);) ANIM(enf_walk6, walk6, enf_walk7; ai_walk(2);) ANIM(enf_walk7, walk7, enf_walk8; ai_walk(2);) ANIM(enf_walk8, walk8, enf_walk9; ai_walk(1);) ANIM(enf_walk9, walk9, enf_walk10; ai_walk(2);) ANIM(enf_walk10, walk10, enf_walk11; ai_walk(4);) ANIM(enf_walk11, walk11, enf_walk12; ai_walk(4);) ANIM(enf_walk12, walk12, enf_walk13; ai_walk(1);) ANIM(enf_walk13, walk13, enf_walk14; ai_walk(2);) ANIM(enf_walk14, walk14, enf_walk15; ai_walk(3);) ANIM(enf_walk15, walk15, enf_walk16; ai_walk(4);) ANIM(enf_walk16, walk16, enf_walk1; ai_walk(2);) void _enf_run1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE); } ai_run(18); } ANIM(enf_run1, run1, enf_run2; _enf_run1();) ANIM(enf_run2, run2, enf_run3; ai_run(14);) ANIM(enf_run3, run3, enf_run4; ai_run(7);) ANIM(enf_run4, run4, enf_run5; ai_run(12);) ANIM(enf_run5, run5, enf_run6; ai_run(14);) ANIM(enf_run6, run6, enf_run7; ai_run(14);) ANIM(enf_run7, run7, enf_run8; ai_run(7);) ANIM(enf_run8, run8, enf_run1; ai_run(11);) void enforcer_fire(void) { vec3_t org, delta; muzzleflash(); trap_makevectors(self->s.v.angles); VectorMA(self->s.v.origin, 30, g_globalvars.v_forward, org); VectorMA(org, 8.5, g_globalvars.v_right, org); org[2] += 16; VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); LaunchLaser(org, delta); } ANIM(enf_atk1, attack1, enf_atk2; ai_face();) ANIM(enf_atk2, attack2, enf_atk3; ai_face();) ANIM(enf_atk3, attack3, enf_atk4; ai_face();) ANIM(enf_atk4, attack4, enf_atk5; ai_face();) ANIM(enf_atk5, attack5, enf_atk6; ai_face();) ANIM(enf_atk6, attack6, enf_atk7; enforcer_fire();) ANIM(enf_atk7, attack7, enf_atk8; ai_face();) ANIM(enf_atk8, attack8, enf_atk9; ai_face();) ANIM(enf_atk9, attack5, enf_atk10; ai_face();) ANIM(enf_atk10, attack6, enf_atk11; enforcer_fire();) ANIM(enf_atk11, attack7, enf_atk12; ai_face();) ANIM(enf_atk12, attack8, enf_atk13; ai_face();) ANIM(enf_atk13, attack9, enf_atk14; ai_face();) ANIM(enf_atk14, attack10, enf_run1; ai_face(); SUB_CheckRefire( ( func_t ) enf_atk1);) ANIM(enf_paina1, paina1, enf_paina2) ANIM(enf_paina2, paina2, enf_paina3) ANIM(enf_paina3, paina3, enf_paina4) ANIM(enf_paina4, paina4, enf_run1) ANIM(enf_painb1, painb1, enf_painb2) ANIM(enf_painb2, painb2, enf_painb3) ANIM(enf_painb3, painb3, enf_painb4) ANIM(enf_painb4, painb4, enf_painb5) ANIM(enf_painb5, painb5, enf_run1) ANIM(enf_painc1, painc1, enf_painc2) ANIM(enf_painc2, painc2, enf_painc3) ANIM(enf_painc3, painc3, enf_painc4) ANIM(enf_painc4, painc4, enf_painc5) ANIM(enf_painc5, painc5, enf_painc6) ANIM(enf_painc6, painc6, enf_painc7) ANIM(enf_painc7, painc7, enf_painc8) ANIM(enf_painc8, painc8, enf_run1) ANIM(enf_paind1, paind1, enf_paind2) ANIM(enf_paind2, paind2, enf_paind3) ANIM(enf_paind3, paind3, enf_paind4) ANIM(enf_paind4, paind4, enf_paind5; ai_painforward(2);) ANIM(enf_paind5, paind5, enf_paind6; ai_painforward(1);) ANIM(enf_paind6, paind6, enf_paind7) ANIM(enf_paind7, paind7, enf_paind8) ANIM(enf_paind8, paind8, enf_paind9) ANIM(enf_paind9, paind9, enf_paind10) ANIM(enf_paind10, paind10, enf_paind11) ANIM(enf_paind11, paind11, enf_paind12; ai_painforward(1);) ANIM(enf_paind12, paind12, enf_paind13; ai_painforward(1);) ANIM(enf_paind13, paind13, enf_paind14; ai_painforward(1);) ANIM(enf_paind14, paind14, enf_paind15) ANIM(enf_paind15, paind15, enf_paind16) ANIM(enf_paind16, paind16, enf_paind17; ai_pain(1);) ANIM(enf_paind17, paind17, enf_paind18; ai_pain(1);) ANIM(enf_paind18, paind18, enf_paind19) ANIM(enf_paind19, paind19, enf_run1) void enf_pain(struct gedict_s *attacker, float damage) { float r; if (self->pain_finished > g_globalvars.time) { return; } r = g_random(); if (r < 0.5) { sound(self, CHAN_VOICE, "enforcer/pain1.wav", 1, ATTN_NORM); } else { sound(self, CHAN_VOICE, "enforcer/pain2.wav", 1, ATTN_NORM); } if (r < 0.2) { self->pain_finished = g_globalvars.time + 1; enf_paina1(); } else if (r < 0.4) { self->pain_finished = g_globalvars.time + 1; enf_painb1(); } else if (r < 0.7) { self->pain_finished = g_globalvars.time + 1; enf_painc1(); } else { self->pain_finished = g_globalvars.time + 2; enf_paind1(); } } void enf_drop_pack(void) { self->s.v.ammo_cells = 5; // drop 5 cells in backpack DropBackpack(); } void _enf_die_xxx(void) { self->s.v.solid = SOLID_NOT; enf_drop_pack(); } ANIM(enf_die1, death1, enf_die2) ANIM(enf_die2, death2, enf_die3) ANIM(enf_die3, death3, enf_die4; _enf_die_xxx();) ANIM(enf_die4, death4, enf_die5; ai_forward(14);) ANIM(enf_die5, death5, enf_die6; ai_forward(2);) ANIM(enf_die6, death6, enf_die7) ANIM(enf_die7, death7, enf_die8) ANIM(enf_die8, death8, enf_die9) ANIM(enf_die9, death9, enf_die10; ai_forward(3);) ANIM(enf_die10, death10, enf_die11; ai_forward(5);) ANIM(enf_die11, death11, enf_die12; ai_forward(5);) ANIM(enf_die12, death12, enf_die13; ai_forward(5);) ANIM(enf_die13, death13, enf_die14) ANIM(enf_die14, death14, enf_die14) ANIM(enf_fdie1, fdeath1, enf_fdie2) ANIM(enf_fdie2, fdeath2, enf_fdie3) ANIM(enf_fdie3, fdeath3, enf_fdie4; _enf_die_xxx();) ANIM(enf_fdie4, fdeath4, enf_fdie5) ANIM(enf_fdie5, fdeath5, enf_fdie6) ANIM(enf_fdie6, fdeath6, enf_fdie7) ANIM(enf_fdie7, fdeath7, enf_fdie8) ANIM(enf_fdie8, fdeath8, enf_fdie9) ANIM(enf_fdie9, fdeath9, enf_fdie10) ANIM(enf_fdie10, fdeath10, enf_fdie11) ANIM(enf_fdie11, fdeath11, enf_fdie11) void enf_die(void) { // check for gib if (self->s.v.health < -35) { enf_drop_pack(); sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_mega.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "enforcer/death1.wav", 1, ATTN_NORM); if (g_random() > 0.5) { enf_die1(); } else { enf_fdie1(); } } //============================================================================ /*QUAKED monster_enforcer (1 0 0) (-16 -16 -24) (16 16 40) Ambush */ void SP_monster_enforcer(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/enforcer.mdl"); safe_precache_model("progs/h_mega.mdl"); safe_precache_model("progs/laser.mdl"); safe_precache_sound("enforcer/death1.wav"); safe_precache_sound("enforcer/enfire.wav"); safe_precache_sound("enforcer/enfstop.wav"); safe_precache_sound("enforcer/idle1.wav"); safe_precache_sound("enforcer/pain1.wav"); safe_precache_sound("enforcer/pain2.wav"); safe_precache_sound("enforcer/sight1.wav"); safe_precache_sound("enforcer/sight2.wav"); safe_precache_sound("enforcer/sight3.wav"); safe_precache_sound("enforcer/sight4.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 80; self->th_stand = enf_stand1; self->th_walk = enf_walk1; self->th_run = enf_run1; self->th_pain = enf_pain; self->th_die = enf_die; self->th_missile = enf_atk1; self->th_respawn = SP_monster_enforcer; walkmonster_start("progs/enforcer.mdl"); } QW-Group-ktx-d05d6ca/src/sp_fish.c000066400000000000000000000250241475442401000170210ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== FISH ============================================================================== */ #include "g_local.h" enum { attack1, attack2, attack3, attack4, attack5, attack6, attack7, attack8, attack9, attack10, attack11, attack12, attack13, attack14, attack15, attack16, attack17, attack18, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, death11, death12, death13, death14, death15, death16, death17, death18, death19, death20, death21, swim1, swim2, swim3, swim4, swim5, swim6, swim7, swim8, swim9, swim10, swim11, swim12, swim13, swim14, swim15, swim16, swim17, swim18, pain1, pain2, pain3, pain4, pain5, pain6, pain7, pain8, pain9, }; void f_stand1(void); void f_stand2(void); void f_stand3(void); void f_stand4(void); void f_stand5(void); void f_stand6(void); void f_stand7(void); void f_stand8(void); void f_stand9(void); void f_stand10(void); void f_stand11(void); void f_stand12(void); void f_stand13(void); void f_stand14(void); void f_stand15(void); void f_stand16(void); void f_stand17(void); void f_stand18(void); void f_walk1(void); void f_walk2(void); void f_walk3(void); void f_walk4(void); void f_walk5(void); void f_walk6(void); void f_walk7(void); void f_walk8(void); void f_walk9(void); void f_walk10(void); void f_walk11(void); void f_walk12(void); void f_walk13(void); void f_walk14(void); void f_walk15(void); void f_walk16(void); void f_walk17(void); void f_walk18(void); void f_run1(void); void f_run2(void); void f_run3(void); void f_run4(void); void f_run5(void); void f_run6(void); void f_run7(void); void f_run8(void); void f_run9(void); void f_attack1(void); void f_attack2(void); void f_attack3(void); void f_attack4(void); void f_attack5(void); void f_attack6(void); void f_attack7(void); void f_attack8(void); void f_attack9(void); void f_attack10(void); void f_attack11(void); void f_attack12(void); void f_attack13(void); void f_attack14(void); void f_attack15(void); void f_attack16(void); void f_attack17(void); void f_attack18(void); void f_death1(void); void f_death2(void); void f_death3(void); void f_death4(void); void f_death5(void); void f_death6(void); void f_death7(void); void f_death8(void); void f_death9(void); void f_death10(void); void f_death11(void); void f_death12(void); void f_death13(void); void f_death14(void); void f_death15(void); void f_death16(void); void f_death17(void); void f_death18(void); void f_death19(void); void f_death20(void); void f_death21(void); void f_pain1(void); void f_pain2(void); void f_pain3(void); void f_pain4(void); void f_pain5(void); void f_pain6(void); void f_pain7(void); void f_pain8(void); void f_pain9(void); //============================================================================== ANIM(f_stand1, swim1, f_stand2; ai_stand();) ANIM(f_stand2, swim2, f_stand3; ai_stand();) ANIM(f_stand3, swim3, f_stand4; ai_stand();) ANIM(f_stand4, swim4, f_stand5; ai_stand();) ANIM(f_stand5, swim5, f_stand6; ai_stand();) ANIM(f_stand6, swim6, f_stand7; ai_stand();) ANIM(f_stand7, swim7, f_stand8; ai_stand();) ANIM(f_stand8, swim8, f_stand9; ai_stand();) ANIM(f_stand9, swim9, f_stand10; ai_stand();) ANIM(f_stand10, swim10, f_stand11; ai_stand();) ANIM(f_stand11, swim11, f_stand12; ai_stand();) ANIM(f_stand12, swim12, f_stand13; ai_stand();) ANIM(f_stand13, swim13, f_stand14; ai_stand();) ANIM(f_stand14, swim14, f_stand15; ai_stand();) ANIM(f_stand15, swim15, f_stand16; ai_stand();) ANIM(f_stand16, swim16, f_stand17; ai_stand();) ANIM(f_stand17, swim17, f_stand18; ai_stand();) ANIM(f_stand18, swim18, f_stand1; ai_stand();) ANIM(f_walk1, swim1, f_walk2; ai_walk(8);) ANIM(f_walk2, swim2, f_walk3; ai_walk(8);) ANIM(f_walk3, swim3, f_walk4; ai_walk(8);) ANIM(f_walk4, swim4, f_walk5; ai_walk(8);) ANIM(f_walk5, swim5, f_walk6; ai_walk(8);) ANIM(f_walk6, swim6, f_walk7; ai_walk(8);) ANIM(f_walk7, swim7, f_walk8; ai_walk(8);) ANIM(f_walk8, swim8, f_walk9; ai_walk(8);) ANIM(f_walk9, swim9, f_walk10; ai_walk(8);) ANIM(f_walk10, swim10, f_walk11; ai_walk(8);) ANIM(f_walk11, swim11, f_walk12; ai_walk(8);) ANIM(f_walk12, swim12, f_walk13; ai_walk(8);) ANIM(f_walk13, swim13, f_walk14; ai_walk(8);) ANIM(f_walk14, swim14, f_walk15; ai_walk(8);) ANIM(f_walk15, swim15, f_walk16; ai_walk(8);) ANIM(f_walk16, swim16, f_walk17; ai_walk(8);) ANIM(f_walk17, swim17, f_walk18; ai_walk(8);) ANIM(f_walk18, swim18, f_walk1; ai_walk(8);) void _f_run1(void) { ai_run(12); // force stupid fish attack faster. if (self->s.v.enemy && CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { f_attack1(); return; } if (g_random() < 0.5) { sound(self, CHAN_VOICE, "fish/idle.wav", 1, ATTN_NORM); } } #if 0 // NOTE: and why frames are skipped? like 1 3 5 7 ... 13 15 17 1..., perhaps just to make animation more "fast". ANIM(f_run1, swim1, f_run2; _f_run1();) ANIM(f_run2, swim3, f_run3; ai_run(12);) ANIM(f_run3, swim5, f_run4; ai_run(12);) ANIM(f_run4, swim7, f_run5; ai_run(12);) ANIM(f_run5, swim9, f_run6; ai_run(12);) ANIM(f_run6, swim11, f_run7; ai_run(12);) ANIM(f_run7, swim13, f_run8; ai_run(12);) ANIM(f_run8, swim15, f_run9; ai_run(12);) ANIM(f_run9, swim17, f_run1; ai_run(12);) #else void f_run10(void); void f_run11(void); void f_run12(void); void f_run13(void); void f_run14(void); void f_run15(void); void f_run16(void); void f_run17(void); void f_run18(void); ANIM(f_run1, swim1, f_run2; _f_run1();) ANIM(f_run2, swim2, f_run3; ai_run(12);) ANIM(f_run3, swim3, f_run4; ai_run(12);) ANIM(f_run4, swim4, f_run5; ai_run(12);) ANIM(f_run5, swim5, f_run6; ai_run(12);) ANIM(f_run6, swim6, f_run7; ai_run(12);) ANIM(f_run7, swim7, f_run8; ai_run(12);) ANIM(f_run8, swim8, f_run9; ai_run(12);) ANIM(f_run9, swim9, f_run10; ai_run(12);) ANIM(f_run10, swim10, f_run11; ai_run(12);) ANIM(f_run11, swim11, f_run12; ai_run(12);) ANIM(f_run12, swim12, f_run13; ai_run(12);) ANIM(f_run13, swim13, f_run14; ai_run(12);) ANIM(f_run14, swim14, f_run15; ai_run(12);) ANIM(f_run15, swim15, f_run16; ai_run(12);) ANIM(f_run16, swim16, f_run17; ai_run(12);) ANIM(f_run17, swim17, f_run18; ai_run(12);) ANIM(f_run18, swim18, f_run1; ai_run(12);) #endif void fish_melee(void) { vec3_t delta; float ldmg; if (!self->s.v.enemy) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 110) { return; } sound(self, CHAN_VOICE, "fish/bite.wav", 1, ATTN_NORM); if (k_bloodfest) { ldmg = (g_random() + g_random() + g_random() + g_random() + g_random()) * 3; } else { ldmg = (g_random() + g_random()) * 3; } PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); } ANIM(f_attack1, attack1, f_attack2; ai_charge(10);) ANIM(f_attack2, attack2, f_attack3; ai_charge(10);) ANIM(f_attack3, attack3, f_attack4; fish_melee();) ANIM(f_attack4, attack4, f_attack5; ai_charge(10);) ANIM(f_attack5, attack5, f_attack6; ai_charge(10);) ANIM(f_attack6, attack6, f_attack7; ai_charge(10);) ANIM(f_attack7, attack7, f_attack8; ai_charge(10);) ANIM(f_attack8, attack8, f_attack9; ai_charge(10);) ANIM(f_attack9, attack9, f_attack10; fish_melee();) ANIM(f_attack10, attack10, f_attack11; ai_charge(10);) ANIM(f_attack11, attack11, f_attack12; ai_charge(10);) ANIM(f_attack12, attack12, f_attack13; ai_charge(10);) ANIM(f_attack13, attack13, f_attack14; ai_charge(10);) ANIM(f_attack14, attack14, f_attack15; ai_charge(10);) ANIM(f_attack15, attack15, f_attack16; fish_melee();) ANIM(f_attack16, attack16, f_attack17; ai_charge(10);) ANIM(f_attack17, attack17, f_attack18; ai_charge(10);) ANIM(f_attack18, attack18, f_run1; ai_charge(10);) void _f_death1(void) { sound(self, CHAN_VOICE, "fish/death.wav", 1, ATTN_NORM); } void _f_death3(void) { self->s.v.solid = SOLID_NOT; } ANIM(f_death1, death1, f_death2; _f_death1();) ANIM(f_death2, death2, f_death3) ANIM(f_death3, death3, f_death4; _f_death3();) ANIM(f_death4, death4, f_death5) ANIM(f_death5, death5, f_death6) ANIM(f_death6, death6, f_death7) ANIM(f_death7, death7, f_death8) ANIM(f_death8, death8, f_death9) ANIM(f_death9, death9, f_death10) ANIM(f_death10, death10, f_death11) ANIM(f_death11, death11, f_death12) ANIM(f_death12, death12, f_death13) ANIM(f_death13, death13, f_death14) ANIM(f_death14, death14, f_death15) ANIM(f_death15, death15, f_death16) ANIM(f_death16, death16, f_death17) ANIM(f_death17, death17, f_death18) ANIM(f_death18, death18, f_death19) ANIM(f_death19, death19, f_death20) ANIM(f_death20, death20, f_death21) ANIM(f_death21, death21, f_death21) ANIM(f_pain1, pain1, f_pain2) ANIM(f_pain2, pain2, f_pain3; ai_pain(6);) ANIM(f_pain3, pain3, f_pain4; ai_pain(6);) ANIM(f_pain4, pain4, f_pain5; ai_pain(6);) ANIM(f_pain5, pain5, f_pain6; ai_pain(6);) ANIM(f_pain6, pain6, f_pain7; ai_pain(6);) ANIM(f_pain7, pain7, f_pain8; ai_pain(6);) ANIM(f_pain8, pain8, f_pain9; ai_pain(6);) ANIM(f_pain9, pain9, f_run1; ai_pain(6);) void fish_pain(struct gedict_s *attacker, float damage) { // fish always do pain frames f_pain1(); } //=========================================================================== /*QUAKED monster_fish (1 0 0) (-16 -16 -24) (16 16 24) Ambush */ void SP_monster_fish(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/fish.mdl"); safe_precache_sound("fish/death.wav"); safe_precache_sound("fish/bite.wav"); safe_precache_sound("fish/idle.wav"); if (k_bloodfest) { setsize(self, -10, -10, -5, 10, 10, 5); } else { setsize(self, -16, -16, -24, 16, 16, 24); } self->s.v.health = 25; self->th_stand = f_stand1; self->th_walk = f_walk1; self->th_run = f_run1; self->th_die = f_death1; self->th_pain = fish_pain; self->th_melee = f_attack1; self->th_respawn = SP_monster_fish; swimmonster_start("progs/fish.mdl"); } QW-Group-ktx-d05d6ca/src/sp_hknight.c000066400000000000000000000543141475442401000175300ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== HELL KNIGHT ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, walk17, walk18, walk19, walk20, run1, run2, run3, run4, run5, run6, run7, run8, pain1, pain2, pain3, pain4, pain5, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, death11, death12, deathb1, deathb2, deathb3, deathb4, deathb5, deathb6, deathb7, deathb8, deathb9, char_a1, char_a2, char_a3, char_a4, char_a5, char_a6, char_a7, char_a8, char_a9, char_a10, char_a11, char_a12, char_a13, char_a14, char_a15, char_a16, magica1, magica2, magica3, magica4, magica5, magica6, magica7, magica8, magica9, magica10, magica11, magica12, magica13, magica14, magicb1, magicb2, magicb3, magicb4, magicb5, magicb6, magicb7, magicb8, magicb9, magicb10, magicb11, magicb12, magicb13, char_b1, char_b2, char_b3, char_b4, char_b5, char_b6, slice1, slice2, slice3, slice4, slice5, slice6, slice7, slice8, slice9, slice10, smash1, smash2, smash3, smash4, smash5, smash6, smash7, smash8, smash9, smash10, smash11, w_attack1, w_attack2, w_attack3, w_attack4, w_attack5, w_attack6, w_attack7, w_attack8, w_attack9, w_attack10, w_attack11, w_attack12, w_attack13, w_attack14, w_attack15, w_attack16, w_attack17, w_attack18, w_attack19, w_attack20, w_attack21, w_attack22, magicc1, magicc2, magicc3, magicc4, magicc5, magicc6, magicc7, magicc8, magicc9, magicc10, magicc11, }; void hknight_stand1(void); void hknight_stand2(void); void hknight_stand3(void); void hknight_stand4(void); void hknight_stand5(void); void hknight_stand6(void); void hknight_stand7(void); void hknight_stand8(void); void hknight_stand9(void); void hknight_walk1(void); void hknight_walk2(void); void hknight_walk3(void); void hknight_walk4(void); void hknight_walk5(void); void hknight_walk6(void); void hknight_walk7(void); void hknight_walk8(void); void hknight_walk9(void); void hknight_walk10(void); void hknight_walk11(void); void hknight_walk12(void); void hknight_walk13(void); void hknight_walk14(void); void hknight_walk15(void); void hknight_walk16(void); void hknight_walk17(void); void hknight_walk18(void); void hknight_walk19(void); void hknight_walk20(void); void hknight_run1(void); void hknight_run2(void); void hknight_run3(void); void hknight_run4(void); void hknight_run5(void); void hknight_run6(void); void hknight_run7(void); void hknight_run8(void); void hknight_pain1(void); void hknight_pain2(void); void hknight_pain3(void); void hknight_pain4(void); void hknight_pain5(void); void hknight_die1(void); void hknight_die2(void); void hknight_die3(void); void hknight_die4(void); void hknight_die5(void); void hknight_die6(void); void hknight_die7(void); void hknight_die8(void); void hknight_die9(void); void hknight_die10(void); void hknight_die11(void); void hknight_die12(void); void hknight_dieb1(void); void hknight_dieb2(void); void hknight_dieb3(void); void hknight_dieb4(void); void hknight_dieb5(void); void hknight_dieb6(void); void hknight_dieb7(void); void hknight_dieb8(void); void hknight_dieb9(void); void hknight_magica1(void); void hknight_magica2(void); void hknight_magica3(void); void hknight_magica4(void); void hknight_magica5(void); void hknight_magica6(void); void hknight_magica7(void); void hknight_magica8(void); void hknight_magica9(void); void hknight_magica10(void); void hknight_magica11(void); void hknight_magica12(void); void hknight_magica13(void); void hknight_magica14(void); void hknight_magicb1(void); void hknight_magicb2(void); void hknight_magicb3(void); void hknight_magicb4(void); void hknight_magicb5(void); void hknight_magicb6(void); void hknight_magicb7(void); void hknight_magicb8(void); void hknight_magicb9(void); void hknight_magicb10(void); void hknight_magicb11(void); void hknight_magicb12(void); void hknight_magicb13(void); void hknight_magicc1(void); void hknight_magicc2(void); void hknight_magicc3(void); void hknight_magicc4(void); void hknight_magicc5(void); void hknight_magicc6(void); void hknight_magicc7(void); void hknight_magicc8(void); void hknight_magicc9(void); void hknight_magicc10(void); void hknight_magicc11(void); void hknight_char_a1(void); void hknight_char_a2(void); void hknight_char_a3(void); void hknight_char_a4(void); void hknight_char_a5(void); void hknight_char_a6(void); void hknight_char_a7(void); void hknight_char_a8(void); void hknight_char_a9(void); void hknight_char_a10(void); void hknight_char_a11(void); void hknight_char_a12(void); void hknight_char_a13(void); void hknight_char_a14(void); void hknight_char_a15(void); void hknight_char_a16(void); void hknight_char_b1(void); void hknight_char_b2(void); void hknight_char_b3(void); void hknight_char_b4(void); void hknight_char_b5(void); void hknight_char_b6(void); void hknight_slice1(void); void hknight_slice2(void); void hknight_slice3(void); void hknight_slice4(void); void hknight_slice5(void); void hknight_slice6(void); void hknight_slice7(void); void hknight_slice8(void); void hknight_slice9(void); void hknight_slice10(void); void hknight_smash1(void); void hknight_smash2(void); void hknight_smash3(void); void hknight_smash4(void); void hknight_smash5(void); void hknight_smash6(void); void hknight_smash7(void); void hknight_smash8(void); void hknight_smash9(void); void hknight_smash10(void); void hknight_smash11(void); void hknight_watk1(void); void hknight_watk2(void); void hknight_watk3(void); void hknight_watk4(void); void hknight_watk5(void); void hknight_watk6(void); void hknight_watk7(void); void hknight_watk8(void); void hknight_watk9(void); void hknight_watk10(void); void hknight_watk11(void); void hknight_watk12(void); void hknight_watk13(void); void hknight_watk14(void); void hknight_watk15(void); void hknight_watk16(void); void hknight_watk17(void); void hknight_watk18(void); void hknight_watk19(void); void hknight_watk20(void); void hknight_watk21(void); void hknight_watk22(void); //=========================================================================== // used by both walk and run void hk_idle_sound(void) { if (g_random() < 0.2) sound(self, CHAN_VOICE, "hknight/idle.wav", 1, ATTN_NORM); } //=========================================================================== ANIM(hknight_stand1, stand1, hknight_stand2; ai_stand();) ANIM(hknight_stand2, stand2, hknight_stand3; ai_stand();) ANIM(hknight_stand3, stand3, hknight_stand4; ai_stand();) ANIM(hknight_stand4, stand4, hknight_stand5; ai_stand();) ANIM(hknight_stand5, stand5, hknight_stand6; ai_stand();) ANIM(hknight_stand6, stand6, hknight_stand7; ai_stand();) ANIM(hknight_stand7, stand7, hknight_stand8; ai_stand();) ANIM(hknight_stand8, stand8, hknight_stand9; ai_stand();) ANIM(hknight_stand9, stand9, hknight_stand1; ai_stand();) //=========================================================================== void _hknight_walk1(void) { hk_idle_sound(); ai_walk(2); } ANIM(hknight_walk1, walk1, hknight_walk2; _hknight_walk1();) ANIM(hknight_walk2, walk2, hknight_walk3; ai_walk(5);) ANIM(hknight_walk3, walk3, hknight_walk4; ai_walk(5);) ANIM(hknight_walk4, walk4, hknight_walk5; ai_walk(4);) ANIM(hknight_walk5, walk5, hknight_walk6; ai_walk(4);) ANIM(hknight_walk6, walk6, hknight_walk7; ai_walk(2);) ANIM(hknight_walk7, walk7, hknight_walk8; ai_walk(2);) ANIM(hknight_walk8, walk8, hknight_walk9; ai_walk(3);) ANIM(hknight_walk9, walk9, hknight_walk10; ai_walk(3);) ANIM(hknight_walk10, walk10, hknight_walk11; ai_walk(4);) ANIM(hknight_walk11, walk11, hknight_walk12; ai_walk(3);) ANIM(hknight_walk12, walk12, hknight_walk13; ai_walk(4);) ANIM(hknight_walk13, walk13, hknight_walk14; ai_walk(6);) ANIM(hknight_walk14, walk14, hknight_walk15; ai_walk(2);) ANIM(hknight_walk15, walk15, hknight_walk16; ai_walk(2);) ANIM(hknight_walk16, walk16, hknight_walk17; ai_walk(4);) ANIM(hknight_walk17, walk17, hknight_walk18; ai_walk(3);) ANIM(hknight_walk18, walk18, hknight_walk19; ai_walk(3);) ANIM(hknight_walk19, walk19, hknight_walk20; ai_walk(3);) ANIM(hknight_walk20, walk20, hknight_walk1; ai_walk(2);) //=========================================================================== void CheckForCharge(void) { vec3_t delta; // check for mad charge if (!enemy_vis) { return; } if (g_globalvars.time < self->attack_finished) { return; } if ((fabs(self->s.v.origin[2] - PROG_TO_EDICT(self->s.v.enemy)->s.v.origin[2])) > 20) { return; // too much height change } VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) < 80) { return; // use regular attack } // charge SUB_AttackFinished(2); hknight_char_a1(); } void _hknight_run1(void) { hk_idle_sound(); ai_run(20); CheckForCharge(); } ANIM(hknight_run1, run1, hknight_run2; _hknight_run1();) ANIM(hknight_run2, run2, hknight_run3; ai_run(25);) ANIM(hknight_run3, run3, hknight_run4; ai_run(18);) ANIM(hknight_run4, run4, hknight_run5; ai_run(16);) ANIM(hknight_run5, run5, hknight_run6; ai_run(14);) ANIM(hknight_run6, run6, hknight_run7; ai_run(25);) ANIM(hknight_run7, run7, hknight_run8; ai_run(21);) ANIM(hknight_run8, run8, hknight_run1; ai_run(13);) //============================================================================ void _hknight_pain1(void) { sound(self, CHAN_VOICE, "hknight/pain1.wav", 1, ATTN_NORM); } ANIM(hknight_pain1, pain1, hknight_pain2; _hknight_pain1();) ANIM(hknight_pain2, pain2, hknight_pain3) ANIM(hknight_pain3, pain3, hknight_pain4) ANIM(hknight_pain4, pain4, hknight_pain5) ANIM(hknight_pain5, pain5, hknight_run1) void hknight_pain(struct gedict_s *attacker, float damage) { if (self->pain_finished > g_globalvars.time) { return; } if ((g_globalvars.time - self->pain_finished) > 5) { // always go into pain frame if it has been a while hknight_pain1(); self->pain_finished = g_globalvars.time + 1; return; } if ((g_random() * 30) > damage) { return; // didn't flinch } hknight_pain1(); self->pain_finished = g_globalvars.time + 1; } //============================================================================ ANIM(hknight_die1, death1, hknight_die2; ai_forward(10);) ANIM(hknight_die2, death2, hknight_die3; ai_forward(8);) ANIM(hknight_die3, death3, hknight_die4; self->s.v.solid = SOLID_NOT; ai_forward(7);) ANIM(hknight_die4, death4, hknight_die5;) ANIM(hknight_die5, death5, hknight_die6;) ANIM(hknight_die6, death6, hknight_die7;) ANIM(hknight_die7, death7, hknight_die8;) ANIM(hknight_die8, death8, hknight_die9; ai_forward(10);) ANIM(hknight_die9, death9, hknight_die10; ai_forward(11);) ANIM(hknight_die10, death10, hknight_die11;) ANIM(hknight_die11, death11, hknight_die12;) ANIM(hknight_die12, death12, hknight_die12;) ANIM(hknight_dieb1, deathb1, hknight_dieb2;) ANIM(hknight_dieb2, deathb2, hknight_dieb3;) ANIM(hknight_dieb3, deathb3, hknight_dieb4; self->s.v.solid = SOLID_NOT;) ANIM(hknight_dieb4, deathb4, hknight_dieb5;) ANIM(hknight_dieb5, deathb5, hknight_dieb6;) ANIM(hknight_dieb6, deathb6, hknight_dieb7;) ANIM(hknight_dieb7, deathb7, hknight_dieb8;) ANIM(hknight_dieb8, deathb8, hknight_dieb9;) ANIM(hknight_dieb9, deathb9, hknight_dieb9;) void hknight_die(void) { // check for gib if (self->s.v.health < -40) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_hellkn.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "hknight/death1.wav", 1, ATTN_NORM); if (g_random() > 0.5) { hknight_die1(); } else { hknight_dieb1(); } } //============================================================================ // magic void hknight_shot(float offset) { vec3_t offang, delta; vec3_t org, vec; VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); vectoangles(delta, offang); offang[1] += offset * 6; trap_makevectors(offang); // org = self.origin + self.mins + self.size * 0.5 + v_forward * 20; VectorAdd(self->s.v.origin, self->s.v.mins, org); VectorMA(org, 0.5, self->s.v.size, org); VectorMA(org, 20, g_globalvars.v_forward, org); // set missile speed normalize(g_globalvars.v_forward, vec); vec[2] = -vec[2] + (g_random() - 0.5) * 0.1; launch_spike(org, vec); newmis->classname = "knightspike"; setmodel(newmis, "progs/k_spike.mdl"); setsize(newmis, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); VectorScale(vec, 300, newmis->s.v.velocity); sound(self, CHAN_WEAPON, "hknight/attack1.wav", 1, ATTN_NORM); } ANIM(hknight_magica1, magica1, hknight_magica2; ai_face();) ANIM(hknight_magica2, magica2, hknight_magica3; ai_face();) ANIM(hknight_magica3, magica3, hknight_magica4; ai_face();) ANIM(hknight_magica4, magica4, hknight_magica5; ai_face();) ANIM(hknight_magica5, magica5, hknight_magica6; ai_face();) ANIM(hknight_magica6, magica6, hknight_magica7; ai_face();) ANIM(hknight_magica7, magica7, hknight_magica8; hknight_shot(-2);) ANIM(hknight_magica8, magica8, hknight_magica9; hknight_shot(-1);) ANIM(hknight_magica9, magica9, hknight_magica10; hknight_shot(0);) ANIM(hknight_magica10, magica10, hknight_magica11; hknight_shot(1);) ANIM(hknight_magica11, magica11, hknight_magica12; hknight_shot(2);) ANIM(hknight_magica12, magica12, hknight_magica13; hknight_shot(3);) ANIM(hknight_magica13, magica13, hknight_magica14; ai_face();) ANIM(hknight_magica14, magica14, hknight_run1; ai_face();) ANIM(hknight_magicb1, magicb1, hknight_magicb2; ai_face();) ANIM(hknight_magicb2, magicb2, hknight_magicb3; ai_face();) ANIM(hknight_magicb3, magicb3, hknight_magicb4; ai_face();) ANIM(hknight_magicb4, magicb4, hknight_magicb5; ai_face();) ANIM(hknight_magicb5, magicb5, hknight_magicb6; ai_face();) ANIM(hknight_magicb6, magicb6, hknight_magicb7; ai_face();) ANIM(hknight_magicb7, magicb7, hknight_magicb8; hknight_shot(-2);) ANIM(hknight_magicb8, magicb8, hknight_magicb9; hknight_shot(-1);) ANIM(hknight_magicb9, magicb9, hknight_magicb10; hknight_shot(0);) ANIM(hknight_magicb10, magicb10, hknight_magicb11; hknight_shot(1);) ANIM(hknight_magicb11, magicb11, hknight_magicb12; hknight_shot(2);) ANIM(hknight_magicb12, magicb12, hknight_magicb13; hknight_shot(3);) ANIM(hknight_magicb13, magicb13, hknight_run1; ai_face();) ANIM(hknight_magicc1, magicc1, hknight_magicc2; ai_face();) ANIM(hknight_magicc2, magicc2, hknight_magicc3; ai_face();) ANIM(hknight_magicc3, magicc3, hknight_magicc4; ai_face();) ANIM(hknight_magicc4, magicc4, hknight_magicc5; ai_face();) ANIM(hknight_magicc5, magicc5, hknight_magicc6; ai_face();) ANIM(hknight_magicc6, magicc6, hknight_magicc7; hknight_shot(-2);) ANIM(hknight_magicc7, magicc7, hknight_magicc8; hknight_shot(-1);) ANIM(hknight_magicc8, magicc8, hknight_magicc9; hknight_shot(0);) ANIM(hknight_magicc9, magicc9, hknight_magicc10; hknight_shot(1);) ANIM(hknight_magicc10, magicc10, hknight_magicc11; hknight_shot(2);) ANIM(hknight_magicc11, magicc11, hknight_run1; hknight_shot(3);) //=========================================================================== // melee ANIM(hknight_char_a1, char_a1, hknight_char_a2; ai_charge(20);) ANIM(hknight_char_a2, char_a2, hknight_char_a3; ai_charge(25);) ANIM(hknight_char_a3, char_a3, hknight_char_a4; ai_charge(18);) ANIM(hknight_char_a4, char_a4, hknight_char_a5; ai_charge(16);) ANIM(hknight_char_a5, char_a5, hknight_char_a6; ai_charge(14);) ANIM(hknight_char_a6, char_a6, hknight_char_a7; ai_charge(20); ai_melee();) ANIM(hknight_char_a7, char_a7, hknight_char_a8; ai_charge(21); ai_melee();) ANIM(hknight_char_a8, char_a8, hknight_char_a9; ai_charge(13); ai_melee();) ANIM(hknight_char_a9, char_a9, hknight_char_a10; ai_charge(20); ai_melee();) ANIM(hknight_char_a10, char_a10, hknight_char_a11; ai_charge(20); ai_melee();) ANIM(hknight_char_a11, char_a11, hknight_char_a12; ai_charge(18); ai_melee();) ANIM(hknight_char_a12, char_a12, hknight_char_a13; ai_charge(16);) ANIM(hknight_char_a13, char_a13, hknight_char_a14; ai_charge(14);) ANIM(hknight_char_a14, char_a14, hknight_char_a15; ai_charge(25);) ANIM(hknight_char_a15, char_a15, hknight_char_a16; ai_charge(21);) ANIM(hknight_char_a16, char_a16, hknight_run1; ai_charge(13);) void CheckContinueCharge(void) { if (g_globalvars.time > self->attack_finished) { SUB_AttackFinished(3); hknight_run1(); return; // done charging } if (g_random() > 0.5) { sound(self, CHAN_WEAPON, "knight/sword2.wav", 1, ATTN_NORM); } else { sound(self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM); } } ANIM(hknight_char_b1, char_b1, hknight_char_b2; CheckContinueCharge(); ai_charge(23); ai_melee();) ANIM(hknight_char_b2, char_b2, hknight_char_b3; ai_charge(17); ai_melee();) ANIM(hknight_char_b3, char_b3, hknight_char_b4; ai_charge(12); ai_melee();) ANIM(hknight_char_b4, char_b4, hknight_char_b5; ai_charge(22); ai_melee();) ANIM(hknight_char_b5, char_b5, hknight_char_b6; ai_charge(18); ai_melee();) ANIM(hknight_char_b6, char_b6, hknight_char_b1; ai_charge(8); ai_melee();) ANIM(hknight_slice1, slice1, hknight_slice2; ai_charge(9);) ANIM(hknight_slice2, slice2, hknight_slice3; ai_charge(6);) ANIM(hknight_slice3, slice3, hknight_slice4; ai_charge(13);) ANIM(hknight_slice4, slice4, hknight_slice5; ai_charge(4);) ANIM(hknight_slice5, slice5, hknight_slice6; ai_charge(7); ai_melee();) ANIM(hknight_slice6, slice6, hknight_slice7; ai_charge(15); ai_melee();) ANIM(hknight_slice7, slice7, hknight_slice8; ai_charge(8); ai_melee();) ANIM(hknight_slice8, slice8, hknight_slice9; ai_charge(2); ai_melee();) ANIM(hknight_slice9, slice9, hknight_slice10; ai_melee();) ANIM(hknight_slice10, slice10, hknight_run1; ai_charge(3);) ANIM(hknight_smash1, smash1, hknight_smash2; ai_charge(1);) ANIM(hknight_smash2, smash2, hknight_smash3; ai_charge(13);) ANIM(hknight_smash3, smash3, hknight_smash4; ai_charge(9);) ANIM(hknight_smash4, smash4, hknight_smash5; ai_charge(11);) ANIM(hknight_smash5, smash5, hknight_smash6; ai_charge(10); ai_melee();) ANIM(hknight_smash6, smash6, hknight_smash7; ai_charge(7); ai_melee();) ANIM(hknight_smash7, smash7, hknight_smash8; ai_charge(12); ai_melee();) ANIM(hknight_smash8, smash8, hknight_smash9; ai_charge(2); ai_melee();) ANIM(hknight_smash9, smash9, hknight_smash10; ai_charge(3); ai_melee();) ANIM(hknight_smash10, smash10, hknight_smash11; ai_charge(0);) ANIM(hknight_smash11, smash11, hknight_run1; ai_charge(0);) ANIM(hknight_watk1, w_attack1, hknight_watk2; ai_charge(2);) ANIM(hknight_watk2, w_attack2, hknight_watk3; ai_charge(0);) ANIM(hknight_watk3, w_attack3, hknight_watk4; ai_charge(0);) ANIM(hknight_watk4, w_attack4, hknight_watk5; ai_melee();) ANIM(hknight_watk5, w_attack5, hknight_watk6; ai_melee();) ANIM(hknight_watk6, w_attack6, hknight_watk7; ai_melee();) ANIM(hknight_watk7, w_attack7, hknight_watk8; ai_charge(1);) ANIM(hknight_watk8, w_attack8, hknight_watk9; ai_charge(4);) ANIM(hknight_watk9, w_attack9, hknight_watk10; ai_charge(5);) ANIM(hknight_watk10, w_attack10, hknight_watk11; ai_charge(3); ai_melee();) ANIM(hknight_watk11, w_attack11, hknight_watk12; ai_charge(2); ai_melee();) ANIM(hknight_watk12, w_attack12, hknight_watk13; ai_charge(2); ai_melee();) ANIM(hknight_watk13, w_attack13, hknight_watk14; ai_charge(0);) ANIM(hknight_watk14, w_attack14, hknight_watk15; ai_charge(0);) ANIM(hknight_watk15, w_attack15, hknight_watk16; ai_charge(0);) ANIM(hknight_watk16, w_attack16, hknight_watk17; ai_charge(1);) ANIM(hknight_watk17, w_attack17, hknight_watk18; ai_charge(1); ai_melee();) ANIM(hknight_watk18, w_attack18, hknight_watk19; ai_charge(3); ai_melee();) ANIM(hknight_watk19, w_attack19, hknight_watk20; ai_charge(4); ai_melee();) ANIM(hknight_watk20, w_attack20, hknight_watk21; ai_charge(6);) ANIM(hknight_watk21, w_attack21, hknight_watk22; ai_charge(7);) ANIM(hknight_watk22, w_attack22, hknight_run1; ai_charge(3);) //============================================================================ static int hknight_type; // FIXME; may be made it per one knight, but not shared for all knights right it now? void hknight_melee(void) { hknight_type++; hknight_type %= 3; sound(self, CHAN_WEAPON, "hknight/slash1.wav", 1, ATTN_NORM); switch (hknight_type) { case 1: hknight_slice1(); break; case 2: hknight_smash1(); break; default: hknight_watk1(); break; } } //============================================================================== /*QUAKED monster_hell_knight (1 0 0) (-16 -16 -24) (16 16 40) Ambush */ void SP_monster_hell_knight(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/hknight.mdl"); safe_precache_model("progs/k_spike.mdl"); safe_precache_model("progs/h_hellkn.mdl"); safe_precache_sound("hknight/attack1.wav"); safe_precache_sound("hknight/death1.wav"); safe_precache_sound("hknight/pain1.wav"); safe_precache_sound("hknight/sight1.wav"); safe_precache_sound("hknight/hit.wav"); safe_precache_sound("hknight/slash1.wav"); safe_precache_sound("hknight/idle.wav"); safe_precache_sound("hknight/grunt.wav"); safe_precache_sound("knight/sword1.wav"); safe_precache_sound("knight/sword2.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 250; self->th_stand = hknight_stand1; self->th_walk = hknight_walk1; self->th_run = hknight_run1; self->th_melee = hknight_melee; self->th_missile = hknight_magicc1; self->th_pain = hknight_pain; self->th_die = hknight_die; self->th_respawn = SP_monster_hell_knight; walkmonster_start("progs/hknight.mdl"); } QW-Group-ktx-d05d6ca/src/sp_knight.c000066400000000000000000000274521475442401000173630ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== KNIGHT ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, runb1, runb2, runb3, runb4, runb5, runb6, runb7, runb8, //runc1 runc2 runc3 runc4 runc5 runc6 runattack1, runattack2, runattack3, runattack4, runattack5, runattack6, runattack7, runattack8, runattack9, runattack10, runattack11, pain1, pain2, pain3, painb1, painb2, painb3, painb4, painb5, painb6, painb7, painb8, painb9, painb10, painb11, //attack1 attack2 attack3 attack4 attack5 attack6 attack7 //attack8 attack9 attack10 attack11 attackb1, attackb2, attackb3, attackb4, attackb5, attackb6, attackb7, attackb8, attackb9, attackb10, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, kneel1, kneel2, kneel3, kneel4, kneel5, standing2, standing3, standing4, standing5, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, deathb1, deathb2, deathb3, deathb4, deathb5, deathb6, deathb7, deathb8, deathb9, deathb10, deathb11, }; void knight_stand1(void); void knight_stand2(void); void knight_stand3(void); void knight_stand4(void); void knight_stand5(void); void knight_stand6(void); void knight_stand7(void); void knight_stand8(void); void knight_stand9(void); void knight_walk1(void); void knight_walk2(void); void knight_walk3(void); void knight_walk4(void); void knight_walk5(void); void knight_walk6(void); void knight_walk7(void); void knight_walk8(void); void knight_walk9(void); void knight_walk10(void); void knight_walk11(void); void knight_walk12(void); void knight_walk13(void); void knight_walk14(void); void knight_run1(void); void knight_run2(void); void knight_run3(void); void knight_run4(void); void knight_run5(void); void knight_run6(void); void knight_run7(void); void knight_run8(void); void knight_runatk1(void); void knight_runatk2(void); void knight_runatk3(void); void knight_runatk4(void); void knight_runatk5(void); void knight_runatk6(void); void knight_runatk7(void); void knight_runatk8(void); void knight_runatk9(void); void knight_runatk10(void); void knight_runatk11(void); void knight_atk1(void); void knight_atk2(void); void knight_atk3(void); void knight_atk4(void); void knight_atk5(void); void knight_atk6(void); void knight_atk7(void); void knight_atk8(void); void knight_atk9(void); void knight_atk10(void); void knight_pain1(void); void knight_pain2(void); void knight_pain3(void); void knight_painb1(void); void knight_painb2(void); void knight_painb3(void); void knight_painb4(void); void knight_painb5(void); void knight_painb6(void); void knight_painb7(void); void knight_painb8(void); void knight_painb9(void); void knight_painb10(void); void knight_painb11(void); void knight_die1(void); void knight_die2(void); void knight_die3(void); void knight_die4(void); void knight_die5(void); void knight_die6(void); void knight_die7(void); void knight_die8(void); void knight_die9(void); void knight_die10(void); void knight_dieb1(void); void knight_dieb2(void); void knight_dieb3(void); void knight_dieb4(void); void knight_dieb5(void); void knight_dieb6(void); void knight_dieb7(void); void knight_dieb8(void); void knight_dieb9(void); void knight_dieb10(void); void knight_dieb11(void); //============================================================================== ANIM(knight_stand1, stand1, knight_stand2; ai_stand();) ANIM(knight_stand2, stand2, knight_stand3; ai_stand();) ANIM(knight_stand3, stand3, knight_stand4; ai_stand();) ANIM(knight_stand4, stand4, knight_stand5; ai_stand();) ANIM(knight_stand5, stand5, knight_stand6; ai_stand();) ANIM(knight_stand6, stand6, knight_stand7; ai_stand();) ANIM(knight_stand7, stand7, knight_stand8; ai_stand();) ANIM(knight_stand8, stand8, knight_stand9; ai_stand();) ANIM(knight_stand9, stand9, knight_stand1; ai_stand();) void _knight_walk1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "knight/idle.wav", 1, ATTN_IDLE); } ai_walk(3); } ANIM(knight_walk1, walk1, knight_walk2; _knight_walk1();) ANIM(knight_walk2, walk2, knight_walk3; ai_walk(2);) ANIM(knight_walk3, walk3, knight_walk4; ai_walk(3);) ANIM(knight_walk4, walk4, knight_walk5; ai_walk(4);) ANIM(knight_walk5, walk5, knight_walk6; ai_walk(3);) ANIM(knight_walk6, walk6, knight_walk7; ai_walk(3);) ANIM(knight_walk7, walk7, knight_walk8; ai_walk(3);) ANIM(knight_walk8, walk8, knight_walk9; ai_walk(4);) ANIM(knight_walk9, walk9, knight_walk10; ai_walk(3);) ANIM(knight_walk10, walk10, knight_walk11; ai_walk(3);) ANIM(knight_walk11, walk11, knight_walk12; ai_walk(2);) ANIM(knight_walk12, walk12, knight_walk13; ai_walk(3);) ANIM(knight_walk13, walk13, knight_walk14; ai_walk(4);) ANIM(knight_walk14, walk14, knight_walk1; ai_walk(3);) void _knight_run1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "knight/idle.wav", 1, ATTN_IDLE); } ai_run(16); } ANIM(knight_run1, runb1, knight_run2; _knight_run1();) ANIM(knight_run2, runb2, knight_run3; ai_run(20);) ANIM(knight_run3, runb3, knight_run4; ai_run(13);) ANIM(knight_run4, runb4, knight_run5; ai_run(7);) ANIM(knight_run5, runb5, knight_run6; ai_run(16);) ANIM(knight_run6, runb6, knight_run7; ai_run(20);) ANIM(knight_run7, runb7, knight_run8; ai_run(14);) ANIM(knight_run8, runb8, knight_run1; ai_run(6);) void _knight_runatk1(void) { if (g_random() > 0.5) { sound(self, CHAN_WEAPON, "knight/sword2.wav", 1, ATTN_NORM); } else { sound(self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM); } ai_charge(20); } ANIM(knight_runatk1, runattack1, knight_runatk2; _knight_runatk1();) ANIM(knight_runatk2, runattack2, knight_runatk3; ai_charge_side();) ANIM(knight_runatk3, runattack3, knight_runatk4; ai_charge_side();) ANIM(knight_runatk4, runattack4, knight_runatk5; ai_charge_side();) ANIM(knight_runatk5, runattack5, knight_runatk6; ai_melee_side();) ANIM(knight_runatk6, runattack6, knight_runatk7; ai_melee_side();) ANIM(knight_runatk7, runattack7, knight_runatk8; ai_melee_side();) ANIM(knight_runatk8, runattack8, knight_runatk9; ai_melee_side();) ANIM(knight_runatk9, runattack9, knight_runatk10; ai_melee_side();) ANIM(knight_runatk10, runattack10, knight_runatk11; ai_charge_side();) ANIM(knight_runatk11, runattack11, knight_run1; ai_charge(10);) void _knight_atk1(void) { sound(self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM); ai_charge(0); } ANIM(knight_atk1, attackb1, knight_atk2; _knight_atk1();) ANIM(knight_atk2, attackb2, knight_atk3; ai_charge(7);) ANIM(knight_atk3, attackb3, knight_atk4; ai_charge(4);) ANIM(knight_atk4, attackb4, knight_atk5; ai_charge(0);) ANIM(knight_atk5, attackb5, knight_atk6; ai_charge(3);) ANIM(knight_atk6, attackb6, knight_atk7; ai_charge(4); ai_melee();) ANIM(knight_atk7, attackb7, knight_atk8; ai_charge(1); ai_melee();) ANIM(knight_atk8, attackb8, knight_atk9; ai_charge(3); ai_melee();) ANIM(knight_atk9, attackb9, knight_atk10; ai_charge(1);) ANIM(knight_atk10, attackb10, knight_run1; ai_charge(5);) void knight_melee(void) { vec3_t delta; // decide if now is a good swing time // self.enemy.origin+self.enemy.view_ofs - (self.origin+self.view_ofs) VectorAdd(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, PROG_TO_EDICT(self->s.v.enemy)->s.v.view_ofs, delta); VectorSubtract(delta, self->s.v.origin, delta); VectorSubtract(delta, self->s.v.view_ofs, delta); if (vlen(delta) < 80) { knight_atk1(); } else { knight_runatk1(); } } //=========================================================================== ANIM(knight_pain1, pain1, knight_pain2;) ANIM(knight_pain2, pain2, knight_pain3;) ANIM(knight_pain3, pain3, knight_run1;) ANIM(knight_painb1, painb1, knight_painb2; ai_painforward(0);) ANIM(knight_painb2, painb2, knight_painb3; ai_painforward(3);) ANIM(knight_painb3, painb3, knight_painb4;) ANIM(knight_painb4, painb4, knight_painb5;) ANIM(knight_painb5, painb5, knight_painb6; ai_painforward(2);) ANIM(knight_painb6, painb6, knight_painb7; ai_painforward(4);) ANIM(knight_painb7, painb7, knight_painb8; ai_painforward(2);) ANIM(knight_painb8, painb8, knight_painb9; ai_painforward(5);) ANIM(knight_painb9, painb9, knight_painb10; ai_painforward(5);) ANIM(knight_painb10, painb10, knight_painb11; ai_painforward(0);) ANIM(knight_painb11, painb11, knight_run1;) void knight_pain(struct gedict_s *attacker, float damage) { if (self->pain_finished > g_globalvars.time) { return; } sound(self, CHAN_VOICE, "knight/khurt.wav", 1, ATTN_NORM); if (g_random() < 0.85) { knight_pain1(); self->pain_finished = g_globalvars.time + 1; } else { knight_painb1(); self->pain_finished = g_globalvars.time + 1; } } //=========================================================================== ANIM(knight_die1, death1, knight_die2;) ANIM(knight_die2, death2, knight_die3;) ANIM(knight_die3, death3, knight_die4; self->s.v.solid = SOLID_NOT;) ANIM(knight_die4, death4, knight_die5) ANIM(knight_die5, death5, knight_die6) ANIM(knight_die6, death6, knight_die7) ANIM(knight_die7, death7, knight_die8) ANIM(knight_die8, death8, knight_die9) ANIM(knight_die9, death9, knight_die10) ANIM(knight_die10, death10, knight_die10) ANIM(knight_dieb1, deathb1, knight_dieb2) ANIM(knight_dieb2, deathb2, knight_dieb3) ANIM(knight_dieb3, deathb3, knight_dieb4; self->s.v.solid = SOLID_NOT;) ANIM(knight_dieb4, deathb4, knight_dieb5) ANIM(knight_dieb5, deathb5, knight_dieb6) ANIM(knight_dieb6, deathb6, knight_dieb7) ANIM(knight_dieb7, deathb7, knight_dieb8) ANIM(knight_dieb8, deathb8, knight_dieb9) ANIM(knight_dieb9, deathb9, knight_dieb10) ANIM(knight_dieb10, deathb10, knight_dieb11) ANIM(knight_dieb11, deathb11, knight_dieb11) void knight_die(void) { // check for gib if (self->s.v.health < -40) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_knight.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM); if (g_random() < 0.5) { knight_die1(); } else { knight_dieb1(); } } //============================================================================== /*QUAKED monster_knight (1 0 0) (-16 -16 -24) (16 16 40) Ambush */ void SP_monster_knight(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/knight.mdl"); safe_precache_model("progs/h_knight.mdl"); safe_precache_sound("knight/kdeath.wav"); safe_precache_sound("knight/khurt.wav"); safe_precache_sound("knight/ksight.wav"); safe_precache_sound("knight/sword1.wav"); safe_precache_sound("knight/sword2.wav"); safe_precache_sound("knight/idle.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 75; self->th_stand = knight_stand1; self->th_walk = knight_walk1; self->th_run = knight_run1; self->th_melee = knight_melee; self->th_pain = knight_pain; self->th_die = knight_die; self->th_respawn = SP_monster_knight; walkmonster_start("progs/knight.mdl"); } QW-Group-ktx-d05d6ca/src/sp_monsters.c000066400000000000000000000554241475442401000177510ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ #include "g_local.h" /* ALL MONSTERS SHOULD BE 1 0 0 IN COLOR */ // name =[framenum, nexttime, nextthink] {code} // expands to: // name () // { // self.frame=framenum; // self.nextthink = time + nexttime; // self.think = nextthink // // } //============================================================================ // LIMITS. static const int k_bloodfest_monsters = 100; // maximum monsters allowed in bloodfest mode. static const int k_bloodfest_projectiles = 30; // maximum projectiles allowed in bloodfest mode. static const float k_bloodfest_monsters_spawn_period = 20;// with which perioud we should issue monsters wave. static const float k_bloodfest_monsters_spawn_factor = 0.2; // monsters population is bigger by this each wave. static const int k_bloodfest_monsters_spawn_initial = 20; // monsters population in first wave. static const float k_bloodfest_boss_hp_factor = 13; // hp factor if monster is boss. static const float k_bloodfest_boss_chance = -1;// percentage chance of boss spawn in particular wave. // RUNTIME. bloodfest_t g_bloodfest; typedef struct bloodfest_monster_s { char *class_name; // monsters class name, same that used in g_spawn.c int hp_for_kill; // how much hp player gains for killing such monster. int armor_for_kill; // how much armor player gains for killing such monster. qbool boss_able; // able to be boss. } bloodfest_monster_t; // reset bloodfest runtime variables to default values. void bloodfest_reset(void) { memset(&g_bloodfest, 0, sizeof(g_bloodfest)); } static bloodfest_monster_t bloodfest_monster_array[] = { // WARNING: FISH _MUST_ BE _FIRST_ IN ARRAY, I HAVE HACK FOR IT IN bloodfest_spawn_monsters()!!! { "monster_fish", 1, 1, false, }, { "monster_ogre", 3, 2, false, }, { "monster_demon1", 4, 4, false, }, { "monster_shambler", 10, 8, true, }, { "monster_knight", 1, 1, false, }, { "monster_army", 1, 1, false, }, { "monster_wizard", 2, 2, false, }, { "monster_dog", 1, 1, false, }, { "monster_zombie", 1, 1, false, }, { "monster_tarbaby", 4, 4, false, }, { "monster_hell_knight", 4, 3, false, }, { "monster_shalrath", 6, 6, false, }, { "monster_enforcer", 2, 1, false, }, }; static const int bloodfest_monster_array_size = sizeof(bloodfest_monster_array) / sizeof(bloodfest_monster_array[0]); // find bloodfest_monster_t in array by class_name. static bloodfest_monster_t* bloodfest_find_monster_by_classname(const char *class_name) { int i; for (i = 0; i < bloodfest_monster_array_size; i++) { if (streq(bloodfest_monster_array[i].class_name, class_name)) { return &bloodfest_monster_array[i]; } } return NULL; } // print bloodfest stats. void bloodfest_stats(void) { float time = g_globalvars.time - match_start_time; G_bprint(2, "The surviving is over\n"); G_bprint(2, "Surviving time is %.1f seconds\n", time); } static void safe_ent_remove(gedict_t *t) { if (!t ||( t == world)) { return; } ent_remove(t); } void SP_info_monster_start(void) { if (deathmatch) { ent_remove(self); return; } } // return monsters count, including corpses. int monsters_count(qbool alive, qbool boss_only) { int cnt = 0; gedict_t *p; for (p = world; (p = nextent(p));) { if (!((int)p->s.v.flags & FL_MONSTER)) { continue; // not a monster } if (alive && !ISLIVE(p)) { continue; // not alive. } if (boss_only && !p->bloodfest_boss) { continue; // not a boss. } cnt++; } return cnt; } // return projectiles count. int projectiles_count(void) { int cnt = 0; gedict_t *p; for (p = world; (p = nextent(p));) { if (!p->isMissile) { continue; // not a projectile } cnt++; } return cnt; } // spawn one monster. gedict_t* bloodfest_spawn_monster(gedict_t *spot, char *classname) { extern qbool G_CallSpawn(gedict_t *ent); gedict_t *oself; gedict_t *p = spawn(); p->classname = classname; VectorCopy(spot->s.v.origin, p->s.v.origin); VectorCopy(spot->s.v.angles, p->s.v.angles); setorigin(p, PASSVEC3(p->s.v.origin)); // G_CallSpawn will change 'self', so we have to do trick about it. oself = self; // save!!! if (!G_CallSpawn(p) || !p->s.v.solid) { // failed to call spawn function, so remove it ASAP. ent_remove(p); p = NULL; } self = oself; // restore!!! return p; } void bloodfest_wave_calculate(void) { float factor; // if boss still alive we can't start new wave. if (g_bloodfest.monsters_spawn_time == -1) { if (monsters_count(true, true)) { return; // boss is still alive, can't do new wave yet. } g_bloodfest.monsters_spawn_time = 0; } if (g_bloodfest.monsters_spawn_time > g_globalvars.time) { return; // not ready to calculate wave. } // OK. time for next wave! // calculate next wave time. g_bloodfest.monsters_spawn_time = g_globalvars.time + k_bloodfest_monsters_spawn_period; // calculate how much monsters we should spawn in this wave. factor = match_start_time ? 1 + k_bloodfest_monsters_spawn_factor * (g_globalvars.time - match_start_time) / k_bloodfest_monsters_spawn_period : 1; factor = bound(1, factor, 999999); g_bloodfest.monsters_to_spawn = (int)(factor * k_bloodfest_monsters_spawn_initial); // if there is still alive monsters, reduce wave by that count. g_bloodfest.monsters_to_spawn -= monsters_count(true, false); // apply limits. g_bloodfest.monsters_to_spawn = bound(0, g_bloodfest.monsters_to_spawn, k_bloodfest_monsters); if (g_bloodfest.monsters_to_spawn) { g_bloodfest.spawn_boss = (g_random() < k_bloodfest_boss_chance); if (g_bloodfest.spawn_boss) { g_bloodfest.monsters_spawn_time = -1; // stop waves untill boss die g_bloodfest.monsters_to_spawn = 1; // allow to spawn only boss alone. } } // G_cprint("to spawn: %d\n", monsters_to_spawn); } // attempt to spawn more monsters. void bloodfest_spawn_monsters(void) { gedict_t *spot; gedict_t *p; int total_spawns; int i; intptr_t content; // precache: spawn all possible monsters and remove them so they precached. // we do it once at first frame of the map. if (framecount == 1) { for (i = 0; i < bloodfest_monster_array_size; i++) { safe_ent_remove(bloodfest_spawn_monster(world, bloodfest_monster_array[i].class_name)); } return; } if (intermission_running || (match_in_progress != 2) || match_over) { return; } bloodfest_wave_calculate(); if (g_bloodfest.monsters_to_spawn < 1) { return; // nothing to spawn. } // too much monsters, can't spawn more. if (monsters_count(true, false) >= k_bloodfest_monsters) { return; } // find total amount of spots. total_spawns = find_cnt( FOFCLSN, "info_monster_start"); // can't find spawn point. if (!total_spawns) { return; } // attempt to spawn one monster, // we trying to do it few times in row since we can fail because spawn point is busy or something. for (i = 0; i < 30; i++) { int idx = 0; // find some random spawn point. spot = find_idx(i_rnd(0, total_spawns - 1), FOFCLSN, "info_monster_start"); // can't find. if (!spot) { break; } // get spawn content. content = trap_pointcontents(PASSVEC3(spot->s.v.origin)); // select monster. if (g_bloodfest.spawn_boss) { // does not spawn boss in a water. if (content == CONTENT_WATER) { continue; } idx = i_rnd(1, bloodfest_monster_array_size - 1); // not a boss. if (!bloodfest_monster_array[idx].boss_able) { continue; } } else { if (content == CONTENT_WATER) { idx = 0; // HACK: spawn fish. } else { idx = i_rnd(1, bloodfest_monster_array_size - 1); } } // spawn monster. p = bloodfest_spawn_monster(spot, bloodfest_monster_array[idx].class_name); if (p) { // attempt to spawn boss. if (g_bloodfest.spawn_boss && bloodfest_monster_array[idx].boss_able) { p->s.v.health *= k_bloodfest_boss_hp_factor; p->s.v.effects = (int)p->s.v.effects | EF_BLUE | EF_RED; p->bloodfest_boss = true; g_bloodfest.spawn_boss = false; // G_bprint( 2, "BOSS %d\n", (int)p->s.v.health ); } break; // spawned something. } // G_cprint("respawn %d\n", i); } // reduce amount to spawn next time. g_bloodfest.monsters_to_spawn--; } // remove monsters corpses, so there free edicts. void bloodfest_free_monsters(void) { gedict_t *p; for (p = world; (p = nextent(p));) { if (!((int)p->s.v.flags & FL_MONSTER)) { continue; // not a monster } if (match_in_progress == 2) { if (ISLIVE(p)) { continue; // not dead } if (p->dead_time && ((p->dead_time + 5) > g_globalvars.time)) { continue; // time is not come yet } } ent_remove(p); } } // apply content damage for the monsters. void bloodfest_monsters_content_damage(void) { gedict_t *p; if (match_in_progress != 2) { return; } for (p = world; (p = nextent(p));) { if (!((int)p->s.v.flags & FL_MONSTER)) { continue; // not a monster } if (!ISLIVE(p)) { continue; // dead } if (p->s.v.watertype == CONTENT_LAVA) { // do damage if (p->dmgtime < g_globalvars.time) { p->dmgtime = g_globalvars.time + 0.2; p->deathtype = dtLAVA_DMG; T_Damage(p, world, world, 30 * p->s.v.waterlevel); } } else if (p->s.v.watertype == CONTENT_SLIME) { // do damage if (p->dmgtime < g_globalvars.time) { p->dmgtime = g_globalvars.time + 0.2; p->deathtype = dtSLIME_DMG; T_Damage(p, world, world, 20 * p->s.v.waterlevel); } } else if (p->s.v.watertype == CONTENT_WATER) { // do damage - if monster can't swim if (p->dmgtime < g_globalvars.time && !((int)p->s.v.flags & FL_SWIM)) { p->dmgtime = g_globalvars.time + 0.2; p->deathtype = dtWATER_DMG; T_Damage(p, world, world, 15 * p->s.v.waterlevel); } } } } // remove projectiles if there too much. void bloodfest_free_projectiles(void) { int remove; gedict_t *p; remove = projectiles_count() - k_bloodfest_projectiles; for (p = world; remove > 0 && (p = nextent(p));) { if (!p->isMissile) { continue; // not a projectile } if (PROG_TO_EDICT(p->s.v.owner)->ct == ctPlayer) { continue; // can't remove players projectiles. } ent_remove(p); remove--; } } void bloodfest_change_pov(void) { gedict_t *p; if (self->trackent > 0 && (self->trackent <= MAX_CLIENTS)) { p = &g_edicts[self->trackent]; } else { p = world; } for (; (p = find_plr(p));) { if (ISLIVE(p)) { break; // we found alive player! } } self->trackent = NUM_FOR_EDICT(p ? p : world); if (p) { G_sprint(self, 2, "tracking %s\n", getname(p)); } } void bloodfest_dead_jump_button(void) { if (!self->s.v.button2) { self->s.v.flags = ((int)(self->s.v.flags)) | FL_JUMPRELEASED; return; } if (!(((int)(self->s.v.flags)) & FL_JUMPRELEASED)) { return; } self->s.v.flags = (int)self->s.v.flags & ~FL_JUMPRELEASED; // switch pov. bloodfest_change_pov(); } // main clients bloodfest hook. void bloodfest_client_think(void) { if (self->ct != ctPlayer) { return; } // if player dead, then allow speccing alive players with jump button. if (!ISLIVE(self)) { bloodfest_dead_jump_button(); } } void bloodfest_check_end_match(void) { gedict_t *p; if (match_in_progress != 2) { return; } for (p = world; (p = find_plr(p));) { if (ISLIVE(p)) { return; // we found at least one alive player! } } // all players is dead, so issue end match now! EndMatch(0); } // called each time something/someone is killed. void bloodfest_killed_hook(gedict_t *killed, gedict_t *attacker) { bloodfest_monster_t *monster = NULL; if (match_in_progress != 2) { return; } // if killed was a player then check for endmatch. if (killed->ct == ctPlayer) { bloodfest_check_end_match(); return; } // alive players regen health for killing monsters. if (!ISLIVE(attacker) || (attacker->ct != ctPlayer)) { return; // does not match our needs. } // 'killed' could be a monstah or trigger, we need teh monstah. if (!((int)killed->s.v.flags & FL_MONSTER)) { return; } if (!(monster = bloodfest_find_monster_by_classname(killed->classname))) { return; // monster not found, should not be the case. } if ((attacker->s.v.health < 250) && (monster->hp_for_kill > 0)) { attacker->s.v.health += monster->hp_for_kill; attacker->s.v.health = min(attacker->s.v.health, 250); // cap it at 250 } if ((attacker->s.v.armorvalue < 200) && (monster->armor_for_kill > 0)) { attacker->s.v.armorvalue += monster->armor_for_kill; attacker->s.v.armorvalue = min(attacker->s.v.armorvalue, 200); // cap it at 200 // remove all armors and add red armor. attacker->s.v.items += IT_ARMOR3 - ((int)attacker->s.v.items & ( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)); attacker->s.v.armortype = 0.8; } // bump the score according to monster difficulty if (monster->hp_for_kill > 1) { attacker->s.v.frags += monster->hp_for_kill - 1; } } // main bloodfest hook. void bloodfest_think(void) { bloodfest_check_end_match(); bloodfest_spawn_monsters(); bloodfest_free_projectiles(); bloodfest_free_monsters(); bloodfest_monsters_content_damage(); } //============================================================================ void MonsterDropPowerups(void) { int i; if (skill < 3) { return; // skill 3 or more required } if (!Get_Powerups()) { return; } if (g_random() > cvar("k_nightmare_pu_droprate")) { return; } i = i_rnd(0, 5); switch (i) { case 0: if ( /* cvar( "dp" ) && */cvar("k_pow_p")) { DropPowerup(30, IT_INVULNERABILITY); } break; case 1: if ( /* cvar( "dr" ) && */cvar("k_pow_r")) { DropPowerup(30, IT_INVISIBILITY); } break; // more chances for quad compared to pent and ring default: if ( /* cvar( "dq" ) && */cvar("k_pow_q")) { DropPowerup(30, IT_QUAD); } break; } } //============================================================================ /* ================ monster_use Using a monster makes it angry at the current activator ================ */ void monster_use(void) { if (self->s.v.enemy) { return; } if (ISDEAD(self)) { return; } if (activator->ct != ctPlayer) { return; } if ((int)activator->s.v.items & IT_INVISIBILITY) { return; } if ((int)activator->s.v.flags & FL_NOTARGET) { return; } // delay reaction so if the monster is teleported, its sound is still heard self->s.v.enemy = EDICT_TO_PROG(activator); self->s.v.nextthink = g_globalvars.time + 0.1; self->think = (func_t) FoundTarget; } /* ================ monster_death_use When a mosnter dies, it fires all of its targets with the current enemy as activator. ================ */ void monster_death_use(void) { if (!((int)self->s.v.flags & FL_MONSTER)) { return; // not a monster } if (cvar("k_nightmare_pu")) { MonsterDropPowerups(); } // fall to ground self->s.v.flags = (int)self->s.v.flags & ~( FL_FLY | FL_SWIM); if (!self->target) { return; } activator = PROG_TO_EDICT(self->s.v.enemy); SUB_UseTargets(); } //============================================================================ void check_monsters_respawn(void) { gedict_t *p, *oself; if (deathmatch) { return; // no need in dm } if (k_bloodfest) { bloodfest_think(); return; } if (skill < 3) { return; // skill 3 or more required } if (cvar("k_monster_spawn_time") <= 0) { return; } for (p = world; (p = nextent(p));) { if (!((int)p->s.v.flags & FL_MONSTER)) { continue; // not a monster } if (ISLIVE(p)) { continue; // not dead } if (!p->th_respawn) { continue; // respawn function is not set } if (p->monster_desired_spawn_time > g_globalvars.time) { continue; // time is not come yet } oself = self; // save self = p; // WARNING !!! self->th_respawn(); self = oself; // restore } } //============================================================================ /* * Checking is it possibile to put entity at position with such minx/maxs. * !!! Pretty expensive for CPU. USE WITH CARE !!! */ static qbool is_location_occupied(gedict_t *e, vec3_t pos, vec3_t mins, vec3_t maxs) { qbool occupied = false; gedict_t *p; vec3_t origin_copy, pos_copy; // have to copy origin. VectorCopy(self->s.v.origin, origin_copy); // have to copy position since it most of the time // is e->s.v.origin which is gonna be changed one line below. VectorCopy(pos, pos_copy); // have to change origin, so damned TraceCapsule() working as expected. setorigin(self, 1.0e+5, 1.0e+5, 1.0e+5); TraceCapsule(PASSVEC3(pos_copy), PASSVEC3(pos_copy), false, e, PASSVEC3(mins), PASSVEC3(maxs)); p = PROG_TO_EDICT(g_globalvars.trace_ent); if (g_globalvars.trace_startsolid || (g_globalvars.trace_fraction != 1) || ((p != e) && (p != world) && ((p->s.v.solid == SOLID_BSP) || (p->s.v.solid == SOLID_SLIDEBOX)))) { occupied = true; // positon occupied. } // restore origin. setorigin(self, PASSVEC3(origin_copy)); return occupied; } //============================================================================ typedef enum { mtWalk, mtFly, mtSwim, } monsterType_t; void monster_start_go(monsterType_t mt) { vec3_t tmpv; self->s.v.enemy = EDICT_TO_PROG(world); self->s.v.goalentity = EDICT_TO_PROG(world); self->oldenemy = NULL; self->lefty = 0; self->search_time = 0; self->attack_state = 0; if (mt == mtWalk) { self->s.v.origin[2] += 1; // raise off floor a bit droptofloor(self); } VectorSet(tmpv, 0, 1, 0); self->s.v.ideal_yaw = DotProduct(self->s.v.angles, tmpv); if (!self->s.v.yaw_speed) { self->s.v.yaw_speed = (mt == mtWalk ? 20 : 10); } VectorSet(self->s.v.view_ofs, 0, 0, mt == mtSwim ? 10 : 25); self->use = (func_t) monster_use; self->s.v.solid = SOLID_SLIDEBOX; self->s.v.takedamage = DAMAGE_AIM; if (k_bloodfest && is_location_occupied(self, self->s.v.origin, self->s.v.mins, self->s.v.maxs)) { // G_cprint( "monster (%s) in wall at: %.1f %.1f %.1f, removed!\n", // self->classname, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] ); ent_remove(self); // remove it ASAP. return; } if (!k_bloodfest && !walkmove(self, 0, 0)) { G_cprint("monster %d in wall at: %.1f %.1f %.1f\n", NUM_FOR_EDICT(self), self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2]); self->model = ""; // turn off model self->s.v.solid = SOLID_NOT; self->s.v.takedamage = DAMAGE_NO; self->s.v.nextthink = g_globalvars.time + 5; // reshedule setorigin(self, PASSVEC3(self->s.v.oldorigin)); return; } if (!strnull(self->mdl)) { setmodel(self, self->mdl); // restore original model } // seems we respawning monster again, use some funky effects if (self->dead_time) { play_teleport(self); spawn_tfog(self->s.v.origin); } if (self->target) { self->movetarget = find(world, FOFS(targetname), self->target); if (!self->movetarget) // NOTE: this is a damn difference with qc { self->movetarget = world; } self->s.v.goalentity = EDICT_TO_PROG(self->movetarget); VectorSubtract(PROG_TO_EDICT(self->s.v.goalentity)->s.v.origin, self->s.v.origin, tmpv); self->s.v.ideal_yaw = vectoyaw(tmpv); if (!self->movetarget || (self->movetarget == world)) { // G_bprint( 2, "monster can't find target at: %.1f %.1f %.1f\n", self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] ); G_cprint("monster can't find target at: %.1f %.1f %.1f\n", self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2]); } // this used to be an objerror if (self->movetarget && streq(self->movetarget->classname, "path_corner")) { if (self->th_walk) { self->th_walk(); } } else { self->pausetime = 10e+32; if (self->th_stand) { self->th_stand(); } } } else { self->pausetime = 10e+32; if (self->th_stand) { self->th_stand(); } } // spread think times so they don't all happen at same time self->s.v.nextthink = g_globalvars.time + g_random() * 0.5; } void walkmonster_start_go(void) { monster_start_go(mtWalk); } void flymonster_start_go(void) { monster_start_go(mtFly); } void swimmonster_start_go(void) { monster_start_go(mtSwim); } static void common_monster_start(char *model, int flags) { self->s.v.flags = (int)self->s.v.flags & ~FL_ONGROUND; self->s.v.movetype = MOVETYPE_STEP; g_globalvars.total_monsters += 1; // bump monsters total count if ((int)self->s.v.flags & FL_MONSTER) { // FL_MONSTER set, so we spawn monster non first time, it should be nightmare mode... self->s.v.solid = SOLID_NOT; setorigin(self, PASSVEC3(self->s.v.oldorigin)); // move monster back to his first spawn origin VectorCopy(self->oldangles, self->s.v.angles); // restore angles } else { // FL_MONSTER not set, should be first monster spawn setmodel(self, model); // set model (so modelindex is initialized) self->mdl = self->model; // save model VectorCopy(self->s.v.origin, self->s.v.oldorigin); // save first spawn origin VectorCopy(self->s.v.angles, self->oldangles); // save angles } // turn off model since monster spawn complete in monster_start_go(). self->model = ""; // always set FL_MONSTER and possibily add some additional flags self->s.v.flags = (int)self->s.v.flags | FL_MONSTER | flags; } void bloodfest_speedup_monster_spawn(void) { if (!k_bloodfest || !self->think) { return; } self->s.v.nextthink = g_globalvars.time; ((void (*)(void))(self->think))(); } void walkmonster_start(char *model) { common_monster_start(model, 0); // delay drop to floor to make sure all doors have been spawned // spread think times so they don't all happen at same time self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.5; self->think = (func_t) walkmonster_start_go; bloodfest_speedup_monster_spawn(); } void flymonster_start(char *model) { // set FL_FLY early so that we're not affected by gravity common_monster_start(model, FL_FLY); // spread think times so they don't all happen at same time self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.5; self->think = (func_t) flymonster_start_go; bloodfest_speedup_monster_spawn(); } void swimmonster_start(char *model) { // set FL_SWIM early so that we're not affected by gravity common_monster_start(model, FL_SWIM); // spread think times so they don't all happen at same time self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.5; self->think = (func_t) swimmonster_start_go; bloodfest_speedup_monster_spawn(); } QW-Group-ktx-d05d6ca/src/sp_ogre.c000066400000000000000000000471651475442401000170360ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== OGRE ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, run1, run2, run3, run4, run5, run6, run7, run8, swing1, swing2, swing3, swing4, swing5, swing6, swing7, swing8, swing9, swing10, swing11, swing12, swing13, swing14, smash1, smash2, smash3, smash4, smash5, smash6, smash7, smash8, smash9, smash10, smash11, smash12, smash13, smash14, shoot1, shoot2, shoot3, shoot4, shoot5, shoot6, pain1, pain2, pain3, pain4, pain5, painb1, painb2, painb3, painc1, painc2, painc3, painc4, painc5, painc6, paind1, paind2, paind3, paind4, paind5, paind6, paind7, paind8, paind9, paind10, paind11, paind12, paind13, paind14, paind15, paind16, paine1, paine2, paine3, paine4, paine5, paine6, paine7, paine8, paine9, paine10, paine11, paine12, paine13, paine14, paine15, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, death11, death12, death13, death14, bdeath1, bdeath2, bdeath3, bdeath4, bdeath5, bdeath6, bdeath7, bdeath8, bdeath9, bdeath10, pull1, pull2, pull3, pull4, pull5, pull6, pull7, pull8, pull9, pull10, pull11, }; void ogre_stand1(void); void ogre_stand2(void); void ogre_stand3(void); void ogre_stand4(void); void ogre_stand5(void); void ogre_stand6(void); void ogre_stand7(void); void ogre_stand8(void); void ogre_stand9(void); void ogre_walk1(void); void ogre_walk2(void); void ogre_walk3(void); void ogre_walk4(void); void ogre_walk5(void); void ogre_walk6(void); void ogre_walk7(void); void ogre_walk8(void); void ogre_walk9(void); void ogre_walk10(void); void ogre_walk11(void); void ogre_walk12(void); void ogre_walk13(void); void ogre_walk14(void); void ogre_walk15(void); void ogre_walk16(void); void ogre_run1(void); void ogre_run2(void); void ogre_run3(void); void ogre_run4(void); void ogre_run5(void); void ogre_run6(void); void ogre_run7(void); void ogre_run8(void); void ogre_swing1(void); void ogre_swing2(void); void ogre_swing3(void); void ogre_swing4(void); void ogre_swing5(void); void ogre_swing6(void); void ogre_swing7(void); void ogre_swing8(void); void ogre_swing9(void); void ogre_swing10(void); void ogre_swing11(void); void ogre_swing12(void); void ogre_swing13(void); void ogre_swing14(void); void ogre_smash1(void); void ogre_smash2(void); void ogre_smash3(void); void ogre_smash4(void); void ogre_smash5(void); void ogre_smash6(void); void ogre_smash7(void); void ogre_smash8(void); void ogre_smash9(void); void ogre_smash10(void); void ogre_smash11(void); void ogre_smash12(void); void ogre_smash13(void); void ogre_smash14(void); void ogre_nail1(void); void ogre_nail2(void); void ogre_nail3(void); void ogre_nail4(void); void ogre_nail5(void); void ogre_nail6(void); void ogre_nail7(void); void ogre_pain1(void); void ogre_pain2(void); void ogre_pain3(void); void ogre_pain4(void); void ogre_pain5(void); void ogre_painb1(void); void ogre_painb2(void); void ogre_painb3(void); void ogre_painc1(void); void ogre_painc2(void); void ogre_painc3(void); void ogre_painc4(void); void ogre_painc5(void); void ogre_painc6(void); void ogre_paind1(void); void ogre_paind2(void); void ogre_paind3(void); void ogre_paind4(void); void ogre_paind5(void); void ogre_paind6(void); void ogre_paind7(void); void ogre_paind8(void); void ogre_paind9(void); void ogre_paind10(void); void ogre_paind11(void); void ogre_paind12(void); void ogre_paind13(void); void ogre_paind14(void); void ogre_paind15(void); void ogre_paind16(void); void ogre_paine1(void); void ogre_paine2(void); void ogre_paine3(void); void ogre_paine4(void); void ogre_paine5(void); void ogre_paine6(void); void ogre_paine7(void); void ogre_paine8(void); void ogre_paine9(void); void ogre_paine10(void); void ogre_paine11(void); void ogre_paine12(void); void ogre_paine13(void); void ogre_paine14(void); void ogre_paine15(void); void ogre_die1(void); void ogre_die2(void); void ogre_die3(void); void ogre_die4(void); void ogre_die5(void); void ogre_die6(void); void ogre_die7(void); void ogre_die8(void); void ogre_die9(void); void ogre_die10(void); void ogre_die11(void); void ogre_die12(void); void ogre_die13(void); void ogre_die14(void); void ogre_bdie1(void); void ogre_bdie2(void); void ogre_bdie3(void); void ogre_bdie4(void); void ogre_bdie5(void); void ogre_bdie6(void); void ogre_bdie7(void); void ogre_bdie8(void); void ogre_bdie9(void); void ogre_bdie10(void); //============================================================================= void _ogre_stand5(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "ogre/ogidle.wav", 1, ATTN_IDLE); } ai_stand(); } ANIM(ogre_stand1, stand1, ogre_stand2; ai_stand();) ANIM(ogre_stand2, stand2, ogre_stand3; ai_stand();) ANIM(ogre_stand3, stand3, ogre_stand4; ai_stand();) ANIM(ogre_stand4, stand4, ogre_stand5; ai_stand();) ANIM(ogre_stand5, stand5, ogre_stand6; _ogre_stand5();) ANIM(ogre_stand6, stand6, ogre_stand7; ai_stand();) ANIM(ogre_stand7, stand7, ogre_stand8; ai_stand();) ANIM(ogre_stand8, stand8, ogre_stand9; ai_stand();) ANIM(ogre_stand9, stand9, ogre_stand1; ai_stand();) void _ogre_walk3(void) { ai_walk(2); if (g_random() < 0.2) { sound(self, CHAN_VOICE, "ogre/ogidle.wav", 1, ATTN_IDLE); } } void _ogre_walk6(void) { ai_walk(5); if (g_random() < 0.1) { sound(self, CHAN_VOICE, "ogre/ogdrag.wav", 1, ATTN_IDLE); } } ANIM(ogre_walk1, walk1, ogre_walk2; ai_walk(3);) ANIM(ogre_walk2, walk2, ogre_walk3; ai_walk(2);) ANIM(ogre_walk3, walk3, ogre_walk4; _ogre_walk3();) ANIM(ogre_walk4, walk4, ogre_walk5; ai_walk(2);) ANIM(ogre_walk5, walk5, ogre_walk6; ai_walk(2);) ANIM(ogre_walk6, walk6, ogre_walk7; _ogre_walk6();) ANIM(ogre_walk7, walk7, ogre_walk8; ai_walk(3);) ANIM(ogre_walk8, walk8, ogre_walk9; ai_walk(2);) ANIM(ogre_walk9, walk9, ogre_walk10; ai_walk(3);) ANIM(ogre_walk10, walk10, ogre_walk11; ai_walk(1);) ANIM(ogre_walk11, walk11, ogre_walk12; ai_walk(2);) ANIM(ogre_walk12, walk12, ogre_walk13; ai_walk(3);) ANIM(ogre_walk13, walk13, ogre_walk14; ai_walk(3);) ANIM(ogre_walk14, walk14, ogre_walk15; ai_walk(3);) ANIM(ogre_walk15, walk15, ogre_walk16; ai_walk(3);) ANIM(ogre_walk16, walk16, ogre_walk1; ai_walk(4);) void _ogre_run1(void) { ai_run(9); if (g_random() < 0.2) { sound(self, CHAN_VOICE, "ogre/ogidle2.wav", 1, ATTN_IDLE); } } ANIM(ogre_run1, run1, ogre_run2; _ogre_run1();) ANIM(ogre_run2, run2, ogre_run3; ai_run(12);) ANIM(ogre_run3, run3, ogre_run4; ai_run(8);) ANIM(ogre_run4, run4, ogre_run5; ai_run(22);) ANIM(ogre_run5, run5, ogre_run6; ai_run(16);) ANIM(ogre_run6, run6, ogre_run7; ai_run(4);) ANIM(ogre_run7, run7, ogre_run8; ai_run(13);) ANIM(ogre_run8, run8, ogre_run1; ai_run(24);) void chainsaw(float side) { vec3_t delta, vel; float ldmg; if (!self->s.v.enemy) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } ai_charge(10); VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 100) { return; } ldmg = (g_random() + g_random() + g_random()) * 4; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); // in most cases chainsaw called as chainsaw( 0 ) so side is 0 if (side) { float scale = (side == 1 ? crandom() * 100 : side); trap_makevectors(self->s.v.angles); VectorMA(self->s.v.origin, 16, g_globalvars.v_forward, delta); VectorScale(g_globalvars.v_right, scale, vel); if (side == 1) { SpawnMeatSpray(delta, vel); } else { SpawnMeatSpray(delta, vel); } } } ANIM(ogre_swing1, swing1, ogre_swing2; ai_charge(11); sound( self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM );) ANIM(ogre_swing2, swing2, ogre_swing3; ai_charge(1);) ANIM(ogre_swing3, swing3, ogre_swing4; ai_charge(4);) ANIM(ogre_swing4, swing4, ogre_swing5; ai_charge(13);) ANIM(ogre_swing5, swing5, ogre_swing6; ai_charge(9); chainsaw(0); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing6, swing6, ogre_swing7; chainsaw(200); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing7, swing7, ogre_swing8; chainsaw(0); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing8, swing8, ogre_swing9; chainsaw(0); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing9, swing9, ogre_swing10; chainsaw(0); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing10, swing10, ogre_swing11; chainsaw(-200); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing11, swing11, ogre_swing12; chainsaw(0); self->s.v.angles[1] += g_random() * 25;) ANIM(ogre_swing12, swing12, ogre_swing13; ai_charge(3);) ANIM(ogre_swing13, swing13, ogre_swing14; ai_charge(8);) ANIM(ogre_swing14, swing14, ogre_run1; ai_charge(9);) void _ogre_smash11(void) { ai_charge(2); chainsaw(0); // slight variation self->s.v.nextthink = g_globalvars.time + g_random() * 0.2; } ANIM(ogre_smash1, smash1, ogre_smash2; ai_charge(6); sound( self, CHAN_WEAPON, "ogre/ogsawatk.wav", 1, ATTN_NORM );) ANIM(ogre_smash2, smash2, ogre_smash3; ai_charge(0);) ANIM(ogre_smash3, smash3, ogre_smash4; ai_charge(0);) ANIM(ogre_smash4, smash4, ogre_smash5; ai_charge(1);) ANIM(ogre_smash5, smash5, ogre_smash6; ai_charge(4);) ANIM(ogre_smash6, smash6, ogre_smash7; ai_charge(4); chainsaw(0);) ANIM(ogre_smash7, smash7, ogre_smash8; ai_charge(4); chainsaw(0);) ANIM(ogre_smash8, smash8, ogre_smash9; ai_charge(10); chainsaw(0);) ANIM(ogre_smash9, smash9, ogre_smash10; ai_charge(13); chainsaw(0);) ANIM(ogre_smash10, smash10, ogre_smash11; chainsaw(1);) ANIM(ogre_smash11, smash11, ogre_smash12; _ogre_smash11();) ANIM(ogre_smash12, smash12, ogre_smash13; ai_charge(0);) ANIM(ogre_smash13, smash13, ogre_smash14; ai_charge(4);) ANIM(ogre_smash14, smash14, ogre_run1; ai_charge(12);) void ogre_melee(void) { if (g_random() > 0.5) { ogre_smash1(); } else { ogre_swing1(); } } //============================================================================= void OgreGrenadeExplode(void) { T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 40, world, dtSQUISH); sound(self, CHAN_VOICE, "weapons/r_exp3.wav", 1, ATTN_NORM); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_EXPLOSION); WriteCoord( MSG_BROADCAST, self->s.v.origin[0]); WriteCoord( MSG_BROADCAST, self->s.v.origin[1]); WriteCoord( MSG_BROADCAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } void OgreGrenadeTouch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } if (other->s.v.takedamage == DAMAGE_AIM) { OgreGrenadeExplode(); return; } sound(self, CHAN_VOICE, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound if (VectorCompare(self->s.v.velocity, VEC_ORIGIN)) { VectorCopy(VEC_ORIGIN, self->s.v.avelocity); } } /* ================ OgreFireGrenade ================ */ void OgreFireGrenade(void) { gedict_t *missile; muzzleflash(); sound(self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM); missile = spawn(); missile->s.v.owner = EDICT_TO_PROG(self); missile->s.v.movetype = MOVETYPE_BOUNCE; missile->isMissile = true; missile->s.v.solid = SOLID_BBOX; // set missile speed trap_makevectors(self->s.v.angles); VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, missile->s.v.velocity); normalize(missile->s.v.velocity, missile->s.v.velocity); VectorScale(missile->s.v.velocity, 600, missile->s.v.velocity); missile->s.v.velocity[2] = 200; SetVector(missile->s.v.avelocity, 300, 300, 300); vectoangles(missile->s.v.velocity, missile->s.v.angles); missile->touch = (func_t) OgreGrenadeTouch; // set missile duration missile->s.v.nextthink = g_globalvars.time + 2.5; missile->think = (func_t) OgreGrenadeExplode; setmodel(missile, "progs/grenade.mdl"); setsize(missile, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); setorigin(missile, PASSVEC3(self->s.v.origin)); } ANIM(ogre_nail1, shoot1, ogre_nail2; ai_face();) ANIM(ogre_nail2, shoot2, ogre_nail3; ai_face();) ANIM(ogre_nail3, shoot2, ogre_nail4; ai_face();) ANIM(ogre_nail4, shoot3, ogre_nail5; ai_face(); OgreFireGrenade();) ANIM(ogre_nail5, shoot4, ogre_nail6; ai_face();) ANIM(ogre_nail6, shoot5, ogre_nail7; ai_face();) ANIM(ogre_nail7, shoot6, ogre_run1; ai_face();) //============================================================================= ANIM(ogre_pain1, pain1, ogre_pain2;) ANIM(ogre_pain2, pain2, ogre_pain3;) ANIM(ogre_pain3, pain3, ogre_pain4;) ANIM(ogre_pain4, pain4, ogre_pain5;) ANIM(ogre_pain5, pain5, ogre_run1;) ANIM(ogre_painb1, painb1, ogre_painb2;) ANIM(ogre_painb2, painb2, ogre_painb3;) ANIM(ogre_painb3, painb3, ogre_run1;) ANIM(ogre_painc1, painc1, ogre_painc2;) ANIM(ogre_painc2, painc2, ogre_painc3;) ANIM(ogre_painc3, painc3, ogre_painc4;) ANIM(ogre_painc4, painc4, ogre_painc5;) ANIM(ogre_painc5, painc5, ogre_painc6;) ANIM(ogre_painc6, painc6, ogre_run1;) ANIM(ogre_paind1, paind1, ogre_paind2;) ANIM(ogre_paind2, paind2, ogre_paind3; ai_pain(10);) ANIM(ogre_paind3, paind3, ogre_paind4; ai_pain(9);) ANIM(ogre_paind4, paind4, ogre_paind5; ai_pain(4);) ANIM(ogre_paind5, paind5, ogre_paind6;) ANIM(ogre_paind6, paind6, ogre_paind7;) ANIM(ogre_paind7, paind7, ogre_paind8;) ANIM(ogre_paind8, paind8, ogre_paind9;) ANIM(ogre_paind9, paind9, ogre_paind10;) ANIM(ogre_paind10, paind10, ogre_paind11;) ANIM(ogre_paind11, paind11, ogre_paind12;) ANIM(ogre_paind12, paind12, ogre_paind13;) ANIM(ogre_paind13, paind13, ogre_paind14;) ANIM(ogre_paind14, paind14, ogre_paind15;) ANIM(ogre_paind15, paind15, ogre_paind16;) ANIM(ogre_paind16, paind16, ogre_run1;) ANIM(ogre_paine1, paine1, ogre_paine2;) ANIM(ogre_paine2, paine2, ogre_paine3; ai_pain(10);) ANIM(ogre_paine3, paine3, ogre_paine4; ai_pain(9);) ANIM(ogre_paine4, paine4, ogre_paine5; ai_pain(4);) ANIM(ogre_paine5, paine5, ogre_paine6;) ANIM(ogre_paine6, paine6, ogre_paine7;) ANIM(ogre_paine7, paine7, ogre_paine8;) ANIM(ogre_paine8, paine8, ogre_paine9;) ANIM(ogre_paine9, paine9, ogre_paine10;) ANIM(ogre_paine10, paine10, ogre_paine11;) ANIM(ogre_paine11, paine11, ogre_paine12;) ANIM(ogre_paine12, paine12, ogre_paine13;) ANIM(ogre_paine13, paine13, ogre_paine14;) ANIM(ogre_paine14, paine14, ogre_paine15;) ANIM(ogre_paine15, paine15, ogre_run1;) void ogre_pain(gedict_t *attacker, float damage) { float r; // don't make multiple pain sounds right after each other if (self->pain_finished > g_globalvars.time) { return; } sound(self, CHAN_VOICE, "ogre/ogpain1.wav", 1, ATTN_NORM); r = g_random(); if (r < 0.25) { ogre_pain1(); self->pain_finished = g_globalvars.time + 1; } else if (r < 0.5) { ogre_painb1(); self->pain_finished = g_globalvars.time + 1; } else if (r < 0.75) { ogre_painc1(); self->pain_finished = g_globalvars.time + 1; } else if (r < 0.88) { ogre_paind1(); self->pain_finished = g_globalvars.time + 2; } else { ogre_paine1(); self->pain_finished = g_globalvars.time + 2; } } void ogre_drop_pack(void) { self->s.v.ammo_rockets = 2; // 2 rox in backpack DropBackpack(); } void _ogre_die_xxx(void) { self->s.v.solid = SOLID_NOT; ogre_drop_pack(); } ANIM(ogre_die1, death1, ogre_die2;) ANIM(ogre_die2, death2, ogre_die3;) ANIM(ogre_die3, death3, ogre_die4; _ogre_die_xxx();) ANIM(ogre_die4, death4, ogre_die5;) ANIM(ogre_die5, death5, ogre_die6;) ANIM(ogre_die6, death6, ogre_die7;) ANIM(ogre_die7, death7, ogre_die8;) ANIM(ogre_die8, death8, ogre_die9;) ANIM(ogre_die9, death9, ogre_die10;) ANIM(ogre_die10, death10, ogre_die11;) ANIM(ogre_die11, death11, ogre_die12;) ANIM(ogre_die12, death12, ogre_die13;) ANIM(ogre_die13, death13, ogre_die14;) ANIM(ogre_die14, death14, ogre_die14;) ANIM(ogre_bdie1, bdeath1, ogre_bdie2;) ANIM(ogre_bdie2, bdeath2, ogre_bdie3; ai_forward(5);) ANIM(ogre_bdie3, bdeath3, ogre_bdie4; _ogre_die_xxx();) ANIM(ogre_bdie4, bdeath4, ogre_bdie5; ai_forward(1);) ANIM(ogre_bdie5, bdeath5, ogre_bdie6; ai_forward(3);) ANIM(ogre_bdie6, bdeath6, ogre_bdie7; ai_forward(7);) ANIM(ogre_bdie7, bdeath7, ogre_bdie8; ai_forward(25);) ANIM(ogre_bdie8, bdeath8, ogre_bdie9;) ANIM(ogre_bdie9, bdeath9, ogre_bdie10;) ANIM(ogre_bdie10, bdeath10, ogre_bdie10;) void ogre_die(void) { // check for gib if (self->s.v.health < -80) { ogre_drop_pack(); sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_ogre.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } sound(self, CHAN_VOICE, "ogre/ogdth.wav", 1, ATTN_NORM); if (g_random() < 0.5) { ogre_die1(); } else { ogre_bdie1(); } } //============================================================================= /* =========== OgreCheckAttack The player is in view, so decide to move or launch an attack Returns false if movement should continue ============ */ float OgreCheckAttack(void) { vec3_t spot1, spot2; gedict_t *targ; if (enemy_range == RANGE_MELEE) { if (CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { self->attack_state = AS_MELEE; return true; } } if (g_globalvars.time < self->attack_finished) { return false; } if (!enemy_vis) { return false; } targ = PROG_TO_EDICT(self->s.v.enemy); // see if any entities are in the way of the shot VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); traceline(PASSVEC3(spot1), PASSVEC3(spot2), false, self); if (g_globalvars.trace_inopen && g_globalvars.trace_inwater) { return false; // sight line crossed contents } if (PROG_TO_EDICT(g_globalvars.trace_ent) != targ) { return false; // don't have a clear shot } // missile attack if (enemy_range == RANGE_FAR) { return false; } self->attack_state = AS_MISSILE; SUB_AttackFinished(1 + 2 * g_random()); return true; } //============================================================================= /*QUAKED monster_ogre (1 0 0) (-32 -32 -24) (32 32 64) Ambush */ void SP_monster_ogre(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/ogre.mdl"); safe_precache_model("progs/h_ogre.mdl"); safe_precache_model("progs/grenade.mdl"); safe_precache_sound("ogre/ogdrag.wav"); safe_precache_sound("ogre/ogdth.wav"); safe_precache_sound("ogre/ogidle.wav"); safe_precache_sound("ogre/ogidle2.wav"); safe_precache_sound("ogre/ogpain1.wav"); safe_precache_sound("ogre/ogsawatk.wav"); safe_precache_sound("ogre/ogwake.wav"); setsize(self, PASSVEC3(VEC_HULL2_MIN), PASSVEC3(VEC_HULL2_MAX)); self->s.v.health = 200; self->th_stand = ogre_stand1; self->th_walk = ogre_walk1; self->th_run = ogre_run1; self->th_die = ogre_die; self->th_melee = ogre_melee; self->th_missile = ogre_nail1; self->th_pain = ogre_pain; self->th_respawn = SP_monster_ogre; walkmonster_start("progs/ogre.mdl"); } QW-Group-ktx-d05d6ca/src/sp_oldone.c000066400000000000000000000313171475442401000173520ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== OLD ONE ============================================================================== */ #include "g_local.h" enum { old1, old2, old3, old4, old5, old6, old7, old8, old9, old10, old11, old12, old13, old14, old15, old16, old17, old18, old19, old20, old21, old22, old23, old24, old25, old26, old27, old28, old29, old30, old31, old32, old33, old34, old35, old36, old37, old38, old39, old40, old41, old42, old43, old44, old45, old46, shake1, shake2, shake3, shake4, shake5, shake6, shake7, shake8, shake9, shake10, shake11, shake12, shake13, shake14, shake15, shake16, shake17, shake18, shake19, shake20, }; void old_idle1(void); void old_idle2(void); void old_idle3(void); void old_idle4(void); void old_idle5(void); void old_idle6(void); void old_idle7(void); void old_idle8(void); void old_idle9(void); void old_idle10(void); void old_idle11(void); void old_idle12(void); void old_idle13(void); void old_idle14(void); void old_idle15(void); void old_idle16(void); void old_idle17(void); void old_idle18(void); void old_idle19(void); void old_idle20(void); void old_idle21(void); void old_idle22(void); void old_idle23(void); void old_idle24(void); void old_idle25(void); void old_idle26(void); void old_idle27(void); void old_idle28(void); void old_idle29(void); void old_idle30(void); void old_idle31(void); void old_idle32(void); void old_idle33(void); void old_idle34(void); void old_idle35(void); void old_idle36(void); void old_idle37(void); void old_idle38(void); void old_idle39(void); void old_idle40(void); void old_idle41(void); void old_idle42(void); void old_idle43(void); void old_idle44(void); void old_idle45(void); void old_idle46(void); void old_thrash1(void); void old_thrash2(void); void old_thrash3(void); void old_thrash4(void); void old_thrash5(void); void old_thrash6(void); void old_thrash7(void); void old_thrash8(void); void old_thrash9(void); void old_thrash10(void); void old_thrash11(void); void old_thrash12(void); void old_thrash13(void); void old_thrash14(void); void old_thrash15(void); void old_thrash16(void); void old_thrash17(void); void old_thrash18(void); void old_thrash19(void); void old_thrash20(void); //============================================================================= ANIM(old_idle1, old1, old_idle2;) ANIM(old_idle2, old2, old_idle3;) ANIM(old_idle3, old3, old_idle4;) ANIM(old_idle4, old4, old_idle5;) ANIM(old_idle5, old5, old_idle6;) ANIM(old_idle6, old6, old_idle7;) ANIM(old_idle7, old7, old_idle8;) ANIM(old_idle8, old8, old_idle9;) ANIM(old_idle9, old9, old_idle10;) ANIM(old_idle10, old10, old_idle11;) ANIM(old_idle11, old11, old_idle12;) ANIM(old_idle12, old12, old_idle13;) ANIM(old_idle13, old13, old_idle14;) ANIM(old_idle14, old14, old_idle15;) ANIM(old_idle15, old15, old_idle16;) ANIM(old_idle16, old16, old_idle17;) ANIM(old_idle17, old17, old_idle18;) ANIM(old_idle18, old18, old_idle19;) ANIM(old_idle19, old19, old_idle20;) ANIM(old_idle20, old20, old_idle21;) ANIM(old_idle21, old21, old_idle22;) ANIM(old_idle22, old22, old_idle23;) ANIM(old_idle23, old23, old_idle24;) ANIM(old_idle24, old24, old_idle25;) ANIM(old_idle25, old25, old_idle26;) ANIM(old_idle26, old26, old_idle27;) ANIM(old_idle27, old27, old_idle28;) ANIM(old_idle28, old28, old_idle29;) ANIM(old_idle29, old29, old_idle30;) ANIM(old_idle30, old30, old_idle31;) ANIM(old_idle31, old31, old_idle32;) ANIM(old_idle32, old32, old_idle33;) ANIM(old_idle33, old33, old_idle34;) ANIM(old_idle34, old34, old_idle35;) ANIM(old_idle35, old35, old_idle36;) ANIM(old_idle36, old36, old_idle37;) ANIM(old_idle37, old37, old_idle38;) ANIM(old_idle38, old38, old_idle39;) ANIM(old_idle39, old39, old_idle40;) ANIM(old_idle40, old40, old_idle41;) ANIM(old_idle41, old41, old_idle42;) ANIM(old_idle42, old42, old_idle43;) ANIM(old_idle43, old43, old_idle44;) ANIM(old_idle44, old44, old_idle45;) ANIM(old_idle45, old45, old_idle46;) ANIM(old_idle46, old46, old_idle1;) void finale_1(void); void finale_2(void); void finale_3(void); void finale_4(void); void _old_thrash15(void) { self->cnt++; if (self->cnt < 3) { self->think = (func_t) old_thrash1; } } ANIM(old_thrash1, shake1, old_thrash2; trap_lightstyle(0, "m");) ANIM(old_thrash2, shake2, old_thrash3; trap_lightstyle(0, "k");) ANIM(old_thrash3, shake3, old_thrash4; trap_lightstyle(0, "k");) ANIM(old_thrash4, shake4, old_thrash5; trap_lightstyle(0, "i");) ANIM(old_thrash5, shake5, old_thrash6; trap_lightstyle(0, "g");) ANIM(old_thrash6, shake6, old_thrash7; trap_lightstyle(0, "e");) ANIM(old_thrash7, shake7, old_thrash8; trap_lightstyle(0, "c");) ANIM(old_thrash8, shake8, old_thrash9; trap_lightstyle(0, "a");) ANIM(old_thrash9, shake9, old_thrash10; trap_lightstyle(0, "c");) ANIM(old_thrash10, shake10, old_thrash11; trap_lightstyle(0, "e");) ANIM(old_thrash11, shake11, old_thrash12; trap_lightstyle(0, "g");) ANIM(old_thrash12, shake12, old_thrash13; trap_lightstyle(0, "i");) ANIM(old_thrash13, shake13, old_thrash14; trap_lightstyle(0, "k");) ANIM(old_thrash14, shake14, old_thrash15; trap_lightstyle(0, "m");) ANIM(old_thrash15, shake15, old_thrash16; trap_lightstyle(0, "m"); _old_thrash15();) ANIM(old_thrash16, shake16, old_thrash17; trap_lightstyle(0, "g");) ANIM(old_thrash17, shake17, old_thrash18; trap_lightstyle(0, "c");) ANIM(old_thrash18, shake18, old_thrash19; trap_lightstyle(0, "b");) ANIM(old_thrash19, shake19, old_thrash20; trap_lightstyle(0, "a");) ANIM(old_thrash20, shake20, old_thrash20; finale_4();) //============================================================================ void finale_1(void) { gedict_t *pl; gedict_t *timer; self->s.v.effects = (int)self->s.v.effects | EF_RED; g_globalvars.killed_monsters++; WriteByte( MSG_ALL, SVC_KILLEDMONSTER); pl = ez_find(world, "misc_teleporttrain"); if (!pl) { G_Error("no teleporttrain"); } ent_remove(pl); set_nextmap("start"); // prepare change map to start again g_globalvars.serverflags = (int)g_globalvars.serverflags & ~15; // remove runes intermission_exittime = g_globalvars.time + 45; // never allow exit intermission_running = 1; // find the intermission spot intermission_spot = ez_find(world, "info_intermission"); if (!intermission_spot) { G_Error("no info_intermission"); } // svc_finale is broken in QW, so send svc_intermission first to set view angles // and origin, then send svc_finale to set cl.intermission to 2. WriteByte( MSG_ALL, SVC_INTERMISSION); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[0]); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[1]); WriteCoord( MSG_ALL, intermission_spot->s.v.origin[2]); WriteAngle( MSG_ALL, intermission_spot->mangle[0]); WriteAngle( MSG_ALL, intermission_spot->mangle[1]); WriteAngle( MSG_ALL, intermission_spot->mangle[2]); WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, ""); for (pl = world; (pl = find_plr(pl));) { VectorCopy(VEC_ORIGIN, pl->s.v.view_ofs); //pl->s.v.angles = other.v_angle = intermission_spot.mangle; VectorCopy(intermission_spot->mangle, pl->s.v.angles); VectorCopy(intermission_spot->mangle, /* "other" it was... */pl->s.v.v_angle); pl->s.v.fixangle = true; // turn this way immediately pl->map = self->map; pl->s.v.nextthink = g_globalvars.time + 0.5; pl->s.v.takedamage = DAMAGE_NO; pl->s.v.solid = SOLID_NOT; pl->s.v.movetype = MOVETYPE_NONE; pl->s.v.modelindex = 0; setorigin(pl, PASSVEC3(intermission_spot->s.v.origin)); } // make fake versions of all players as standins, and move the real // players to the intermission spot // wait for 1 second timer = spawn(); timer->s.v.nextthink = g_globalvars.time + 1; timer->think = (func_t) finale_2; } gedict_t* shub_find(char *msg) { gedict_t *shub = ez_find(world, "monster_oldone"); if (!shub) { G_Error("shub_find() null, in %s", msg); } return shub; } void finale_2(void) { vec3_t o; gedict_t *shub = shub_find("finale_2"); // start a teleport splash inside shub //o = shub->s.v.origin - '0 100 0'; VectorCopy(shub->s.v.origin, o); o[1] -= 100; WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_TELEPORT); WriteCoord( MSG_BROADCAST, o[0]); WriteCoord( MSG_BROADCAST, o[1]); WriteCoord( MSG_BROADCAST, o[2]); sound(shub, CHAN_VOICE, "misc/r_tele1.wav", 1, ATTN_NORM); self->s.v.nextthink = g_globalvars.time + 2; self->think = (func_t) finale_3; } void finale_3(void) { gedict_t *shub = shub_find("finale_3"); // start shub thrashing wildly shub->think = (func_t) old_thrash1; shub->s.v.nextthink = g_globalvars.time + 0.01; sound(shub, CHAN_VOICE, "boss2/death.wav", 1, ATTN_NORM); trap_lightstyle(0, "abcdefghijklmlkjihgfedcb"); // remove timer ent it not needed any more ent_remove(self); } void kill_all_monsters(void) { gedict_t *monster; for (monster = world; (monster = nextent(monster));) { if (!((int)monster->s.v.flags & FL_MONSTER)) { continue; // not a monster } if (ISDEAD(monster)) { continue; } monster->deathtype = dtSQUISH; T_Damage(monster, world, world, 50000); } self->think = (func_t) kill_all_monsters; self->s.v.nextthink = g_globalvars.time + 0.2; } void finale_4(void) { // throw tons of meat chunks vec3_t oldo; float x, y, z; float r; gedict_t *n; sound(self, CHAN_VOICE, "boss2/pop2.wav", 1, ATTN_NORM); VectorCopy(self->s.v.origin, oldo); // In QW, we only spawn 18 gibs as opposed to 50 in NetQuake // 50 is too much for QW's MAX_PACKET_ENTITIES = 64 for (z = 16; z <= 144; z += 96) { for (x = -64; x <= 64; x += 64) { for (y = -64; y <= 64; y += 64) { self->s.v.origin[0] = oldo[0] + x; self->s.v.origin[1] = oldo[1] + y; self->s.v.origin[2] = oldo[2] + z; r = g_random(); if (r < 0.3) { n = ThrowGib("progs/gib1.mdl", -999); } else if (r < 0.6) { n = ThrowGib("progs/gib2.mdl", -999); } else { n = ThrowGib("progs/gib3.mdl", -999); } n->s.v.effects = (int)n->s.v.effects | EF_RED; } } } // start the end text WriteByte( MSG_ALL, SVC_FINALE); WriteString( MSG_ALL, "Congratulations and well done! You have\n" "beaten the hideous Shub-Niggurath, and\n" "her hundreds of ugly changelings and\n" "monsters. You have proven that your\n" "skill and your cunning are greater than\n" "all the powers of Quake. You are the\n" "master now. Id Software salutes you.\n" "\n" "o/"); // prepare timer commit genocide in monsters formation n = spawn(); n->think = (func_t) kill_all_monsters; n->s.v.nextthink = g_globalvars.time + 0.01; // put a player model down n = spawn(); setmodel(n, "progs/player.mdl"); setorigin(n, oldo[0] - 32, oldo[1] - 264, oldo[2]); SetVector(n->s.v.angles, 0, 290, 0); n->s.v.frame = 17; n->think = (func_t) player_stand1; n->s.v.nextthink = g_globalvars.time; n->s.v.weapon = IT_AXE; n->s.v.effects = (int)n->s.v.effects | EF_BLUE; ent_remove(self); // switch cd track WriteByte( MSG_ALL, SVC_CDTRACK); WriteByte( MSG_ALL, 3); trap_lightstyle(0, "m"); } //============================================================================ void nopain(gedict_t *attacker, float damage) { self->s.v.health = 40000; // kill by telefrag } //============================================================================ /*QUAKED monster_oldone (1 0 0) (-16 -16 -24) (16 16 32) */ void SP_monster_oldone(void) { if (!AllowMonster(self)) { ent_remove(self); return; } trap_precache_model("progs/oldone.mdl"); trap_precache_sound("boss2/death.wav"); trap_precache_sound("boss2/idle.wav"); trap_precache_sound("boss2/sight.wav"); trap_precache_sound("boss2/pop2.wav"); self->s.v.solid = SOLID_SLIDEBOX; self->s.v.movetype = MOVETYPE_STEP; self->s.v.effects = (int)self->s.v.effects | EF_RED; setmodel(self, "progs/oldone.mdl"); setsize(self, -160, -128, -24, 160, 128, 256); self->s.v.health = 40000; // kill by telefrag self->think = (func_t) old_idle1; self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.takedamage = DAMAGE_YES; self->th_pain = nopain; self->th_die = finale_1; g_globalvars.total_monsters++; } QW-Group-ktx-d05d6ca/src/sp_shalrath.c000066400000000000000000000223541475442401000177010ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== SHAL-RATH ============================================================================== */ #include "g_local.h" enum { attack1, attack2, attack3, attack4, attack5, attack6, attack7, attack8, attack9, attack10, attack11, pain1, pain2, pain3, pain4, pain5, death1, death2, death3, death4, death5, death6, death7, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, }; void shal_stand(void); void shal_walk1(void); void shal_walk2(void); void shal_walk3(void); void shal_walk4(void); void shal_walk5(void); void shal_walk6(void); void shal_walk7(void); void shal_walk8(void); void shal_walk9(void); void shal_walk10(void); void shal_walk11(void); void shal_walk12(void); void shal_run1(void); void shal_run2(void); void shal_run3(void); void shal_run4(void); void shal_run5(void); void shal_run6(void); void shal_run7(void); void shal_run8(void); void shal_run9(void); void shal_run10(void); void shal_run11(void); void shal_run12(void); void shal_attack1(void); void shal_attack2(void); void shal_attack3(void); void shal_attack4(void); void shal_attack5(void); void shal_attack6(void); void shal_attack7(void); void shal_attack8(void); void shal_attack9(void); void shal_attack10(void); void shal_attack11(void); void shal_pain1(void); void shal_pain2(void); void shal_pain3(void); void shal_pain4(void); void shal_pain5(void); void shal_death1(void); void shal_death2(void); void shal_death3(void); void shal_death4(void); void shal_death5(void); void shal_death6(void); void shal_death7(void); //============================================================================= ANIM(shal_stand, walk1, shal_stand; ai_stand();) void _shal_walk1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "shalrath/idle.wav", 1, ATTN_IDLE); } ai_walk(6); } ANIM(shal_walk1, walk2, shal_walk2; _shal_walk1();) ANIM(shal_walk2, walk3, shal_walk3; ai_walk(4);) ANIM(shal_walk3, walk4, shal_walk4; ai_walk(0);) ANIM(shal_walk4, walk5, shal_walk5; ai_walk(0);) ANIM(shal_walk5, walk6, shal_walk6; ai_walk(0);) ANIM(shal_walk6, walk7, shal_walk7; ai_walk(0);) ANIM(shal_walk7, walk8, shal_walk8; ai_walk(5);) ANIM(shal_walk8, walk9, shal_walk9; ai_walk(6);) ANIM(shal_walk9, walk10, shal_walk10; ai_walk(5);) ANIM(shal_walk10, walk11, shal_walk11; ai_walk(0);) ANIM(shal_walk11, walk12, shal_walk12; ai_walk(4);) ANIM(shal_walk12, walk1, shal_walk1; ai_walk(5);) void _shal_run1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "shalrath/idle.wav", 1, ATTN_IDLE); } ai_run(6); } ANIM(shal_run1, walk2, shal_run2; _shal_run1();) ANIM(shal_run2, walk3, shal_run3; ai_run(4);) ANIM(shal_run3, walk4, shal_run4; ai_run(0);) ANIM(shal_run4, walk5, shal_run5; ai_run(0);) ANIM(shal_run5, walk6, shal_run6; ai_run(0);) ANIM(shal_run6, walk7, shal_run7; ai_run(0);) ANIM(shal_run7, walk8, shal_run8; ai_run(5);) ANIM(shal_run8, walk9, shal_run9; ai_run(6);) ANIM(shal_run9, walk10, shal_run10; ai_run(5);) ANIM(shal_run10, walk11, shal_run11; ai_run(0);) ANIM(shal_run11, walk12, shal_run12; ai_run(4);) ANIM(shal_run12, walk1, shal_run1; ai_run(5);) //============================================================================= void ShalMissileTouch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } if (streq(other->classname, "monster_zombie")) { other->deathtype = dtSQUISH; // FIXME T_Damage(other, self, self, 110); } T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 40, world, dtSQUISH); sound(self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_EXPLOSION); WriteCoord( MSG_BROADCAST, self->s.v.origin[0]); WriteCoord( MSG_BROADCAST, self->s.v.origin[1]); WriteCoord( MSG_BROADCAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } void ShalHome(void) { vec3_t dir, vtemp; if (ISDEAD(PROG_TO_EDICT(self->s.v.enemy)) // enemy dead || ((self->spawn_time + (k_bloodfest ? 3 : 25)) < g_globalvars.time)) // flying for too long time { other = world; ShalMissileTouch(); ent_remove(self); // ShalMissileTouch not always remove ent, so ensure it return; } VectorCopy(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, vtemp) vtemp[2] += 10; VectorSubtract(vtemp, self->s.v.origin, dir) normalize(dir, dir); VectorScale(dir, skill == 3 ? 350 : 250, self->s.v.velocity); self->s.v.nextthink = g_globalvars.time + 0.2; self->think = (func_t) ShalHome; } /* ================ ShalMissile ================ */ void ShalMissile(void) { gedict_t *missile; vec3_t dir; float dist, flytime; VectorCopy(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, dir); dir[2] += 10; VectorSubtract(dir, self->s.v.origin, dir); dist = vlen(dir); normalize(dir, dir); flytime = max(0.1, dist * 0.002); // 0.002 is roughtly 1/400 I guess muzzleflash(); sound(self, CHAN_WEAPON, "shalrath/attack2.wav", 1, ATTN_NORM); missile = spawn(); missile->classname = "shalrath_missile"; missile->s.v.owner = EDICT_TO_PROG(self); missile->s.v.solid = SOLID_BBOX; missile->s.v.movetype = MOVETYPE_FLYMISSILE; missile->isMissile = true; setmodel(missile, "progs/v_spike.mdl"); setsize(missile, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); setorigin(missile, self->s.v.origin[0], self->s.v.origin[1], self->s.v.origin[2] + 10); VectorScale(dir, 400, missile->s.v.velocity); SetVector(missile->s.v.avelocity, 300, 300, 300); missile->s.v.nextthink = g_globalvars.time + flytime; missile->think = (func_t) ShalHome; missile->s.v.enemy = self->s.v.enemy; missile->touch = (func_t) ShalMissileTouch; } void _shal_attack1(void) { sound(self, CHAN_VOICE, "shalrath/attack.wav", 1, ATTN_NORM); ai_face(); } ANIM(shal_attack1, attack1, shal_attack2; _shal_attack1();) ANIM(shal_attack2, attack2, shal_attack3; ai_face();) ANIM(shal_attack3, attack3, shal_attack4; ai_face();) ANIM(shal_attack4, attack4, shal_attack5; ai_face();) ANIM(shal_attack5, attack5, shal_attack6; ai_face();) ANIM(shal_attack6, attack6, shal_attack7; ai_face();) ANIM(shal_attack7, attack7, shal_attack8; ai_face();) ANIM(shal_attack8, attack8, shal_attack9; ai_face();) ANIM(shal_attack9, attack9, shal_attack10; ShalMissile();) ANIM(shal_attack10, attack10, shal_attack11; ai_face();) ANIM(shal_attack11, attack11, shal_run1;) ANIM(shal_pain1, pain1, shal_pain2;) ANIM(shal_pain2, pain2, shal_pain3;) ANIM(shal_pain3, pain3, shal_pain4;) ANIM(shal_pain4, pain4, shal_pain5;) ANIM(shal_pain5, pain5, shal_run1;) void shalrath_pain(gedict_t *attacker, float damage) { if (self->pain_finished > g_globalvars.time) { return; } sound(self, CHAN_VOICE, "shalrath/pain.wav", 1, ATTN_NORM); shal_pain1(); self->pain_finished = g_globalvars.time + 3; } ANIM(shal_death1, death1, shal_death2;) ANIM(shal_death2, death2, shal_death3;) ANIM(shal_death3, death3, shal_death4;) ANIM(shal_death4, death4, shal_death5;) ANIM(shal_death5, death5, shal_death6;) ANIM(shal_death6, death6, shal_death7;) ANIM(shal_death7, death7, shal_death7;) void shalrath_die(void) { // check for gib if (self->s.v.health < -90) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_shal.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } sound(self, CHAN_VOICE, "shalrath/death.wav", 1, ATTN_NORM); shal_death1(); self->s.v.solid = SOLID_NOT; } //================================================================= /*QUAKED monster_shalrath (1 0 0) (-32 -32 -24) (32 32 48) Ambush */ void SP_monster_shalrath(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/shalrath.mdl"); safe_precache_model("progs/h_shal.mdl"); safe_precache_model("progs/v_spike.mdl"); safe_precache_sound("shalrath/attack.wav"); safe_precache_sound("shalrath/attack2.wav"); safe_precache_sound("shalrath/death.wav"); safe_precache_sound("shalrath/idle.wav"); safe_precache_sound("shalrath/pain.wav"); safe_precache_sound("shalrath/sight.wav"); setsize(self, PASSVEC3(VEC_HULL2_MIN), PASSVEC3(VEC_HULL2_MAX)); self->s.v.health = 400; self->th_stand = shal_stand; self->th_walk = shal_walk1; self->th_run = shal_run1; self->th_die = shalrath_die; self->th_pain = shalrath_pain; self->th_missile = shal_attack1; self->th_respawn = SP_monster_shalrath; walkmonster_start("progs/shalrath.mdl"); } QW-Group-ktx-d05d6ca/src/sp_shambler.c000066400000000000000000000412221475442401000176630ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== SHAMBLER ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, stand10, stand11, stand12, stand13, stand14, stand15, stand16, stand17, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, run1, run2, run3, run4, run5, run6, smash1, smash2, smash3, smash4, smash5, smash6, smash7, smash8, smash9, smash10, smash11, smash12, swingr1, swingr2, swingr3, swingr4, swingr5, swingr6, swingr7, swingr8, swingr9, swingl1, swingl2, swingl3, swingl4, swingl5, swingl6, swingl7, swingl8, swingl9, magic1, magic2, magic3, magic4, magic5, magic6, magic7, magic8, magic9, magic10, magic11, magic12, pain1, pain2, pain3, pain4, pain5, pain6, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, death11, }; void sham_stand1(void); void sham_stand2(void); void sham_stand3(void); void sham_stand4(void); void sham_stand5(void); void sham_stand6(void); void sham_stand7(void); void sham_stand8(void); void sham_stand9(void); void sham_stand10(void); void sham_stand11(void); void sham_stand12(void); void sham_stand13(void); void sham_stand14(void); void sham_stand15(void); void sham_stand16(void); void sham_stand17(void); void sham_walk1(void); void sham_walk2(void); void sham_walk3(void); void sham_walk4(void); void sham_walk5(void); void sham_walk6(void); void sham_walk7(void); void sham_walk8(void); void sham_walk9(void); void sham_walk10(void); void sham_walk11(void); void sham_walk12(void); void sham_run1(void); void sham_run2(void); void sham_run3(void); void sham_run4(void); void sham_run5(void); void sham_run6(void); void sham_smash1(void); void sham_smash2(void); void sham_smash3(void); void sham_smash4(void); void sham_smash5(void); void sham_smash6(void); void sham_smash7(void); void sham_smash8(void); void sham_smash9(void); void sham_smash10(void); void sham_smash11(void); void sham_smash12(void); void sham_swingl1(void); void sham_swingl2(void); void sham_swingl3(void); void sham_swingl4(void); void sham_swingl5(void); void sham_swingl6(void); void sham_swingl7(void); void sham_swingl8(void); void sham_swingl9(void); void sham_swingr1(void); void sham_swingr2(void); void sham_swingr3(void); void sham_swingr4(void); void sham_swingr5(void); void sham_swingr6(void); void sham_swingr7(void); void sham_swingr8(void); void sham_swingr9(void); void sham_magic1(void); void sham_magic2(void); void sham_magic3(void); void sham_magic4(void); void sham_magic5(void); void sham_magic6(void); void sham_magic9(void); void sham_magic10(void); void sham_magic11(void); void sham_magic12(void); void sham_pain1(void); void sham_pain2(void); void sham_pain3(void); void sham_pain4(void); void sham_pain5(void); void sham_pain6(void); void sham_death1(void); void sham_death2(void); void sham_death3(void); void sham_death4(void); void sham_death5(void); void sham_death6(void); void sham_death7(void); void sham_death8(void); void sham_death9(void); void sham_death10(void); void sham_death11(void); //============================================================================= ANIM(sham_stand1, stand1, sham_stand2; ai_stand();) ANIM(sham_stand2, stand2, sham_stand3; ai_stand();) ANIM(sham_stand3, stand3, sham_stand4; ai_stand();) ANIM(sham_stand4, stand4, sham_stand5; ai_stand();) ANIM(sham_stand5, stand5, sham_stand6; ai_stand();) ANIM(sham_stand6, stand6, sham_stand7; ai_stand();) ANIM(sham_stand7, stand7, sham_stand8; ai_stand();) ANIM(sham_stand8, stand8, sham_stand9; ai_stand();) ANIM(sham_stand9, stand9, sham_stand10; ai_stand();) ANIM(sham_stand10, stand10, sham_stand11; ai_stand();) ANIM(sham_stand11, stand11, sham_stand12; ai_stand();) ANIM(sham_stand12, stand12, sham_stand13; ai_stand();) ANIM(sham_stand13, stand13, sham_stand14; ai_stand();) ANIM(sham_stand14, stand14, sham_stand15; ai_stand();) ANIM(sham_stand15, stand15, sham_stand16; ai_stand();) ANIM(sham_stand16, stand16, sham_stand17; ai_stand();) ANIM(sham_stand17, stand17, sham_stand1; ai_stand();) void _sham_walk12(void) { ai_walk(7); if (g_random() > 0.8) { sound(self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE); } } ANIM(sham_walk1, walk1, sham_walk2; ai_walk(10);) ANIM(sham_walk2, walk2, sham_walk3; ai_walk(9);) ANIM(sham_walk3, walk3, sham_walk4; ai_walk(9);) ANIM(sham_walk4, walk4, sham_walk5; ai_walk(5);) ANIM(sham_walk5, walk5, sham_walk6; ai_walk(6);) ANIM(sham_walk6, walk6, sham_walk7; ai_walk(12);) ANIM(sham_walk7, walk7, sham_walk8; ai_walk(8);) ANIM(sham_walk8, walk8, sham_walk9; ai_walk(3);) ANIM(sham_walk9, walk9, sham_walk10; ai_walk(13);) ANIM(sham_walk10, walk10, sham_walk11; ai_walk(9);) ANIM(sham_walk11, walk11, sham_walk12; ai_walk(7);) ANIM(sham_walk12, walk12, sham_walk1; _sham_walk12();) void _sham_run6(void) { ai_run(20); if (g_random() > 0.8) { sound(self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE); } } ANIM(sham_run1, run1, sham_run2; ai_run(20);) ANIM(sham_run2, run2, sham_run3; ai_run(24);) ANIM(sham_run3, run3, sham_run4; ai_run(20);) ANIM(sham_run4, run4, sham_run5; ai_run(20);) ANIM(sham_run5, run5, sham_run6; ai_run(24);) ANIM(sham_run6, run6, sham_run1; _sham_run6();) void _sham_smash1(void) { sound(self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM); ai_charge(2); } void _sham_smash10(void) { vec3_t delta, org; float ldmg; if (!self->s.v.enemy) { return; } ai_charge(0); VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 100) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } ldmg = (g_random() + g_random() + g_random()) * 40; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); sound(self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM); trap_makevectors(self->s.v.angles); VectorMA(self->s.v.origin, 16, g_globalvars.v_forward, org); VectorScale(g_globalvars.v_right, crandom() * 100, delta); SpawnMeatSpray(org, delta); VectorScale(g_globalvars.v_right, crandom() * 100, delta); SpawnMeatSpray(org, delta); } ANIM(sham_smash1, smash1, sham_smash2; _sham_smash1();) ANIM(sham_smash2, smash2, sham_smash3; ai_charge(6);) ANIM(sham_smash3, smash3, sham_smash4; ai_charge(6);) ANIM(sham_smash4, smash4, sham_smash5; ai_charge(5);) ANIM(sham_smash5, smash5, sham_smash6; ai_charge(4);) ANIM(sham_smash6, smash6, sham_smash7; ai_charge(1);) ANIM(sham_smash7, smash7, sham_smash8; ai_charge(0);) ANIM(sham_smash8, smash8, sham_smash9; ai_charge(0);) ANIM(sham_smash9, smash9, sham_smash10; ai_charge(0);) ANIM(sham_smash10, smash10, sham_smash11; _sham_smash10();) ANIM(sham_smash11, smash11, sham_smash12; ai_charge(5);) ANIM(sham_smash12, smash12, sham_run1; ai_charge(4);) void ShamClaw(float side) { vec3_t delta, org; float ldmg; if (!self->s.v.enemy) { return; } ai_charge(10); VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, self->s.v.origin, delta); if (vlen(delta) > 100) { return; } if (!CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { return; } ldmg = (g_random() + g_random() + g_random()) * 20; PROG_TO_EDICT(self->s.v.enemy)->deathtype = dtSQUISH; // FIXME T_Damage(PROG_TO_EDICT(self->s.v.enemy), self, self, ldmg); sound(self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM); if (side) { trap_makevectors(self->s.v.angles); VectorMA(self->s.v.origin, 16, g_globalvars.v_forward, org); VectorScale(g_globalvars.v_right, side, delta); SpawnMeatSpray(org, delta); } } void _sham_swingl1(void) { sound(self, CHAN_VOICE, "shambler/melee2.wav", 1, ATTN_NORM); ai_charge(5); } void _sham_swingl9(void) { ai_charge(8); if (g_random() < 0.5) // why so complicated, why not just random it at sham_melee(), who knows... { self->think = (func_t) sham_swingr1; } } ANIM(sham_swingl1, swingl1, sham_swingl2; _sham_swingl1();) ANIM(sham_swingl2, swingl2, sham_swingl3; ai_charge(3);) ANIM(sham_swingl3, swingl3, sham_swingl4; ai_charge(7);) ANIM(sham_swingl4, swingl4, sham_swingl5; ai_charge(3);) ANIM(sham_swingl5, swingl5, sham_swingl6; ai_charge(7);) ANIM(sham_swingl6, swingl6, sham_swingl7; ai_charge(9);) ANIM(sham_swingl7, swingl7, sham_swingl8; ai_charge(5); ShamClaw(250);) ANIM(sham_swingl8, swingl8, sham_swingl9; ai_charge(4);) ANIM(sham_swingl9, swingl9, sham_run1; _sham_swingl9();) void _sham_swingr1(void) { sound(self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM); ai_charge(1); } void _sham_swingr9(void) { ai_charge(11); if (g_random() < 0.5) // why so complicated, why not just random it at sham_melee(), who knows... self->think = (func_t) sham_swingl1; } ANIM(sham_swingr1, swingr1, sham_swingr2; _sham_swingr1();) ANIM(sham_swingr2, swingr2, sham_swingr3; ai_charge(8);) ANIM(sham_swingr3, swingr3, sham_swingr4; ai_charge(14);) ANIM(sham_swingr4, swingr4, sham_swingr5; ai_charge(7);) ANIM(sham_swingr5, swingr5, sham_swingr6; ai_charge(3);) ANIM(sham_swingr6, swingr6, sham_swingr7; ai_charge(6);) ANIM(sham_swingr7, swingr7, sham_swingr8; ai_charge(6); ShamClaw(-250);) ANIM(sham_swingr8, swingr8, sham_swingr9; ai_charge(3);) ANIM(sham_swingr9, swingr9, sham_run1; _sham_swingr9();) void sham_melee(void) { float chance; chance = g_random(); if ((chance > 0.6) || (self->s.v.health == 600)) { sham_smash1(); } else if (chance > 0.3) { sham_swingr1(); } else { sham_swingl1(); } } //============================================================================ void CastLightning(void) { vec3_t org, dir; muzzleflash(); ai_face(); // from VectorCopy(self->s.v.origin, org); org[2] += 40; // to VectorCopy(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, dir); dir[2] += 16; VectorSubtract(dir, org, dir); normalize(dir, dir); VectorMA(self->s.v.origin, k_bloodfest && self->bloodfest_boss ? 900 : 600, dir, dir); // trace from -> to traceline(PASSVEC3(org), PASSVEC3(dir), true, self); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_LIGHTNING1); WriteEntity( MSG_BROADCAST, self); WriteCoord( MSG_BROADCAST, org[0]); WriteCoord( MSG_BROADCAST, org[1]); WriteCoord( MSG_BROADCAST, org[2]); WriteCoord( MSG_BROADCAST, g_globalvars.trace_endpos[0]); WriteCoord( MSG_BROADCAST, g_globalvars.trace_endpos[1]); WriteCoord( MSG_BROADCAST, g_globalvars.trace_endpos[2]); LightningDamage(org, g_globalvars.trace_endpos, self, 10); } // shambler's bolt have 3 frames, I guess void sham_bolt(void) { if ((self->s.v.frame == 2) || ((self->spawn_time + 0.7) < g_globalvars.time)) { ent_remove(self); return; } self->s.v.frame = bound(0, self->s.v.frame + 1, 2); self->s.v.nextthink = g_globalvars.time + FRAMETIME; } void _sham_magic3(void) { ai_face(); self->s.v.nextthink = g_globalvars.time + 0.2; // hrm muzzleflash(); ai_face(); // spawn shambler's bolt { gedict_t *o; o = spawn(); o->s.v.owner = EDICT_TO_PROG(self); setmodel(o, "progs/s_light.mdl"); setorigin(o, PASSVEC3(self->s.v.origin)); VectorCopy(self->s.v.angles, o->s.v.angles); o->s.v.nextthink = g_globalvars.time + FRAMETIME; o->think = (func_t) sham_bolt; } } ANIM(sham_magic1, magic1, sham_magic2; ai_face(); sound( self, CHAN_WEAPON, "shambler/sattck1.wav", 1, ATTN_NORM );) ANIM(sham_magic2, magic2, sham_magic3; ai_face();) ANIM(sham_magic3, magic3, sham_magic4; _sham_magic3();) ANIM(sham_magic4, magic4, sham_magic5; muzzleflash();) ANIM(sham_magic5, magic5, sham_magic6; muzzleflash();) ANIM(sham_magic6, magic6, sham_magic9; CastLightning(); sound( self, CHAN_WEAPON, "shambler/sboom.wav", 1, ATTN_NORM );) ANIM(sham_magic9, magic9, sham_magic10; CastLightning();) ANIM(sham_magic10, magic10, sham_magic11; CastLightning();) ANIM(sham_magic11, magic11, sham_magic12; if ( skill == 3 ) CastLightning();) ANIM(sham_magic12, magic12, sham_run1;) ANIM(sham_pain1, pain1, sham_pain2;) ANIM(sham_pain2, pain2, sham_pain3;) ANIM(sham_pain3, pain3, sham_pain4;) ANIM(sham_pain4, pain4, sham_pain5;) ANIM(sham_pain5, pain5, sham_pain6;) ANIM(sham_pain6, pain6, sham_run1;) void sham_pain(gedict_t *attacker, float damage) { if (ISDEAD(self)) { return; // already dying, don't go into pain frame } if (g_random() * 400 > damage) { return; // didn't flinch } if (self->pain_finished > g_globalvars.time) { return; } sound(self, CHAN_VOICE, "shambler/shurt2.wav", 1, ATTN_NORM); self->pain_finished = g_globalvars.time + 2; sham_pain1(); } //============================================================================ ANIM(sham_death1, death1, sham_death2;) ANIM(sham_death2, death2, sham_death3;) ANIM(sham_death3, death3, sham_death4; self->s.v.solid = SOLID_NOT;) ANIM(sham_death4, death4, sham_death5;) ANIM(sham_death5, death5, sham_death6;) ANIM(sham_death6, death6, sham_death7;) ANIM(sham_death7, death7, sham_death8;) ANIM(sham_death8, death8, sham_death9;) ANIM(sham_death9, death9, sham_death10;) ANIM(sham_death10, death10, sham_death11;) ANIM(sham_death11, death11, sham_death11;) void sham_die(void) { // check for gib if (self->s.v.health < -60) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_shams.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "shambler/sdeath.wav", 1, ATTN_NORM); sham_death1(); } //============================================================================= /* =========== ShamCheckAttack The player is in view, so decide to move or launch an attack Returns false if movement should continue ============ */ float ShamCheckAttack(void) { vec3_t spot1, spot2, delta; gedict_t *targ; if (enemy_range == RANGE_MELEE) { if (CanDamage(PROG_TO_EDICT(self->s.v.enemy), self)) { self->attack_state = AS_MELEE; return true; } } if (g_globalvars.time < self->attack_finished) { return false; } if (!enemy_vis) { return false; } targ = PROG_TO_EDICT(self->s.v.enemy); // see if any entities are in the way of the shot VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); VectorSubtract(spot1, spot2, delta); if (vlen(delta) > 600) { return false; } traceline(PASSVEC3(spot1), PASSVEC3(spot2), false, self); if (g_globalvars.trace_inopen && g_globalvars.trace_inwater) { return false; // sight line crossed contents } if (PROG_TO_EDICT(g_globalvars.trace_ent) != targ) { return false; // don't have a clear shot } // missile attack if (enemy_range == RANGE_FAR) { return false; } self->attack_state = AS_MISSILE; SUB_AttackFinished(2 + 2 * g_random()); return true; } //============================================================================ /*QUAKED monster_shambler (1 0 0) (-32 -32 -24) (32 32 64) Ambush */ void SP_monster_shambler(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/shambler.mdl"); safe_precache_model("progs/s_light.mdl"); safe_precache_model("progs/h_shams.mdl"); safe_precache_model("progs/bolt.mdl"); safe_precache_sound("shambler/sattck1.wav"); safe_precache_sound("shambler/sboom.wav"); safe_precache_sound("shambler/sdeath.wav"); safe_precache_sound("shambler/shurt2.wav"); safe_precache_sound("shambler/sidle.wav"); safe_precache_sound("shambler/ssight.wav"); safe_precache_sound("shambler/melee1.wav"); safe_precache_sound("shambler/melee2.wav"); safe_precache_sound("shambler/smack.wav"); setsize(self, PASSVEC3(VEC_HULL2_MIN), PASSVEC3(VEC_HULL2_MAX)); self->s.v.health = 600; self->th_stand = sham_stand1; self->th_walk = sham_walk1; self->th_run = sham_run1; self->th_die = sham_die; self->th_melee = sham_melee; self->th_missile = sham_magic1; self->th_pain = sham_pain; self->th_respawn = SP_monster_shambler; walkmonster_start("progs/shambler.mdl"); } QW-Group-ktx-d05d6ca/src/sp_soldier.c000066400000000000000000000334161475442401000175350ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== SOLDIER / PLAYER ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, death1, death2, death3, death4, death5, death6, death7, death8, death9, death10, deathc1, deathc2, deathc3, deathc4, deathc5, deathc6, deathc7, deathc8, deathc9, deathc10, deathc11, load1, load2, load3, load4, load5, load6, load7, load8, load9, load10, load11, pain1, pain2, pain3, pain4, pain5, pain6, painb1, painb2, painb3, painb4, painb5, painb6, painb7, painb8, painb9, painb10, painb11, painb12, painb13, painb14, painc1, painc2, painc3, painc4, painc5, painc6, painc7, painc8, painc9, painc10, painc11, painc12, painc13, run1, run2, run3, run4, run5, run6, run7, run8, shoot1, shoot2, shoot3, shoot4, shoot5, shoot6, shoot7, shoot8, shoot9, prowl_1, prowl_2, prowl_3, prowl_4, prowl_5, prowl_6, prowl_7, prowl_8, prowl_9, prowl_10, prowl_11, prowl_12, prowl_13, prowl_14, prowl_15, prowl_16, prowl_17, prowl_18, prowl_19, prowl_20, prowl_21, prowl_22, prowl_23, prowl_24, }; void army_stand1(void); void army_stand2(void); void army_stand3(void); void army_stand4(void); void army_stand5(void); void army_stand6(void); void army_stand7(void); void army_stand8(void); void army_walk1(void); void army_walk2(void); void army_walk3(void); void army_walk4(void); void army_walk5(void); void army_walk6(void); void army_walk7(void); void army_walk8(void); void army_walk9(void); void army_walk10(void); void army_walk11(void); void army_walk12(void); void army_walk13(void); void army_walk14(void); void army_walk15(void); void army_walk16(void); void army_walk17(void); void army_walk18(void); void army_walk19(void); void army_walk20(void); void army_walk21(void); void army_walk22(void); void army_walk23(void); void army_walk24(void); void army_run1(void); void army_run2(void); void army_run3(void); void army_run4(void); void army_run5(void); void army_run6(void); void army_run7(void); void army_run8(void); void army_atk1(void); void army_atk2(void); void army_atk3(void); void army_atk4(void); void army_atk5(void); void army_atk6(void); void army_atk7(void); void army_atk8(void); void army_atk9(void); void army_pain1(void); void army_pain2(void); void army_pain3(void); void army_pain4(void); void army_pain5(void); void army_pain6(void); void army_painb1(void); void army_painb2(void); void army_painb3(void); void army_painb4(void); void army_painb5(void); void army_painb6(void); void army_painb7(void); void army_painb8(void); void army_painb9(void); void army_painb10(void); void army_painb11(void); void army_painb12(void); void army_painb13(void); void army_painb14(void); void army_painc1(void); void army_painc2(void); void army_painc3(void); void army_painc4(void); void army_painc5(void); void army_painc6(void); void army_painc7(void); void army_painc8(void); void army_painc9(void); void army_painc10(void); void army_painc11(void); void army_painc12(void); void army_painc13(void); void army_die1(void); void army_die2(void); void army_die3(void); void army_die4(void); void army_die5(void); void army_die6(void); void army_die7(void); void army_die8(void); void army_die9(void); void army_die10(void); void army_cdie1(void); void army_cdie2(void); void army_cdie3(void); void army_cdie4(void); void army_cdie5(void); void army_cdie6(void); void army_cdie7(void); void army_cdie8(void); void army_cdie9(void); void army_cdie10(void); void army_cdie11(void); //============================================================================== ANIM(army_stand1, stand1, army_stand2; ai_stand();) ANIM(army_stand2, stand2, army_stand3; ai_stand();) ANIM(army_stand3, stand3, army_stand4; ai_stand();) ANIM(army_stand4, stand4, army_stand5; ai_stand();) ANIM(army_stand5, stand5, army_stand6; ai_stand();) ANIM(army_stand6, stand6, army_stand7; ai_stand();) ANIM(army_stand7, stand7, army_stand8; ai_stand();) ANIM(army_stand8, stand8, army_stand1; ai_stand();) void _army_walk1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "soldier/idle.wav", 1, ATTN_IDLE); } ai_walk(1); } ANIM(army_walk1, prowl_1, army_walk2; _army_walk1();) ANIM(army_walk2, prowl_2, army_walk3; ai_walk(1);) ANIM(army_walk3, prowl_3, army_walk4; ai_walk(1);) ANIM(army_walk4, prowl_4, army_walk5; ai_walk(1);) ANIM(army_walk5, prowl_5, army_walk6; ai_walk(2);) ANIM(army_walk6, prowl_6, army_walk7; ai_walk(3);) ANIM(army_walk7, prowl_7, army_walk8; ai_walk(4);) ANIM(army_walk8, prowl_8, army_walk9; ai_walk(4);) ANIM(army_walk9, prowl_9, army_walk10; ai_walk(2);) ANIM(army_walk10, prowl_10, army_walk11; ai_walk(2);) ANIM(army_walk11, prowl_11, army_walk12; ai_walk(2);) ANIM(army_walk12, prowl_12, army_walk13; ai_walk(1);) ANIM(army_walk13, prowl_13, army_walk14; ai_walk(0);) ANIM(army_walk14, prowl_14, army_walk15; ai_walk(1);) ANIM(army_walk15, prowl_15, army_walk16; ai_walk(1);) ANIM(army_walk16, prowl_16, army_walk17; ai_walk(1);) ANIM(army_walk17, prowl_17, army_walk18; ai_walk(3);) ANIM(army_walk18, prowl_18, army_walk19; ai_walk(3);) ANIM(army_walk19, prowl_19, army_walk20; ai_walk(3);) ANIM(army_walk20, prowl_20, army_walk21; ai_walk(3);) ANIM(army_walk21, prowl_21, army_walk22; ai_walk(2);) ANIM(army_walk22, prowl_22, army_walk23; ai_walk(1);) ANIM(army_walk23, prowl_23, army_walk24; ai_walk(1);) ANIM(army_walk24, prowl_24, army_walk1; ai_walk(1);) void _army_run1(void) { if (g_random() < 0.2) { sound(self, CHAN_VOICE, "soldier/idle.wav", 1, ATTN_IDLE); } ai_run(11); } ANIM(army_run1, run1, army_run2; _army_run1();) ANIM(army_run2, run2, army_run3; ai_run(15);) ANIM(army_run3, run3, army_run4; ai_run(10);) ANIM(army_run4, run4, army_run5; ai_run(10);) ANIM(army_run5, run5, army_run6; ai_run(8);) ANIM(army_run6, run6, army_run7; ai_run(15);) ANIM(army_run7, run7, army_run8; ai_run(10);) ANIM(army_run8, run8, army_run1; ai_run(8);) void army_fire(void) { vec3_t dir; gedict_t *en; ai_face(); sound(self, CHAN_WEAPON, "soldier/sattck1.wav", 1, ATTN_NORM); // fire somewhat behind the player, so a dodging player is harder to hit en = PROG_TO_EDICT(self->s.v.enemy); //dir = en->s.v.origin - en->s.v.velocity * 0.2; VectorMA(en->s.v.origin, -0.2, en->s.v.velocity, dir); //dir = normalize (dir - self->s.v.origin); VectorSubtract(dir, self->s.v.origin, dir); normalize(dir, dir); FireBullets(4, dir, 0.1, 0.1, 0, dtSQUISH /* FIXME */); } ANIM(army_atk1, shoot1, army_atk2; ai_face();) ANIM(army_atk2, shoot2, army_atk3; ai_face();) ANIM(army_atk3, shoot3, army_atk4; ai_face();) ANIM(army_atk4, shoot4, army_atk5; ai_face();) ANIM(army_atk5, shoot5, army_atk6; ai_face(); army_fire(); muzzleflash();) ANIM(army_atk6, shoot6, army_atk7; ai_face();) ANIM(army_atk7, shoot7, army_atk8; ai_face(); SUB_CheckRefire(( func_t) army_atk1);) ANIM(army_atk8, shoot8, army_atk9; ai_face();) ANIM(army_atk9, shoot9, army_run1; ai_face();) ANIM(army_pain1, pain1, army_pain2;) ANIM(army_pain2, pain2, army_pain3;) ANIM(army_pain3, pain3, army_pain4;) ANIM(army_pain4, pain4, army_pain5;) ANIM(army_pain5, pain5, army_pain6;) ANIM(army_pain6, pain6, army_run1; ai_pain(1);) ANIM(army_painb1, painb1, army_painb2;) ANIM(army_painb2, painb2, army_painb3; ai_painforward(13);) ANIM(army_painb3, painb3, army_painb4; ai_painforward(9);) ANIM(army_painb4, painb4, army_painb5;) ANIM(army_painb5, painb5, army_painb6;) ANIM(army_painb6, painb6, army_painb7;) ANIM(army_painb7, painb7, army_painb8;) ANIM(army_painb8, painb8, army_painb9;) ANIM(army_painb9, painb9, army_painb10;) ANIM(army_painb10, painb10, army_painb11;) ANIM(army_painb11, painb11, army_painb12;) ANIM(army_painb12, painb12, army_painb13; ai_pain(2);) ANIM(army_painb13, painb13, army_painb14;) ANIM(army_painb14, painb14, army_run1;) ANIM(army_painc1, painc1, army_painc2;) ANIM(army_painc2, painc2, army_painc3; ai_pain(1);) ANIM(army_painc3, painc3, army_painc4;) ANIM(army_painc4, painc4, army_painc5;) ANIM(army_painc5, painc5, army_painc6; ai_painforward(1);) ANIM(army_painc6, painc6, army_painc7; ai_painforward(1);) ANIM(army_painc7, painc7, army_painc8;) ANIM(army_painc8, painc8, army_painc9; ai_pain(1);) ANIM(army_painc9, painc9, army_painc10; ai_painforward(4);) ANIM(army_painc10, painc10, army_painc11; ai_painforward(3);) ANIM(army_painc11, painc11, army_painc12; ai_painforward(6);) ANIM(army_painc12, painc12, army_painc13; ai_painforward(8);) ANIM(army_painc13, painc13, army_run1;) void army_pain(gedict_t *attacker, float damage) { float r; if (self->pain_finished > g_globalvars.time) { return; } r = g_random(); if (r < 0.2) { self->pain_finished = g_globalvars.time + 0.6; army_pain1(); sound(self, CHAN_VOICE, "soldier/pain1.wav", 1, ATTN_NORM); } else if (r < 0.6) { self->pain_finished = g_globalvars.time + 1.1; army_painb1(); sound(self, CHAN_VOICE, "soldier/pain2.wav", 1, ATTN_NORM); } else { self->pain_finished = g_globalvars.time + 1.1; army_painc1(); sound(self, CHAN_VOICE, "soldier/pain2.wav", 1, ATTN_NORM); } } void army_drop_pack(void) { self->s.v.ammo_shells = 5; // drop packwith 5 shells DropBackpack(); } void army_die_xxx(void) { self->s.v.solid = SOLID_NOT; army_drop_pack(); } ANIM(army_die1, death1, army_die2;) ANIM(army_die2, death2, army_die3;) ANIM(army_die3, death3, army_die4; army_die_xxx();) ANIM(army_die4, death4, army_die5;) ANIM(army_die5, death5, army_die6;) ANIM(army_die6, death6, army_die7;) ANIM(army_die7, death7, army_die8;) ANIM(army_die8, death8, army_die9;) ANIM(army_die9, death9, army_die10;) ANIM(army_die10, death10, army_die10;) ANIM(army_cdie1, deathc1, army_cdie2;) ANIM(army_cdie2, deathc2, army_cdie3; ai_back(5);) ANIM(army_cdie3, deathc3, army_cdie4; ai_back(4); army_die_xxx();) ANIM(army_cdie4, deathc4, army_cdie5; ai_back(13);) ANIM(army_cdie5, deathc5, army_cdie6; ai_back(3);) ANIM(army_cdie6, deathc6, army_cdie7; ai_back(4);) ANIM(army_cdie7, deathc7, army_cdie8;) ANIM(army_cdie8, deathc8, army_cdie9;) ANIM(army_cdie9, deathc9, army_cdie10;) ANIM(army_cdie10, deathc10, army_cdie11;) ANIM(army_cdie11, deathc11, army_cdie11;) void army_die(void) { // check for gib if (self->s.v.health < -35) { army_drop_pack(); sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_guard.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } // regular death sound(self, CHAN_VOICE, "soldier/death1.wav", 1, ATTN_NORM); if (g_random() < 0.5) { army_die1(); } else { army_cdie1(); } } //============================================================================ /* =========== SoldierCheckAttack The player is in view, so decide to move or launch an attack Returns false if movement should continue ============ */ float SoldierCheckAttack(void) { vec3_t spot1, spot2; gedict_t *targ; float chance; if (g_globalvars.time < self->attack_finished) { return false; } targ = PROG_TO_EDICT(self->s.v.enemy); // see if any entities are in the way of the shot VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); traceline(PASSVEC3(spot1), PASSVEC3(spot2), false, self); if (g_globalvars.trace_inopen && g_globalvars.trace_inwater) { return false; // sight line crossed contents } if ( PROG_TO_EDICT(g_globalvars.trace_ent) != targ) { return false; // don't have a clear shot } // missile attack if (enemy_range == RANGE_FAR) { return false; } if (enemy_range == RANGE_MELEE) { chance = 0.9; } else if (enemy_range == RANGE_NEAR) { chance = 0.4; } else if (enemy_range == RANGE_MID) { chance = 0.05; } else { chance = 0; } if (g_random() < chance) { if (self->th_missile) { self->th_missile(); } SUB_AttackFinished(1 + g_random()); if (g_random() < 0.3) { self->lefty = !self->lefty; } return true; } return false; } //============================================================================ /*QUAKED monster_army (1 0 0) (-16 -16 -24) (16 16 40) Ambush */ void SP_monster_army(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/soldier.mdl"); safe_precache_model("progs/h_guard.mdl"); safe_precache_model("progs/gib1.mdl"); safe_precache_model("progs/gib2.mdl"); safe_precache_model("progs/gib3.mdl"); safe_precache_sound("soldier/death1.wav"); safe_precache_sound("soldier/idle.wav"); safe_precache_sound("soldier/pain1.wav"); safe_precache_sound("soldier/pain2.wav"); safe_precache_sound("soldier/sattck1.wav"); safe_precache_sound("soldier/sight1.wav"); safe_precache_sound("player/udeath.wav"); // gib death setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 30; self->th_stand = army_stand1; self->th_walk = army_walk1; self->th_run = army_run1; self->th_missile = army_atk1; self->th_pain = army_pain; self->th_die = army_die; self->th_respawn = SP_monster_army; walkmonster_start("progs/soldier.mdl"); } QW-Group-ktx-d05d6ca/src/sp_tarbaby.c000066400000000000000000000233271475442401000175200ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== BLOB ============================================================================== */ #include "g_local.h" enum { walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, walk17, walk18, walk19, walk20, walk21, walk22, walk23, walk24, walk25, run1, run2, run3, run4, run5, run6, run7, run8, run9, run10, run11, run12, run13, run14, run15, run16, run17, run18, run19, run20, run21, run22, run23, run24, run25, jump1, jump2, jump3, jump4, jump5, jump6, fly1, fly2, fly3, fly4, exp1, }; void tbaby_stand1(void); void tbaby_stand2(void); void tbaby_stand3(void); void tbaby_stand4(void); void tbaby_walk1(void); void tbaby_walk2(void); void tbaby_walk3(void); void tbaby_walk4(void); void tbaby_walk5(void); void tbaby_walk6(void); void tbaby_walk7(void); void tbaby_walk8(void); void tbaby_walk9(void); void tbaby_walk10(void); void tbaby_walk11(void); void tbaby_walk12(void); void tbaby_walk13(void); void tbaby_walk14(void); void tbaby_walk15(void); void tbaby_walk16(void); void tbaby_walk17(void); void tbaby_walk18(void); void tbaby_walk19(void); void tbaby_walk20(void); void tbaby_walk21(void); void tbaby_walk22(void); void tbaby_walk23(void); void tbaby_walk24(void); void tbaby_walk25(void); void tbaby_run1(void); void tbaby_run2(void); void tbaby_run3(void); void tbaby_run4(void); void tbaby_run5(void); void tbaby_run6(void); void tbaby_run7(void); void tbaby_run8(void); void tbaby_run9(void); void tbaby_run10(void); void tbaby_run11(void); void tbaby_run12(void); void tbaby_run13(void); void tbaby_run14(void); void tbaby_run15(void); void tbaby_run16(void); void tbaby_run17(void); void tbaby_run18(void); void tbaby_run19(void); void tbaby_run20(void); void tbaby_run21(void); void tbaby_run22(void); void tbaby_run23(void); void tbaby_run24(void); void tbaby_run25(void); void tbaby_fly1(void); void tbaby_fly2(void); void tbaby_fly3(void); void tbaby_fly4(void); void tbaby_jump1(void); void tbaby_jump2(void); void tbaby_jump3(void); void tbaby_jump4(void); void tbaby_jump5(void); void tbaby_jump6(void); void tbaby_die1(void); void tbaby_die2(void); //============================================================================ // qqshka: well, in original quake tarbaby have single stand frame = walk1, // that was boring so I replaced it with few frames of run sequence. ANIM(tbaby_stand1, run1, tbaby_stand2; ai_stand();) ANIM(tbaby_stand2, run2, tbaby_stand3; ai_stand();) ANIM(tbaby_stand3, run3, tbaby_stand4; ai_stand();) ANIM(tbaby_stand4, run2, tbaby_stand1; ai_stand();) ANIM(tbaby_walk1, walk1, tbaby_walk2; ai_turn();) ANIM(tbaby_walk2, walk2, tbaby_walk3; ai_turn();) ANIM(tbaby_walk3, walk3, tbaby_walk4; ai_turn();) ANIM(tbaby_walk4, walk4, tbaby_walk5; ai_turn();) ANIM(tbaby_walk5, walk5, tbaby_walk6; ai_turn();) ANIM(tbaby_walk6, walk6, tbaby_walk7; ai_turn();) ANIM(tbaby_walk7, walk7, tbaby_walk8; ai_turn();) ANIM(tbaby_walk8, walk8, tbaby_walk9; ai_turn();) ANIM(tbaby_walk9, walk9, tbaby_walk10; ai_turn();) ANIM(tbaby_walk10, walk10, tbaby_walk11; ai_turn();) ANIM(tbaby_walk11, walk11, tbaby_walk12; ai_walk(2);) ANIM(tbaby_walk12, walk12, tbaby_walk13; ai_walk(2);) ANIM(tbaby_walk13, walk13, tbaby_walk14; ai_walk(2);) ANIM(tbaby_walk14, walk14, tbaby_walk15; ai_walk(2);) ANIM(tbaby_walk15, walk15, tbaby_walk16; ai_walk(2);) ANIM(tbaby_walk16, walk16, tbaby_walk17; ai_walk(2);) ANIM(tbaby_walk17, walk17, tbaby_walk18; ai_walk(2);) ANIM(tbaby_walk18, walk18, tbaby_walk19; ai_walk(2);) ANIM(tbaby_walk19, walk19, tbaby_walk20; ai_walk(2);) ANIM(tbaby_walk20, walk20, tbaby_walk21; ai_walk(2);) ANIM(tbaby_walk21, walk21, tbaby_walk22; ai_walk(2);) ANIM(tbaby_walk22, walk22, tbaby_walk23; ai_walk(2);) ANIM(tbaby_walk23, walk23, tbaby_walk24; ai_walk(2);) ANIM(tbaby_walk24, walk24, tbaby_walk25; ai_walk(2);) ANIM(tbaby_walk25, walk25, tbaby_walk1; ai_walk(2);) ANIM(tbaby_run1, run1, tbaby_run2; ai_face();) ANIM(tbaby_run2, run2, tbaby_run3; ai_face();) ANIM(tbaby_run3, run3, tbaby_run4; ai_face();) ANIM(tbaby_run4, run4, tbaby_run5; ai_face();) ANIM(tbaby_run5, run5, tbaby_run6; ai_face();) ANIM(tbaby_run6, run6, tbaby_run7; ai_face();) ANIM(tbaby_run7, run7, tbaby_run8; ai_face();) ANIM(tbaby_run8, run8, tbaby_run9; ai_face();) ANIM(tbaby_run9, run9, tbaby_run10; ai_face();) ANIM(tbaby_run10, run10, tbaby_run11; ai_face();) ANIM(tbaby_run11, run11, tbaby_run12; ai_run(2);) ANIM(tbaby_run12, run12, tbaby_run13; ai_run(2);) ANIM(tbaby_run13, run13, tbaby_run14; ai_run(2);) ANIM(tbaby_run14, run14, tbaby_run15; ai_run(2);) ANIM(tbaby_run15, run15, tbaby_run16; ai_run(2);) ANIM(tbaby_run16, run16, tbaby_run17; ai_run(2);) ANIM(tbaby_run17, run17, tbaby_run18; ai_run(2);) ANIM(tbaby_run18, run18, tbaby_run19; ai_run(2);) ANIM(tbaby_run19, run19, tbaby_run20; ai_run(2);) ANIM(tbaby_run20, run20, tbaby_run21; ai_run(2);) ANIM(tbaby_run21, run21, tbaby_run22; ai_run(2);) ANIM(tbaby_run22, run22, tbaby_run23; ai_run(2);) ANIM(tbaby_run23, run23, tbaby_run24; ai_run(2);) ANIM(tbaby_run24, run24, tbaby_run25; ai_run(2);) ANIM(tbaby_run25, run25, tbaby_run1; ai_run(2);) //============================================================================ void Tar_JumpTouch(void) { float ldmg; if (other->s.v.takedamage && strneq(other->classname, self->classname)) { if (vlen(self->s.v.velocity) > 400) { ldmg = 10 + 10 * g_random(); other->deathtype = dtSQUISH; // FIXME T_Damage(other, self, self, ldmg); sound(self, CHAN_WEAPON, "blob/hit1.wav", 1, ATTN_NORM); } } else { sound(self, CHAN_WEAPON, "blob/land1.wav", 1, ATTN_NORM); } if (!checkbottom(self)) { if ((int)self->s.v.flags & FL_ONGROUND) { // jump randomly to not get hung up //dprint ("popjump\n"); self->touch = (func_t) SUB_Null; self->think = (func_t) tbaby_run1; self->s.v.movetype = MOVETYPE_STEP; self->s.v.nextthink = g_globalvars.time + FRAMETIME; // self->s.v.velocity[0] = (g_random() - 0.5) * 600; // self->s.v.velocity[1] = (g_random() - 0.5) * 600; // self->s.v.velocity[2] = 200; // self.flags = self.flags - FL_ONGROUND; } return; // not on ground yet } self->touch = (func_t) SUB_Null; self->think = (func_t) tbaby_run1; self->s.v.nextthink = g_globalvars.time + FRAMETIME; } void _tbaby_fly4(void) { self->cnt = bound(0, self->cnt + 1, 4); if (self->cnt >= 4) { //dprint ("spawn hop\n"); // tbaby_jump5 (); tbaby_run1(); } } ANIM(tbaby_fly1, fly1, tbaby_fly2;) ANIM(tbaby_fly2, fly2, tbaby_fly3;) ANIM(tbaby_fly3, fly3, tbaby_fly4;) ANIM(tbaby_fly4, fly4, tbaby_fly1; _tbaby_fly4();) void _tbaby_jump5(void) { self->s.v.movetype = MOVETYPE_BOUNCE; self->touch = (func_t) Tar_JumpTouch; trap_makevectors(self->s.v.angles); self->s.v.origin[2] += 1; // FIXME: possibile stuck in walls, right? //self->s.v.velocity = v_forward * 600 + '0 0 200'; VectorScale(g_globalvars.v_forward, 600, self->s.v.velocity); self->s.v.velocity[2] += 200 + g_random() * 150; self->s.v.flags = (int)self->s.v.flags & ~FL_ONGROUND; self->cnt = 0; // this will be used in _tbaby_fly4() } ANIM(tbaby_jump1, jump1, tbaby_jump2; ai_face();) ANIM(tbaby_jump2, jump2, tbaby_jump3; ai_face();) ANIM(tbaby_jump3, jump3, tbaby_jump4; ai_face();) ANIM(tbaby_jump4, jump4, tbaby_jump5; ai_face();) ANIM(tbaby_jump5, jump5, tbaby_jump6; _tbaby_jump5();) ANIM(tbaby_jump6, jump6, tbaby_fly1;) //============================================================================= void _tbaby_die2(void) { vec3_t tmpv; T_RadiusDamage(self, self, 120, world, dtSQUISH /* FIXME */); sound(self, CHAN_VOICE, "blob/death1.wav", 1, ATTN_NORM); //self->s.v.origin = self->s.v.origin - 8*normalize(self->s.v.velocity); normalize(self->s.v.velocity, tmpv); VectorMA(self->s.v.origin, -8, tmpv, self->s.v.origin); WriteByte( MSG_BROADCAST, SVC_TEMPENTITY); WriteByte( MSG_BROADCAST, TE_TAREXPLOSION); WriteCoord( MSG_BROADCAST, self->s.v.origin[0]); WriteCoord( MSG_BROADCAST, self->s.v.origin[1]); WriteCoord( MSG_BROADCAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } ANIM(tbaby_die1, exp1, tbaby_die2; self->s.v.takedamage = DAMAGE_NO;) ANIM(tbaby_die2, exp1, tbaby_die2; _tbaby_die2();) //============================================================================= /*QUAKED monster_tarbaby (1 0 0) (-16 -16 -24) (16 16 24) Ambush */ void SP_monster_tarbaby(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/tarbaby.mdl"); safe_precache_sound("blob/death1.wav"); safe_precache_sound("blob/hit1.wav"); safe_precache_sound("blob/land1.wav"); safe_precache_sound("blob/sight1.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 80; self->th_stand = tbaby_stand1; self->th_walk = tbaby_walk1; self->th_run = tbaby_run1; self->th_missile = tbaby_jump1; self->th_melee = tbaby_jump1; self->th_die = tbaby_die1; self->th_respawn = SP_monster_tarbaby; walkmonster_start("progs/tarbaby.mdl"); } QW-Group-ktx-d05d6ca/src/sp_wizard.c000066400000000000000000000303111475442401000173630ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== WIZARD ============================================================================== */ #include "g_local.h" enum { hover1, hover2, hover3, hover4, hover5, hover6, hover7, hover8, hover9, hover10, hover11, hover12, hover13, hover14, hover15, fly1, fly2, fly3, fly4, fly5, fly6, fly7, fly8, fly9, fly10, fly11, fly12, fly13, fly14, magatt1, magatt2, magatt3, magatt4, magatt5, magatt6, magatt7, magatt8, magatt9, magatt10, magatt11, magatt12, magatt13, pain1, pain2, pain3, pain4, death1, death2, death3, death4, death5, death6, death7, death8, }; void wiz_stand1(void); void wiz_stand2(void); void wiz_stand3(void); void wiz_stand4(void); void wiz_stand5(void); void wiz_stand6(void); void wiz_stand7(void); void wiz_stand8(void); void wiz_walk1(void); void wiz_walk2(void); void wiz_walk3(void); void wiz_walk4(void); void wiz_walk5(void); void wiz_walk6(void); void wiz_walk7(void); void wiz_walk8(void); void wiz_side1(void); void wiz_side2(void); void wiz_side3(void); void wiz_side4(void); void wiz_side5(void); void wiz_side6(void); void wiz_side7(void); void wiz_side8(void); void wiz_run1(void); void wiz_run2(void); void wiz_run3(void); void wiz_run4(void); void wiz_run5(void); void wiz_run6(void); void wiz_run7(void); void wiz_run8(void); void wiz_run9(void); void wiz_run10(void); void wiz_run11(void); void wiz_run12(void); void wiz_run13(void); void wiz_run14(void); void wiz_fast1(void); void wiz_fast2(void); void wiz_fast3(void); void wiz_fast4(void); void wiz_fast5(void); void wiz_fast6(void); void wiz_fast7(void); void wiz_fast8(void); void wiz_fast9(void); void wiz_fast10(void); void wiz_pain1(void); void wiz_pain2(void); void wiz_pain3(void); void wiz_pain4(void); void wiz_death1(void); void wiz_death2(void); void wiz_death3(void); void wiz_death4(void); void wiz_death5(void); void wiz_death6(void); void wiz_death7(void); void wiz_death8(void); /* ============================================================================== FAST ATTACKS ============================================================================== */ void Wiz_IdleSound(void) { float wr = g_random() * 5; // if (self->waitmin < g_globalvars.time) // { // self->waitmin = g_globalvars.time + 2; if (wr > 4.5) { sound(self, CHAN_VOICE, "wizard/widle1.wav", 1, ATTN_IDLE); } else if (wr < 0.5) { sound(self, CHAN_VOICE, "wizard/widle2.wav", 1, ATTN_IDLE); } // } } ANIM(wiz_stand1, hover1, wiz_stand2; ai_stand();) ANIM(wiz_stand2, hover2, wiz_stand3; ai_stand();) ANIM(wiz_stand3, hover3, wiz_stand4; ai_stand();) ANIM(wiz_stand4, hover4, wiz_stand5; ai_stand();) ANIM(wiz_stand5, hover5, wiz_stand6; ai_stand();) ANIM(wiz_stand6, hover6, wiz_stand7; ai_stand();) ANIM(wiz_stand7, hover7, wiz_stand8; ai_stand();) ANIM(wiz_stand8, hover8, wiz_stand1; ai_stand();) ANIM(wiz_walk1, hover1, wiz_walk2; ai_walk(8); Wiz_IdleSound();) ANIM(wiz_walk2, hover2, wiz_walk3; ai_walk(8);) ANIM(wiz_walk3, hover3, wiz_walk4; ai_walk(8);) ANIM(wiz_walk4, hover4, wiz_walk5; ai_walk(8);) ANIM(wiz_walk5, hover5, wiz_walk6; ai_walk(8);) ANIM(wiz_walk6, hover6, wiz_walk7; ai_walk(8);) ANIM(wiz_walk7, hover7, wiz_walk8; ai_walk(8);) ANIM(wiz_walk8, hover8, wiz_walk1; ai_walk(8);) ANIM(wiz_side1, hover1, wiz_side2; ai_run(8); Wiz_IdleSound();) ANIM(wiz_side2, hover2, wiz_side3; ai_run(8);) ANIM(wiz_side3, hover3, wiz_side4; ai_run(8);) ANIM(wiz_side4, hover4, wiz_side5; ai_run(8);) ANIM(wiz_side5, hover5, wiz_side6; ai_run(8);) ANIM(wiz_side6, hover6, wiz_side7; ai_run(8);) ANIM(wiz_side7, hover7, wiz_side8; ai_run(8);) ANIM(wiz_side8, hover8, wiz_side1; ai_run(8);) ANIM(wiz_run1, fly1, wiz_run2; ai_run(16); Wiz_IdleSound();) ANIM(wiz_run2, fly2, wiz_run3; ai_run(16);) ANIM(wiz_run3, fly3, wiz_run4; ai_run(16);) ANIM(wiz_run4, fly4, wiz_run5; ai_run(16);) ANIM(wiz_run5, fly5, wiz_run6; ai_run(16);) ANIM(wiz_run6, fly6, wiz_run7; ai_run(16);) ANIM(wiz_run7, fly7, wiz_run8; ai_run(16);) ANIM(wiz_run8, fly8, wiz_run9; ai_run(16);) ANIM(wiz_run9, fly9, wiz_run10; ai_run(16);) ANIM(wiz_run10, fly10, wiz_run11; ai_run(16);) ANIM(wiz_run11, fly11, wiz_run12; ai_run(16);) ANIM(wiz_run12, fly12, wiz_run13; ai_run(16);) ANIM(wiz_run13, fly13, wiz_run14; ai_run(16);) ANIM(wiz_run14, fly14, wiz_run1; ai_run(16);) void Wiz_FastFire(void) { vec3_t vec; vec3_t dst; gedict_t *oself; // owner is wizard. // self is missile. if (ISLIVE(PROG_TO_EDICT(self->s.v.owner))) { oself = self; // remember self = PROG_TO_EDICT(self->s.v.owner); muzzleflash(); self = oself; // restore ///////trap_makevectors( PROG_TO_EDICT(self->s.v.enemy)->s.v.angles); //dst = self->s.v.enemy->s.v.origin - 13*self->s.v.movedir; VectorMA( PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, -13, self->s.v.movedir, dst); //vec = normalize(dst - self->s.v.origin); VectorSubtract(dst, self->s.v.origin, vec); normalize(vec, vec); sound(self, CHAN_WEAPON, "wizard/wattack.wav", 1, ATTN_NORM); launch_spike(self->s.v.origin, vec); VectorScale(vec, 600, newmis->s.v.velocity); newmis->s.v.owner = self->s.v.owner; newmis->classname = "wizspike"; setmodel(newmis, "progs/w_spike.mdl"); setsize(newmis, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); } ent_remove(self); } void Wiz_StartFast(void) { gedict_t *missile; sound(self, CHAN_WEAPON, "wizard/wattack.wav", 1, ATTN_NORM); VectorCopy(self->s.v.angles, self->s.v.v_angle) trap_makevectors(self->s.v.angles); missile = spawn(); missile->s.v.owner = EDICT_TO_PROG(self); setsize(missile, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); //self->s.v.origin + '0 0 30' + v_forward * 14 + v_right * 14 VectorCopy(self->s.v.origin, missile->s.v.origin); missile->s.v.origin[2] += 30; VectorMA(missile->s.v.origin, 14, g_globalvars.v_forward, missile->s.v.origin); VectorMA(missile->s.v.origin, 14, g_globalvars.v_right, missile->s.v.origin); setorigin(missile, PASSVEC3(missile->s.v.origin)); missile->s.v.enemy = self->s.v.enemy; missile->s.v.nextthink = g_globalvars.time + 0.8; missile->think = (func_t) Wiz_FastFire; VectorCopy(g_globalvars.v_right, missile->s.v.movedir); missile = spawn(); missile->s.v.owner = EDICT_TO_PROG(self); setsize(missile, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); //self->s.v.origin + '0 0 30' + v_forward * 14 + v_right * -14 VectorCopy(self->s.v.origin, missile->s.v.origin); missile->s.v.origin[2] += 30; VectorMA(missile->s.v.origin, 14, g_globalvars.v_forward, missile->s.v.origin); VectorMA(missile->s.v.origin, -14, g_globalvars.v_right, missile->s.v.origin); setorigin(missile, PASSVEC3(missile->s.v.origin)); missile->s.v.enemy = self->s.v.enemy; missile->s.v.nextthink = g_globalvars.time + 0.3; missile->think = (func_t) Wiz_FastFire; VectorScale(g_globalvars.v_right, -1, missile->s.v.movedir); } void WizardAttackFinished(void) { if ((enemy_range >= RANGE_MID) || !enemy_vis) { self->attack_state = AS_STRAIGHT; self->think = (func_t) wiz_run1; } else { self->attack_state = AS_SLIDING; self->think = (func_t) wiz_side1; } } ANIM(wiz_fast1, magatt1, wiz_fast2; ai_face(); Wiz_StartFast();) ANIM(wiz_fast2, magatt2, wiz_fast3; ai_face();) ANIM(wiz_fast3, magatt3, wiz_fast4; ai_face();) ANIM(wiz_fast4, magatt4, wiz_fast5; ai_face();) ANIM(wiz_fast5, magatt5, wiz_fast6; ai_face();) ANIM(wiz_fast6, magatt6, wiz_fast7; ai_face();) ANIM(wiz_fast7, magatt5, wiz_fast8; ai_face();) ANIM(wiz_fast8, magatt4, wiz_fast9; ai_face();) ANIM(wiz_fast9, magatt3, wiz_fast10; ai_face();) ANIM(wiz_fast10, magatt2, wiz_run1; ai_face(); SUB_AttackFinished(2); WizardAttackFinished();) ANIM(wiz_pain1, pain1, wiz_pain2;) ANIM(wiz_pain2, pain2, wiz_pain3;) ANIM(wiz_pain3, pain3, wiz_pain4;) ANIM(wiz_pain4, pain4, wiz_run1;) void wiz_pain(gedict_t *attacker, float damage) { if ((g_random() * 70) > damage) { return; // didn't flinch } sound(self, CHAN_VOICE, "wizard/wpain.wav", 1, ATTN_NORM); wiz_pain1(); } void _wiz_death1(void) { self->s.v.velocity[0] = 200 * crandom(); self->s.v.velocity[1] = 200 * crandom(); self->s.v.velocity[2] = 100 + 100 * g_random(); self->s.v.flags = (int)self->s.v.flags & ~FL_ONGROUND; sound(self, CHAN_VOICE, "wizard/wdeath.wav", 1, ATTN_NORM); } ANIM(wiz_death1, death1, wiz_death2; _wiz_death1();) ANIM(wiz_death2, death2, wiz_death3;) ANIM(wiz_death3, death3, wiz_death4; self->s.v.solid = SOLID_NOT;) ANIM(wiz_death4, death4, wiz_death5;) ANIM(wiz_death5, death5, wiz_death6;) ANIM(wiz_death6, death6, wiz_death7;) ANIM(wiz_death7, death7, wiz_death8;) ANIM(wiz_death8, death8, wiz_death8;) void wiz_die(void) { // check for gib if (self->s.v.health < -40) { sound(self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM); ThrowHead("progs/h_wizard.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); self->s.v.nextthink = -1; return; } wiz_death1(); } //============================================================================= /* ================= WizardCheckAttack ================= */ float WizardCheckAttack(void) { vec3_t spot1, spot2; gedict_t *targ; float chance; if (g_globalvars.time < self->attack_finished) { return false; } if (!enemy_vis) { return false; } if (enemy_range == RANGE_FAR) { if (self->attack_state != AS_STRAIGHT) { self->attack_state = AS_STRAIGHT; wiz_run1(); } return false; } targ = PROG_TO_EDICT(self->s.v.enemy); // see if any entities are in the way of the shot VectorAdd(self->s.v.origin, self->s.v.view_ofs, spot1); VectorAdd(targ->s.v.origin, targ->s.v.view_ofs, spot2); traceline(PASSVEC3(spot1), PASSVEC3(spot2), false, self); // if ( g_globalvars.trace_inopen && g_globalvars.trace_inwater ) // return false; // sight line crossed contents if (PROG_TO_EDICT(g_globalvars.trace_ent) != targ) { // don't have a clear shot, so move to a side if (self->attack_state != AS_STRAIGHT) { self->attack_state = AS_STRAIGHT; wiz_run1(); } return false; } if (enemy_range == RANGE_MELEE) { chance = 0.9; } else if (enemy_range == RANGE_NEAR) { chance = 0.6; } else if (enemy_range == RANGE_MID) { chance = 0.2; } else { chance = 0; } if (g_random() < chance) { self->attack_state = AS_MISSILE; return true; } if (enemy_range == RANGE_MID) { if (self->attack_state != AS_STRAIGHT) { self->attack_state = AS_STRAIGHT; wiz_run1(); } } else { if (self->attack_state != AS_SLIDING) { self->attack_state = AS_SLIDING; wiz_side1(); } } return false; } //============================================================================= /*QUAKED monster_wizard (1 0 0) (-16 -16 -24) (16 16 40) Ambush */ void SP_monster_wizard(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/wizard.mdl"); safe_precache_model("progs/h_wizard.mdl"); safe_precache_model("progs/w_spike.mdl"); safe_precache_sound("wizard/hit.wav"); // used by c code safe_precache_sound("wizard/wattack.wav"); safe_precache_sound("wizard/wdeath.wav"); safe_precache_sound("wizard/widle1.wav"); safe_precache_sound("wizard/widle2.wav"); safe_precache_sound("wizard/wpain.wav"); safe_precache_sound("wizard/wsight.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 80; self->th_stand = wiz_stand1; self->th_walk = wiz_walk1; self->th_run = wiz_run1; self->th_missile = wiz_fast1; self->th_pain = wiz_pain; self->th_die = wiz_die; self->th_respawn = SP_monster_wizard; flymonster_start("progs/wizard.mdl"); } QW-Group-ktx-d05d6ca/src/sp_zombie.c000066400000000000000000000631251475442401000173610ustar00rootroot00000000000000/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ /* ============================================================================== ZOMBIE ============================================================================== */ #include "g_local.h" enum { stand1, stand2, stand3, stand4, stand5, stand6, stand7, stand8, stand9, stand10, stand11, stand12, stand13, stand14, stand15, walk1, walk2, walk3, walk4, walk5, walk6, walk7, walk8, walk9, walk10, walk11, walk12, walk13, walk14, walk15, walk16, walk17, walk18, walk19, run1, run2, run3, run4, run5, run6, run7, run8, run9, run10, run11, run12, run13, run14, run15, run16, run17, run18, atta1, atta2, atta3, atta4, atta5, atta6, atta7, atta8, atta9, atta10, atta11, atta12, atta13, attb1, attb2, attb3, attb4, attb5, attb6, attb7, attb8, attb9, attb10, attb11, attb12, attb13, attb14, attc1, attc2, attc3, attc4, attc5, attc6, attc7, attc8, attc9, attc10, attc11, attc12, paina1, paina2, paina3, paina4, paina5, paina6, paina7, paina8, paina9, paina10, paina11, paina12, painb1, painb2, painb3, painb4, painb5, painb6, painb7, painb8, painb9, painb10, painb11, painb12, painb13, painb14, painb15, painb16, painb17, painb18, painb19, painb20, painb21, painb22, painb23, painb24, painb25, painb26, painb27, painb28, painc1, painc2, painc3, painc4, painc5, painc6, painc7, painc8, painc9, painc10, painc11, painc12, painc13, painc14, painc15, painc16, painc17, painc18, paind1, paind2, paind3, paind4, paind5, paind6, paind7, paind8, paind9, paind10, paind11, paind12, paind13, paine1, paine2, paine3, paine4, paine5, paine6, paine7, paine8, paine9, paine10, paine11, paine12, paine13, paine14, paine15, paine16, paine17, paine18, paine19, paine20, paine21, paine22, paine23, paine24, paine25, paine26, paine27, paine28, paine29, paine30, cruc_1, cruc_2, cruc_3, cruc_4, cruc_5, cruc_6, }; qbool frame_is_fast_zombie_pain(int frame) { return (((frame >= paina1) && (frame <= paina12)) || ((frame >= painb1) && (frame <= painb28)) || ((frame >= painc1) && (frame <= painc18)) || ((frame >= paind1) && (frame <= paind13))); } qbool frame_is_long_zombie_pain(int frame) { return ((frame >= paine1) && (frame <= paine30)); } void zombie_stand1(void); void zombie_stand2(void); void zombie_stand3(void); void zombie_stand4(void); void zombie_stand5(void); void zombie_stand6(void); void zombie_stand7(void); void zombie_stand8(void); void zombie_stand9(void); void zombie_stand10(void); void zombie_stand11(void); void zombie_stand12(void); void zombie_stand13(void); void zombie_stand14(void); void zombie_stand15(void); void zombie_cruc1(void); void zombie_cruc2(void); void zombie_cruc3(void); void zombie_cruc4(void); void zombie_cruc5(void); void zombie_cruc6(void); void zombie_walk1(void); void zombie_walk2(void); void zombie_walk3(void); void zombie_walk4(void); void zombie_walk5(void); void zombie_walk6(void); void zombie_walk7(void); void zombie_walk8(void); void zombie_walk9(void); void zombie_walk10(void); void zombie_walk11(void); void zombie_walk12(void); void zombie_walk13(void); void zombie_walk14(void); void zombie_walk15(void); void zombie_walk16(void); void zombie_walk17(void); void zombie_walk18(void); void zombie_walk19(void); void zombie_run1(void); void zombie_run2(void); void zombie_run3(void); void zombie_run4(void); void zombie_run5(void); void zombie_run6(void); void zombie_run7(void); void zombie_run8(void); void zombie_run9(void); void zombie_run10(void); void zombie_run11(void); void zombie_run12(void); void zombie_run13(void); void zombie_run14(void); void zombie_run15(void); void zombie_run16(void); void zombie_run17(void); void zombie_run18(void); void zombie_atta1(void); void zombie_atta2(void); void zombie_atta3(void); void zombie_atta4(void); void zombie_atta5(void); void zombie_atta6(void); void zombie_atta7(void); void zombie_atta8(void); void zombie_atta9(void); void zombie_atta10(void); void zombie_atta11(void); void zombie_atta12(void); void zombie_atta13(void); void zombie_attb1(void); void zombie_attb2(void); void zombie_attb3(void); void zombie_attb4(void); void zombie_attb5(void); void zombie_attb6(void); void zombie_attb7(void); void zombie_attb8(void); void zombie_attb9(void); void zombie_attb10(void); void zombie_attb11(void); void zombie_attb12(void); void zombie_attb13(void); void zombie_attb14(void); void zombie_attc1(void); void zombie_attc2(void); void zombie_attc3(void); void zombie_attc4(void); void zombie_attc5(void); void zombie_attc6(void); void zombie_attc7(void); void zombie_attc8(void); void zombie_attc9(void); void zombie_attc10(void); void zombie_attc11(void); void zombie_attc12(void); void zombie_paina1(void); void zombie_paina2(void); void zombie_paina3(void); void zombie_paina4(void); void zombie_paina5(void); void zombie_paina6(void); void zombie_paina7(void); void zombie_paina8(void); void zombie_paina9(void); void zombie_paina10(void); void zombie_paina11(void); void zombie_paina12(void); void zombie_painb1(void); void zombie_painb2(void); void zombie_painb3(void); void zombie_painb4(void); void zombie_painb5(void); void zombie_painb6(void); void zombie_painb7(void); void zombie_painb8(void); void zombie_painb9(void); void zombie_painb10(void); void zombie_painb11(void); void zombie_painb12(void); void zombie_painb13(void); void zombie_painb14(void); void zombie_painb15(void); void zombie_painb16(void); void zombie_painb17(void); void zombie_painb18(void); void zombie_painb19(void); void zombie_painb20(void); void zombie_painb21(void); void zombie_painb22(void); void zombie_painb23(void); void zombie_painb24(void); void zombie_painb25(void); void zombie_painb26(void); void zombie_painb27(void); void zombie_painb28(void); void zombie_painc1(void); void zombie_painc2(void); void zombie_painc3(void); void zombie_painc4(void); void zombie_painc5(void); void zombie_painc6(void); void zombie_painc7(void); void zombie_painc8(void); void zombie_painc9(void); void zombie_painc10(void); void zombie_painc11(void); void zombie_painc12(void); void zombie_painc13(void); void zombie_painc14(void); void zombie_painc15(void); void zombie_painc16(void); void zombie_painc17(void); void zombie_painc18(void); void zombie_paind1(void); void zombie_paind2(void); void zombie_paind3(void); void zombie_paind4(void); void zombie_paind5(void); void zombie_paind6(void); void zombie_paind7(void); void zombie_paind8(void); void zombie_paind9(void); void zombie_paind10(void); void zombie_paind11(void); void zombie_paind12(void); void zombie_paind13(void); void zombie_paine1(void); void zombie_paine2(void); void zombie_paine3(void); void zombie_paine4(void); void zombie_paine5(void); void zombie_paine6(void); void zombie_paine7(void); void zombie_paine8(void); void zombie_paine9(void); void zombie_paine10(void); void zombie_paine11(void); void zombie_paine12(void); void zombie_paine13(void); void zombie_paine14(void); void zombie_paine15(void); void zombie_paine16(void); void zombie_paine17(void); void zombie_paine18(void); void zombie_paine19(void); void zombie_paine20(void); void zombie_paine21(void); void zombie_paine22(void); void zombie_paine23(void); void zombie_paine24(void); void zombie_paine25(void); void zombie_paine26(void); void zombie_paine27(void); void zombie_paine28(void); void zombie_paine29(void); void zombie_paine30(void); const int SPAWN_CRUCIFIED = 1; //============================================================================= ANIM(zombie_stand1, stand1, zombie_stand2; ai_stand();) ANIM(zombie_stand2, stand2, zombie_stand3; ai_stand();) ANIM(zombie_stand3, stand3, zombie_stand4; ai_stand();) ANIM(zombie_stand4, stand4, zombie_stand5; ai_stand();) ANIM(zombie_stand5, stand5, zombie_stand6; ai_stand();) ANIM(zombie_stand6, stand6, zombie_stand7; ai_stand();) ANIM(zombie_stand7, stand7, zombie_stand8; ai_stand();) ANIM(zombie_stand8, stand8, zombie_stand9; ai_stand();) ANIM(zombie_stand9, stand9, zombie_stand10; ai_stand();) ANIM(zombie_stand10, stand10, zombie_stand11; ai_stand();) ANIM(zombie_stand11, stand11, zombie_stand12; ai_stand();) ANIM(zombie_stand12, stand12, zombie_stand13; ai_stand();) ANIM(zombie_stand13, stand13, zombie_stand14; ai_stand();) ANIM(zombie_stand14, stand14, zombie_stand15; ai_stand();) ANIM(zombie_stand15, stand15, zombie_stand1; ai_stand();) void _zombie_cruc1(void) { if (g_random() < 0.1) { sound(self, CHAN_VOICE, "zombie/idle_w2.wav", 1, ATTN_STATIC); } } ANIM(zombie_cruc1, cruc_1, zombie_cruc2; _zombie_cruc1();) ANIM(zombie_cruc2, cruc_2, zombie_cruc3; self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.1;) ANIM(zombie_cruc3, cruc_3, zombie_cruc4; self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.1;) ANIM(zombie_cruc4, cruc_4, zombie_cruc5; self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.1;) ANIM(zombie_cruc5, cruc_5, zombie_cruc6; self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.1;) ANIM(zombie_cruc6, cruc_6, zombie_cruc1; self->s.v.nextthink = g_globalvars.time + 0.1 + g_random() * 0.1;) void _zombie_walk19(void) { ai_walk(0); if (g_random() < 0.2) { sound(self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_IDLE); } } ANIM(zombie_walk1, walk1, zombie_walk2; ai_walk(0);) ANIM(zombie_walk2, walk2, zombie_walk3; ai_walk(2);) ANIM(zombie_walk3, walk3, zombie_walk4; ai_walk(3);) ANIM(zombie_walk4, walk4, zombie_walk5; ai_walk(2);) ANIM(zombie_walk5, walk5, zombie_walk6; ai_walk(1);) ANIM(zombie_walk6, walk6, zombie_walk7; ai_walk(0);) ANIM(zombie_walk7, walk7, zombie_walk8; ai_walk(0);) ANIM(zombie_walk8, walk8, zombie_walk9; ai_walk(0);) ANIM(zombie_walk9, walk9, zombie_walk10; ai_walk(0);) ANIM(zombie_walk10, walk10, zombie_walk11; ai_walk(0);) ANIM(zombie_walk11, walk11, zombie_walk12; ai_walk(2);) ANIM(zombie_walk12, walk12, zombie_walk13; ai_walk(2);) ANIM(zombie_walk13, walk13, zombie_walk14; ai_walk(1);) ANIM(zombie_walk14, walk14, zombie_walk15; ai_walk(0);) ANIM(zombie_walk15, walk15, zombie_walk16; ai_walk(0);) ANIM(zombie_walk16, walk16, zombie_walk17; ai_walk(0);) ANIM(zombie_walk17, walk17, zombie_walk18; ai_walk(0);) ANIM(zombie_walk18, walk18, zombie_walk19; ai_walk(0);) ANIM(zombie_walk19, walk19, zombie_walk1; _zombie_walk19();) void _zombie_run18(void) { ai_run(8); if (g_random() < 0.2) { sound(self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_IDLE); } if (g_random() > 0.8) { sound(self, CHAN_VOICE, "zombie/z_idle1.wav", 1, ATTN_IDLE); } } ANIM(zombie_run1, run1, zombie_run2; ai_run(1)) ANIM(zombie_run2, run2, zombie_run3; ai_run(1);) ANIM(zombie_run3, run3, zombie_run4; ai_run(0);) ANIM(zombie_run4, run4, zombie_run5; ai_run(1);) ANIM(zombie_run5, run5, zombie_run6; ai_run(2);) ANIM(zombie_run6, run6, zombie_run7; ai_run(3);) ANIM(zombie_run7, run7, zombie_run8; ai_run(4);) ANIM(zombie_run8, run8, zombie_run9; ai_run(4);) ANIM(zombie_run9, run9, zombie_run10; ai_run(2);) ANIM(zombie_run10, run10, zombie_run11; ai_run(0);) ANIM(zombie_run11, run11, zombie_run12; ai_run(0);) ANIM(zombie_run12, run12, zombie_run13; ai_run(0);) ANIM(zombie_run13, run13, zombie_run14; ai_run(2);) ANIM(zombie_run14, run14, zombie_run15; ai_run(4);) ANIM(zombie_run15, run15, zombie_run16; ai_run(6);) ANIM(zombie_run16, run16, zombie_run17; ai_run(7);) ANIM(zombie_run17, run17, zombie_run18; ai_run(3);) ANIM(zombie_run18, run18, zombie_run1; _zombie_run18();) /* ============================================================================= ATTACKS ============================================================================= */ void ZombieGrenadeTouch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } if (other->s.v.takedamage) { other->deathtype = dtSQUISH; // FIXME T_Damage(other, self, PROG_TO_EDICT(self->s.v.owner), 10); sound(self, CHAN_WEAPON, "zombie/z_hit.wav", 1, ATTN_NORM); ent_remove(self); return; } sound(self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM); // bounce sound VectorCopy(VEC_ORIGIN, self->s.v.velocity); VectorCopy(VEC_ORIGIN, self->s.v.avelocity); self->touch = (func_t) SUB_Remove; } /* ================ ZombieFireGrenade ================ */ void ZombieFireGrenade(float st_x, float st_y, float st_z) { gedict_t *missile; vec3_t org; sound(self, CHAN_WEAPON, "zombie/z_shot1.wav", 1, ATTN_NORM); missile = spawn(); missile->s.v.owner = EDICT_TO_PROG(self); missile->s.v.movetype = MOVETYPE_BOUNCE; missile->isMissile = true; missile->s.v.solid = SOLID_BBOX; // calc org trap_makevectors(self->s.v.angles); //org = self->s.v.origin + st[0] * v_forward + st[1] * v_right + st[2] * v_up; VectorMA(self->s.v.origin, st_x, g_globalvars.v_forward, org); VectorMA(org, st_y, g_globalvars.v_right, org); VectorMA(org, st_z, g_globalvars.v_up, org); // set missile speed VectorSubtract(PROG_TO_EDICT(self->s.v.enemy)->s.v.origin, org, missile->s.v.velocity); normalize(missile->s.v.velocity, missile->s.v.velocity); VectorScale(missile->s.v.velocity, 600 + 100 * g_random(), missile->s.v.velocity); missile->s.v.velocity[2] += 200 + 50 * g_random(); SetVector(missile->s.v.avelocity, 3000, 1000, 2000); missile->touch = (func_t) ZombieGrenadeTouch; // set missile duration missile->s.v.nextthink = g_globalvars.time + 2.5 + g_random(); missile->think = (func_t) SUB_Remove; setmodel(missile, "progs/zom_gib.mdl"); setsize(missile, PASSVEC3(VEC_ORIGIN), PASSVEC3(VEC_ORIGIN)); setorigin(missile, PASSVEC3(org)); } ANIM(zombie_atta1, atta1, zombie_atta2; ai_face();) ANIM(zombie_atta2, atta2, zombie_atta3; ai_face();) ANIM(zombie_atta3, atta3, zombie_atta4; ai_face();) ANIM(zombie_atta4, atta4, zombie_atta5; ai_face();) ANIM(zombie_atta5, atta5, zombie_atta6; ai_face();) ANIM(zombie_atta6, atta6, zombie_atta7; ai_face();) ANIM(zombie_atta7, atta7, zombie_atta8; ai_face();) ANIM(zombie_atta8, atta8, zombie_atta9; ai_face();) ANIM(zombie_atta9, atta9, zombie_atta10; ai_face();) ANIM(zombie_atta10, atta10, zombie_atta11; ai_face();) ANIM(zombie_atta11, atta11, zombie_atta12; ai_face();) ANIM(zombie_atta12, atta12, zombie_atta13; ai_face();) ANIM(zombie_atta13, atta13, zombie_run1; ai_face(); ZombieFireGrenade( -10, 14, 20 );) ANIM(zombie_attb1, attb1, zombie_attb2; ai_face();) ANIM(zombie_attb2, attb2, zombie_attb3; ai_face();) ANIM(zombie_attb3, attb3, zombie_attb4; ai_face();) ANIM(zombie_attb4, attb4, zombie_attb5; ai_face();) ANIM(zombie_attb5, attb5, zombie_attb6; ai_face();) ANIM(zombie_attb6, attb6, zombie_attb7; ai_face();) ANIM(zombie_attb7, attb7, zombie_attb8; ai_face();) ANIM(zombie_attb8, attb8, zombie_attb9; ai_face();) ANIM(zombie_attb9, attb9, zombie_attb10; ai_face();) ANIM(zombie_attb10, attb10, zombie_attb11; ai_face();) ANIM(zombie_attb11, attb11, zombie_attb12; ai_face();) ANIM(zombie_attb12, attb12, zombie_attb13; ai_face();) ANIM(zombie_attb13, attb13, zombie_attb14; ai_face();) ANIM(zombie_attb14, attb13, zombie_run1; ai_face(); ZombieFireGrenade( -10, -10, 20 );) ANIM(zombie_attc1, attc1, zombie_attc2; ai_face();) ANIM(zombie_attc2, attc2, zombie_attc3; ai_face();) ANIM(zombie_attc3, attc3, zombie_attc4; ai_face();) ANIM(zombie_attc4, attc4, zombie_attc5; ai_face();) ANIM(zombie_attc5, attc5, zombie_attc6; ai_face();) ANIM(zombie_attc6, attc6, zombie_attc7; ai_face();) ANIM(zombie_attc7, attc7, zombie_attc8; ai_face();) ANIM(zombie_attc8, attc8, zombie_attc9; ai_face();) ANIM(zombie_attc9, attc9, zombie_attc10; ai_face();) ANIM(zombie_attc10, attc10, zombie_attc11; ai_face();) ANIM(zombie_attc11, attc11, zombie_attc12; ai_face();) ANIM(zombie_attc12, attc12, zombie_run1; ai_face(); ZombieFireGrenade( -10, 14, 20 );) void zombie_missile(void) { float r; r = g_random(); if (r < 0.3) { zombie_atta1(); } else if (r < 0.6) { zombie_attb1(); } else { zombie_attc1(); } } /* ============================================================================= PAIN ============================================================================= */ ANIM(zombie_paina1, paina1, zombie_paina2; sound( self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM );) ANIM(zombie_paina2, paina2, zombie_paina3; ai_painforward(3);) ANIM(zombie_paina3, paina3, zombie_paina4; ai_painforward(1);) ANIM(zombie_paina4, paina4, zombie_paina5; ai_pain(1);) ANIM(zombie_paina5, paina5, zombie_paina6; ai_pain(3);) ANIM(zombie_paina6, paina6, zombie_paina7; ai_pain(1);) ANIM(zombie_paina7, paina7, zombie_paina8;) ANIM(zombie_paina8, paina8, zombie_paina9;) ANIM(zombie_paina9, paina9, zombie_paina10;) ANIM(zombie_paina10, paina10, zombie_paina11;) ANIM(zombie_paina11, paina11, zombie_paina12;) ANIM(zombie_paina12, paina12, zombie_run1;) ANIM(zombie_painb1, painb1, zombie_painb2; sound( self, CHAN_VOICE, "zombie/z_pain1.wav", 1, ATTN_NORM );) ANIM(zombie_painb2, painb2, zombie_painb3; ai_pain(2);) ANIM(zombie_painb3, painb3, zombie_painb4; ai_pain(8);) ANIM(zombie_painb4, painb4, zombie_painb5; ai_pain(6);) ANIM(zombie_painb5, painb5, zombie_painb6; ai_pain(2);) ANIM(zombie_painb6, painb6, zombie_painb7;) ANIM(zombie_painb7, painb7, zombie_painb8;) ANIM(zombie_painb8, painb8, zombie_painb9;) ANIM(zombie_painb9, painb9, zombie_painb10; sound( self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM );) ANIM(zombie_painb10, painb10, zombie_painb11;) ANIM(zombie_painb11, painb11, zombie_painb12;) ANIM(zombie_painb12, painb12, zombie_painb13;) ANIM(zombie_painb13, painb13, zombie_painb14;) ANIM(zombie_painb14, painb14, zombie_painb15;) ANIM(zombie_painb15, painb15, zombie_painb16;) ANIM(zombie_painb16, painb16, zombie_painb17;) ANIM(zombie_painb17, painb17, zombie_painb18;) ANIM(zombie_painb18, painb18, zombie_painb19;) ANIM(zombie_painb19, painb19, zombie_painb20;) ANIM(zombie_painb20, painb20, zombie_painb21;) ANIM(zombie_painb21, painb21, zombie_painb22;) ANIM(zombie_painb22, painb22, zombie_painb23;) ANIM(zombie_painb23, painb23, zombie_painb24;) ANIM(zombie_painb24, painb24, zombie_painb25;) ANIM(zombie_painb25, painb25, zombie_painb26; ai_painforward(1);) ANIM(zombie_painb26, painb26, zombie_painb27;) ANIM(zombie_painb27, painb27, zombie_painb28;) ANIM(zombie_painb28, painb28, zombie_run1;) ANIM(zombie_painc1, painc1, zombie_painc2; sound( self, CHAN_VOICE, "zombie/z_pain1.wav", 1, ATTN_NORM );) ANIM(zombie_painc2, painc2, zombie_painc3;) ANIM(zombie_painc3, painc3, zombie_painc4; ai_pain(3);) ANIM(zombie_painc4, painc4, zombie_painc5; ai_pain(1);) ANIM(zombie_painc5, painc5, zombie_painc6;) ANIM(zombie_painc6, painc6, zombie_painc7;) ANIM(zombie_painc7, painc7, zombie_painc8;) ANIM(zombie_painc8, painc8, zombie_painc9;) ANIM(zombie_painc9, painc9, zombie_painc10;) ANIM(zombie_painc10, painc10, zombie_painc11;) ANIM(zombie_painc11, painc11, zombie_painc12; ai_painforward(1);) ANIM(zombie_painc12, painc12, zombie_painc13; ai_painforward(1);) ANIM(zombie_painc13, painc13, zombie_painc14;) ANIM(zombie_painc14, painc14, zombie_painc15;) ANIM(zombie_painc15, painc15, zombie_painc16;) ANIM(zombie_painc16, painc16, zombie_painc17;) ANIM(zombie_painc17, painc17, zombie_painc18;) ANIM(zombie_painc18, painc18, zombie_run1;) ANIM(zombie_paind1, paind1, zombie_paind2; sound( self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM );) ANIM(zombie_paind2, paind2, zombie_paind3;) ANIM(zombie_paind3, paind3, zombie_paind4;) ANIM(zombie_paind4, paind4, zombie_paind5;) ANIM(zombie_paind5, paind5, zombie_paind6;) ANIM(zombie_paind6, paind6, zombie_paind7;) ANIM(zombie_paind7, paind7, zombie_paind8;) ANIM(zombie_paind8, paind8, zombie_paind9;) ANIM(zombie_paind9, paind9, zombie_paind10; ai_pain(1);) ANIM(zombie_paind10, paind10, zombie_paind11;) ANIM(zombie_paind11, paind11, zombie_paind12;) ANIM(zombie_paind12, paind12, zombie_paind13;) ANIM(zombie_paind13, paind13, zombie_run1;) void _zombie_paine1(void) { sound(self, CHAN_VOICE, "zombie/z_pain.wav", 1, ATTN_NORM); } void _zombie_paine10(void) { sound(self, CHAN_BODY, "zombie/z_fall.wav", 1, ATTN_NORM); self->s.v.solid = SOLID_NOT; } void _zombie_paine11(void) { self->s.v.nextthink = g_globalvars.time + 3 + g_random() + g_random(); // randozime wake up a bit } void _zombie_paine12(void) { sound(self, CHAN_VOICE, "zombie/z_idle.wav", 1, ATTN_IDLE); self->s.v.solid = SOLID_SLIDEBOX; // this set this before checking walkmove() // see if ok to stand up if (!walkmove(self, 0, 0)) { // not ok, delay wake up in zombie_paine11 self->s.v.solid = SOLID_NOT; // return back non solid state self->think = (func_t) zombie_paine11; return; } } ANIM(zombie_paine1, paine1, zombie_paine2; _zombie_paine1();) ANIM(zombie_paine2, paine2, zombie_paine3; ai_pain(8);) ANIM(zombie_paine3, paine3, zombie_paine4; ai_pain(5);) ANIM(zombie_paine4, paine4, zombie_paine5; ai_pain(3);) ANIM(zombie_paine5, paine5, zombie_paine6; ai_pain(1);) ANIM(zombie_paine6, paine6, zombie_paine7; ai_pain(2);) ANIM(zombie_paine7, paine7, zombie_paine8; ai_pain(1);) ANIM(zombie_paine8, paine8, zombie_paine9; ai_pain(1);) ANIM(zombie_paine9, paine9, zombie_paine10; ai_pain(2);) ANIM(zombie_paine10, paine10, zombie_paine11; _zombie_paine10();) ANIM(zombie_paine11, paine11, zombie_paine12; _zombie_paine11();) ANIM(zombie_paine12, paine12, zombie_paine13; _zombie_paine12();) ANIM(zombie_paine13, paine13, zombie_paine14;) ANIM(zombie_paine14, paine14, zombie_paine15;) ANIM(zombie_paine15, paine15, zombie_paine16;) ANIM(zombie_paine16, paine16, zombie_paine17;) ANIM(zombie_paine17, paine17, zombie_paine18;) ANIM(zombie_paine18, paine18, zombie_paine19;) ANIM(zombie_paine19, paine19, zombie_paine20;) ANIM(zombie_paine20, paine20, zombie_paine21;) ANIM(zombie_paine21, paine21, zombie_paine22;) ANIM(zombie_paine22, paine22, zombie_paine23;) ANIM(zombie_paine23, paine23, zombie_paine24;) ANIM(zombie_paine24, paine24, zombie_paine25;) ANIM(zombie_paine25, paine25, zombie_paine26; ai_painforward(5);) ANIM(zombie_paine26, paine26, zombie_paine27; ai_painforward(3);) ANIM(zombie_paine27, paine27, zombie_paine28; ai_painforward(1);) ANIM(zombie_paine28, paine28, zombie_paine29; ai_pain(1);) ANIM(zombie_paine29, paine29, zombie_paine30;) ANIM(zombie_paine30, paine30, zombie_run1;) /* ================= zombie_pain Zombies can only be killed (gibbed) by doing 60 hit points of damage in a single frame (rockets, grenades, quad shotgun, quad nailgun). A hit of 25 points or more (super shotgun, quad nailgun) will always put it down to the ground. A hit of from 10 to 40 points in one frame will cause it to go down if it has been twice in two seconds, otherwise it goes into one of the four fast pain frames. A hit of less than 10 points of damage (winged by a shotgun) will be ignored. FIXME: don't use pain_finished because of nightmare hack ================= */ void zombie_pain(gedict_t *attacker, float take) { float r; self->s.v.health = 60; // always reset health if (take < 9) { return; // totally ignore } if (frame_is_long_zombie_pain(self->s.v.frame)) { return; // down on ground, so don't reset any counters } // go down immediately if a big enough hit if (take >= 25) { zombie_paine1(); return; } // if alredy in pain, drop down if (frame_is_fast_zombie_pain(self->s.v.frame)) { zombie_paine1(); return; } // go into one of the fast pain animations r = g_random(); if (r < 0.25) { zombie_paina1(); } else if (r < 0.5) { zombie_painb1(); } else if (r < 0.75) { zombie_painc1(); } else { zombie_paind1(); } } void zombie_die(void) { sound(self, CHAN_VOICE, "zombie/z_gib.wav", 1, ATTN_NORM); ThrowHead("progs/h_zombie.mdl", self->s.v.health); ThrowGib("progs/gib1.mdl", self->s.v.health); ThrowGib("progs/gib2.mdl", self->s.v.health); ThrowGib("progs/gib3.mdl", self->s.v.health); self->s.v.nextthink = -1; } //============================================================================ /*QUAKED monster_zombie (1 0 0) (-16 -16 -24) (16 16 32) Crucified ambush If crucified, stick the bounding box 12 pixels back into a wall to look right. */ void SP_monster_zombie(void) { if (!AllowMonster(self)) { ent_remove(self); return; } safe_precache_model("progs/zombie.mdl"); safe_precache_model("progs/h_zombie.mdl"); safe_precache_model("progs/zom_gib.mdl"); safe_precache_sound("zombie/z_idle.wav"); safe_precache_sound("zombie/z_idle1.wav"); safe_precache_sound("zombie/z_shot1.wav"); safe_precache_sound("zombie/z_gib.wav"); safe_precache_sound("zombie/z_pain.wav"); safe_precache_sound("zombie/z_pain1.wav"); safe_precache_sound("zombie/z_fall.wav"); safe_precache_sound("zombie/z_miss.wav"); safe_precache_sound("zombie/z_hit.wav"); safe_precache_sound("zombie/idle_w2.wav"); setsize(self, -16, -16, -24, 16, 16, 40); self->s.v.health = 60; self->th_stand = zombie_stand1; self->th_walk = zombie_walk1; self->th_run = zombie_run1; self->th_pain = zombie_pain; self->th_die = zombie_die; self->th_missile = zombie_missile; self->th_respawn = SP_monster_zombie; if ((int)self->s.v.spawnflags & SPAWN_CRUCIFIED) { self->s.v.solid = SOLID_SLIDEBOX; self->s.v.movetype = MOVETYPE_NONE; walkmonster_start("progs/zombie.mdl"); // This zombie is crucified, and will never start walking so restore model here. setmodel(self, "progs/zombie.mdl"); zombie_cruc1(); } else { walkmonster_start("progs/zombie.mdl"); } } QW-Group-ktx-d05d6ca/src/spectate.c000066400000000000000000000235201475442401000171750ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ // spectate.c #include "g_local.h" void Wp_Stats(float on); void Sc_Stats(float on); void DoAutoTrack(void); void AdminImpBot(void); void MakeMOTD(void); void AutoTrackRestore(void); void Bot_Print_Thinking(void); void SendSpecInfo(gedict_t *spec, gedict_t *target_client); qbool TrackChangeCoach(gedict_t *p); int GetSpecWizard(void) { int k_asw = bound(0, cvar("allow_spec_wizard"), 2); if (match_in_progress || intermission_running || isRACE()) { return 0; } switch (k_asw) { case 0: return 0; // wizards not allowed case 1: return (CountPlayers() ? 0 : 1); // allowed without players case 2: return 2; // allowed with players in prematch } return 0; } void ShowCamHelp(void) { G_sprint(self, 2, "use %s %s to jump between spawn points\n" "use [attack] to change cam mode\n" "use [jump] to change target\n", redtext("impulse"), dig3(1)); } void wizard_think(void) { if (!cvar("k_no_wizard_animation")) // animate if allowed { (self->s.v.frame)++; } if ((self->s.v.frame > 14) || (self->s.v.frame < 0)) { self->s.v.frame = 0; } self->s.v.nextthink = g_globalvars.time + 0.1; } void SpecDecodeLevelParms(void) { /* self->s.v.items = g_globalvars.parm1; self->s.v.health = g_globalvars.parm2; self->s.v.armorvalue = g_globalvars.parm3; self->s.v.ammo_shells = g_globalvars.parm4; self->s.v.ammo_nails = g_globalvars.parm5; self->s.v.ammo_rockets = g_globalvars.parm6; self->s.v.ammo_cells = g_globalvars.parm7; self->s.v.weapon = g_globalvars.parm8; self->s.v.armortype = g_globalvars.parm9 * 0.01; */ if (g_globalvars.parm11) { self->k_admin = g_globalvars.parm11; } if (g_globalvars.parm12) { self->k_coach = g_globalvars.parm12; } if (g_globalvars.parm13) { self->k_stuff = g_globalvars.parm13; } // if ( g_globalvars.parm14 ) // self->ps.handicap = g_globalvars.parm14; } qbool nospecs_canconnect(gedict_t *spec) { if (cvar("_k_nospecs")) { // some VIPS able to connect anyway if (!(VIP(spec) & ALLOWED_NOSPECS_VIPS) && !is_coach(spec)) { return false; } } return true; } //////////////////////////////////////////////////// // Function checks if a spectator can connect or not // // return true - if a spec can connect // false - otherwise //////////////////////////////////////////////////// qbool SpecCanConnect(gedict_t *spec) { if (!nospecs_canconnect(spec)) { G_sprint(spec, 2, "%s mode, you can't connect\n", redtext("No spectators")); return false; } return true; } //////////////// // GlobalParams: // time // self // params /////////////// void SpectatorConnect(void) { gedict_t *p; int diff = (int)(PROG_TO_EDICT(self->s.v.goalentity) - world); // we need this before the SpecCanConnect() call, as we need to restore admin and/or coach flags SpecDecodeLevelParms(); if (!SpecCanConnect(self)) { stuffcmd(self, "disconnect\n"); // FIXME: stupid way return; } self->ct = ctSpec; self->classname = "spectator"; // Added this in for kick code self->k_accepted = 1; // spectator has no restriction to connect for (p = world; (p = (match_in_progress == 2 && !cvar("k_ann")) ? find_spc(p) : find_client(p));) { if (p != self) // does't show msg for self { G_sprint(p, PRINT_HIGH, "Spectator %s entered the game\n", self->netname); } } if ((diff < 0) || (diff >= MAX_EDICTS)) // something wrong happen - fixing { self->s.v.goalentity = EDICT_TO_PROG(world); } VIP_ShowRights(self); CheckRate(self, ""); if (match_in_progress != 2) { self->wizard = spawn(); self->wizard->classname = "spectator_wizard"; self->wizard->think = (func_t) wizard_think; self->wizard->s.v.nextthink = g_globalvars.time + 0.1; } SendSpecInfo(NULL, self); // Get all spectator info // Wait until you do stuffing MakeMOTD(); } //////////////// // GlobalParams: // time // self /////////////// extern int g_matchstarttime; void PutSpectatorInServer(void) { // G_sprint(self, 2, "Hellow %s\n", getname(self)); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte(MSG_ONE, 38 /*svc_updatestatlong*/); WriteByte(MSG_ONE, 18 /*STAT_MATCHSTARTTIME*/); WriteLong(MSG_ONE, g_matchstarttime); AutoTrackRestore(); } //////////////// // GlobalParams: // self /////////////// void SpectatorDisconnect(void) { gedict_t *p; if (self->k_accepted) { for (p = world; (p = (match_in_progress == 2 && !cvar("k_ann")) ? find_spc(p) : find_client(p));) { G_sprint(p, PRINT_HIGH, "Spectator %s left the game\n", self->netname); } } // s: added conditional function call here if (self->v.elect_type != etNone) { if (match_in_progress != 2) { G_bprint(2, "Election aborted\n"); } AbortElect(); } if (coach_num(self)) { G_bprint(2, "A %s has left\n", redtext("coach")); ExitCoach(); } if (self->wizard) { ent_remove(self->wizard); self->wizard = NULL; } if (self->k_kicking) { ExitKick(self); } self->classname = ""; // Cenobite, so we clear out any specs as they leave self->k_accepted = 0; self->ct = ctNone; } /* ================ SpectatorImpulseCommand Called by SpectatorThink if the spectator entered an impulse ================ */ void SpectatorImpulseCommand(void) { gedict_t *goal; if (self->ct != ctSpec) { self->s.v.impulse = 0; return; } goal = PROG_TO_EDICT(self->s.v.goalentity); if (self->k_adminc && (self->s.v.impulse >= 1) && (self->s.v.impulse <= 9)) { AdminImpBot(); } else if (self->s.v.impulse == 1) { // teleport the spectator to the next spawn point // note that if the spectator is tracking, this doesn't do much goal = PROG_TO_EDICT(self->s.v.goalentity); // if track someone - return if (((int)(goal - world) >= 1) && ((int)(goal - world) <= MAX_CLIENTS)) { // qqshka - heh, not all guys like this warning // G_sprint(self, 2, "stop %s first\n", redtext("tracking")); self->s.v.impulse = 0; return; } goal = find(goal, FOFCLSN, "info_player_deathmatch"); if (!goal) { goal = find(world, FOFCLSN, "info_player_deathmatch"); } if (goal) { setorigin(self, PASSVEC3(goal->s.v.origin)); VectorCopy(goal->s.v.angles, self->s.v.angles); self->s.v.fixangle = true; // turn this way immediately } else { goal = world; } self->s.v.goalentity = EDICT_TO_PROG(goal); } self->s.v.impulse = 0; } void SpecGoalChanged(void) { if (self->k_coach) { if (TrackChangeCoach(self)) { return; } } if (self->wp_stats) { Wp_Stats(2); // force refresh } if (self->sc_stats) { Sc_Stats(2); // force refresh } WS_OnSpecPovChange(self, false); // refresh "new weapon stats" SendSpecInfo(self, NULL); // update tracking info with all clients } //////////////// // GlobalParams: // time // self /////////////// void SpectatorThink(void) { gedict_t *wizard = self->wizard; if (self->last_goal != self->s.v.goalentity) { SpecGoalChanged(); self->last_goal = self->s.v.goalentity; } if (self->autotrack) { DoAutoTrack(); } if (self->s.v.impulse) { SpectatorImpulseCommand(); } if (self->sc_stats && self->sc_stats_time && (self->sc_stats_time <= g_globalvars.time) && (match_in_progress != 1)) { Print_Scores(); } if (self->wp_stats && self->wp_stats_time && (self->wp_stats_time <= g_globalvars.time) && (match_in_progress != 1)) { Print_Wp_Stats(); } if (isCA()) { CA_spectator_think(); } #ifdef BOT_SUPPORT if (self->s.v.goalentity) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); if (goal->isBot) { Bot_Print_Thinking(); } } #endif if (wizard) { // set model angles wizard->s.v.angles[0] = -self->s.v.v_angle[0] / 2; wizard->s.v.angles[1] = self->s.v.v_angle[1]; // wizard model blinking at spectator screen - so move model behind spec camera a bit trap_makevectors(self->s.v.v_angle); VectorMA(self->s.v.origin, -32, g_globalvars.v_forward, wizard->s.v.origin); // model bobbing wizard->s.v.origin[2] += sin(g_globalvars.time * 2.5); setorigin(wizard, PASSVEC3(wizard->s.v.origin)); if (GetSpecWizard()) { gedict_t *goal = PROG_TO_EDICT(self->s.v.goalentity); if (goal && (goal->ct == ctPlayer)) // tracking player, so turn model off { wizard->model = ""; } else { // turn model on setmodel(wizard, "progs/wizard.mdl"); } } else { wizard->model = ""; // turn model off } } } void remove_specs_wizards(void) { gedict_t *p; for (p = world; (p = find_spc(p));) { if (p->wizard) { ent_remove(p->wizard); p->wizard = NULL; } } } void hide_specs_wizards(void) { gedict_t *p; for (p = world; (p = find(p, FOFCLSN, "spectator_wizard"));) { p->model = ""; } } void show_specs_wizards(void) { gedict_t *p; for (p = world; (p = find(p, FOFCLSN, "spectator_wizard"));) { setmodel(p, "progs/wizard.mdl"); } } void FixSpecWizards(void) { static int k_asw = -1; // static qbool changed = false; int k_asw_new = GetSpecWizard(); if ((k_asw != k_asw_new) || (framecount == 1)) { // force on first frame changed = true; k_asw = k_asw_new; } if (changed) { if (k_asw) { show_specs_wizards(); } else { hide_specs_wizards(); } } } QW-Group-ktx-d05d6ca/src/stats.c000066400000000000000000001242371475442401000165320ustar00rootroot00000000000000/* * This file contains the logic to print the Endgame Statistics */ #include "g_local.h" #include "stats.h" FILE_FORMAT_DECL(xml) FILE_FORMAT_DECL(json) static stats_format_t file_formats[] = { FILE_FORMAT_DEF(xml), FILE_FORMAT_DEF(json) }; char tmStats_names[MAX_TM_STATS][MAX_TEAM_NAME]; // u can't put this in struct in QVM teamStats_t tmStats[MAX_TM_STATS]; int tmStats_cnt = 0; void OnePlayerInstagibStats(gedict_t *p, int tp); void OnePlayerMidairStats(gedict_t *p, int tp); static void CollectTpStats(void) { gedict_t *p, *p2; int from1, from2; int i, *frags; char *tmp = ""; for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { p->ready = 0; // clear mark } // get one player and search all his mates, mark served players via ->ready field // ghosts is served too for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { if (p->ready || strnull(tmp = getteam(p))) { continue; // served or wrong team } if ((tmStats_cnt < 0) || (tmStats_cnt >= MAX_TM_STATS)) { return; // all slots busy } if (tmStats[tmStats_cnt].name == NULL) { return; } for (from2 = 0, p2 = world; (p2 = find_plrghst(p2, &from2));) { if (p2->ready || strneq(tmp, getteam(p2))) { continue; // served or on different team } if (strnull(tmStats[tmStats_cnt].name)) // we not yet done that, do that once { strlcpy(tmStats[tmStats_cnt].name, tmp, MAX_TEAM_NAME); } frags = (p2->ct == ctPlayer ? &tmStats[tmStats_cnt].frags : &tmStats[tmStats_cnt].gfrags); frags[0] += p2->s.v.frags; tmStats[tmStats_cnt].deaths += p2->deaths; tmStats[tmStats_cnt].tkills += p2->friendly; tmStats[tmStats_cnt].dmg_t += p2->ps.dmg_t; tmStats[tmStats_cnt].dmg_g += p2->ps.dmg_g; tmStats[tmStats_cnt].dmg_team += p2->ps.dmg_team; tmStats[tmStats_cnt].dmg_eweapon += p2->ps.dmg_eweapon; for (i = itNONE; i < itMAX; i++) { // summ each field of items tmStats[tmStats_cnt].itm[i].tooks += p2->ps.itm[i].tooks; tmStats[tmStats_cnt].itm[i].time += p2->ps.itm[i].time; } for (i = wpNONE; i < wpMAX; i++) { // summ each field of weapons tmStats[tmStats_cnt].wpn[i].hits += p2->ps.wpn[i].hits; tmStats[tmStats_cnt].wpn[i].attacks += p2->ps.wpn[i].attacks; tmStats[tmStats_cnt].wpn[i].kills += p2->ps.wpn[i].kills; tmStats[tmStats_cnt].wpn[i].deaths += p2->ps.wpn[i].deaths; tmStats[tmStats_cnt].wpn[i].tkills += p2->ps.wpn[i].tkills; tmStats[tmStats_cnt].wpn[i].ekills += p2->ps.wpn[i].ekills; tmStats[tmStats_cnt].wpn[i].drops += p2->ps.wpn[i].drops; tmStats[tmStats_cnt].wpn[i].tooks += p2->ps.wpn[i].tooks; tmStats[tmStats_cnt].wpn[i].ttooks += p2->ps.wpn[i].ttooks; } tmStats[tmStats_cnt].transferred_RLpacks += p2->ps.transferred_RLpacks; tmStats[tmStats_cnt].transferred_LGpacks += p2->ps.transferred_LGpacks; // { ctf related tmStats[tmStats_cnt].res += p2->ps.res_time; tmStats[tmStats_cnt].str += p2->ps.str_time; tmStats[tmStats_cnt].hst += p2->ps.hst_time; tmStats[tmStats_cnt].rgn += p2->ps.rgn_time; tmStats[tmStats_cnt].caps += p2->ps.caps; tmStats[tmStats_cnt].pickups += p2->ps.pickups; tmStats[tmStats_cnt].returns += p2->ps.returns; tmStats[tmStats_cnt].f_defends += p2->ps.f_defends; tmStats[tmStats_cnt].c_defends += p2->ps.c_defends; // } p2->ready = 1; // set mark } if (strnull(tmStats[tmStats_cnt].name)) { continue; // wtf, empty team? } if (isCTF() && g_globalvars.time - match_start_time > 0) { tmStats[tmStats_cnt].res = (tmStats[tmStats_cnt].res / (g_globalvars.time - match_start_time)) * 100; tmStats[tmStats_cnt].str = (tmStats[tmStats_cnt].str / (g_globalvars.time - match_start_time)) * 100; tmStats[tmStats_cnt].hst = (tmStats[tmStats_cnt].hst / (g_globalvars.time - match_start_time)) * 100; tmStats[tmStats_cnt].rgn = (tmStats[tmStats_cnt].rgn / (g_globalvars.time - match_start_time)) * 100; } tmStats_cnt++; } } static void ShowTeamsBanner(void) { int i; G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); // for( i = 666 + 1; i <= k_teamid ; i++ ) // G_bprint(2, "%s\220%s\221", (i != (666+1) ? " vs " : ""), ezinfokey(world, va("%d", i))); for (i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { G_bprint(2, "%s\220%s\221", (i ? " vs " : ""), tmStats[i].name); } G_bprint(2, " %s:\n", redtext("match statistics")); G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } static void SummaryTPStats(void) { int i; float h_sg, h_ssg, h_gl, h_rl, h_lg; ShowTeamsBanner(); G_bprint(2, "\n%s, %s, %s, %s\n", redtext("weapons"), redtext("powerups"), redtext("armors&mhs"), redtext("damage")); G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); for (i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { h_sg = 100.0 * tmStats[i].wpn[wpSG].hits / max(1, tmStats[i].wpn[wpSG].attacks); h_ssg = 100.0 * tmStats[i].wpn[wpSSG].hits / max(1, tmStats[i].wpn[wpSSG].attacks); h_gl = tmStats[i].wpn[wpGL].hits; h_rl = tmStats[i].wpn[wpRL].hits; h_lg = 100.0 * tmStats[i].wpn[wpLG].hits / max(1, tmStats[i].wpn[wpLG].attacks); // weapons if (!cvar("k_instagib")) { G_bprint(2, "\220%s\221: %s:%s%s%s%s%s\n", tmStats[i].name, redtext("Wp"), (h_lg ? va(" %s%.0f%%", redtext("lg"), h_lg) : ""), (h_rl ? va(" %s%.0f", redtext("rl"), h_rl) : ""), (h_gl ? va(" %s%.0f", redtext("gl"), h_gl) : ""), (h_sg ? va(" %s%.0f%%", redtext("sg"), h_sg) : ""), (h_ssg ? va(" %s%.0f%%", redtext("ssg"), h_ssg) : "")); // powerups G_bprint(2, "%s: %s:%d %s:%d %s:%d\n", redtext("Powerups"), redtext("Q"), tmStats[i].itm[itQUAD].tooks, redtext("P"), tmStats[i].itm[itPENT].tooks, redtext("R"), tmStats[i].itm[itRING].tooks); // armors + megahealths G_bprint(2, "%s: %s:%d %s:%d %s:%d %s:%d\n", redtext("Armr&mhs"), redtext("ga"), tmStats[i].itm[itGA].tooks, redtext("ya"), tmStats[i].itm[itYA].tooks, redtext("ra"), tmStats[i].itm[itRA].tooks, redtext("mh"), tmStats[i].itm[itHEALTH_100].tooks); } else { G_bprint(2, "\220%s\221: %s:%s\n", tmStats[i].name, redtext("Wp"), (h_sg ? va(" %s%.0f%%", redtext("cg"), h_sg) : "")); } if (isCTF()) { if (cvar("k_ctf_runes")) { G_bprint(2, "%s: %s:%.0f%% %s:%.0f%% %s:%.0f%% %s:%.0f%%\n", redtext("RuneTime"), redtext("res"), tmStats[i].res, redtext("str"), tmStats[i].str, redtext("hst"), tmStats[i].hst, redtext("rgn"), tmStats[i].rgn); } G_bprint(2, "%s: %s:%d %s:%d %s:%d\n", redtext(" CTF"), redtext("pickups"), tmStats[i].pickups, redtext("caps"), tmStats[i].caps, redtext("returns"), tmStats[i].returns); G_bprint(2, "%s: %s:%d %s:%d\n", redtext(" Defends"), redtext("flag"), tmStats[i].f_defends, redtext("carrier"), tmStats[i].c_defends); } // rl G_bprint(2, "%s: %s:%d %s:%d %s:%d %s:%d\n", redtext(" RL"), redtext("Took"), tmStats[i].wpn[wpRL].tooks, redtext("Killed"), tmStats[i].wpn[wpRL].ekills, redtext("Dropped"), tmStats[i].wpn[wpRL].drops, redtext("Xfer"), tmStats[i].transferred_RLpacks); // lg G_bprint(2, "%s: %s:%d %s:%d %s:%d %s:%d\n", redtext(" LG"), redtext("Took"), tmStats[i].wpn[wpLG].tooks, redtext("Killed"), tmStats[i].wpn[wpLG].ekills, redtext("Dropped"), tmStats[i].wpn[wpLG].drops, redtext("Xfer"), tmStats[i].transferred_LGpacks); // damage if (deathmatch == 1) { G_bprint(2, "%s: %s:%.0f %s:%.0f %s:%.0f %s:%.0f\n", redtext(" Damage"), redtext("Tkn"), tmStats[i].dmg_t, redtext("Gvn"), tmStats[i].dmg_g, redtext("EWep"), tmStats[i].dmg_eweapon, redtext("Tm"), tmStats[i].dmg_team); } else { G_bprint(2, "%s: %s:%.0f %s:%.0f %s:%.0f\n", redtext(" Damage"), redtext("Tkn"), tmStats[i].dmg_t, redtext("Gvn"), tmStats[i].dmg_g, redtext("Tm"), tmStats[i].dmg_team); } // times G_bprint(2, "%s: %s:%d\n", redtext(" Time"), redtext("Quad"), (int)tmStats[i].itm[itQUAD].time); } G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } static void TeamsStats(void) { int i, sumfrags = 0, wasPrint = 0; if (isCA()) { CA_TeamsStats(); return; } // Summing up the frags to calculate team percentages for (i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { sumfrags += max(0, tmStats[i].frags + tmStats[i].gfrags); } // End of summing G_bprint( 2, "\n%s: %s\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Team scores"), redtext("frags \217 percentage")); for (i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { G_bprint(2, "\220%s\221: %d", tmStats[i].name, tmStats[i].frags); if (tmStats[i].gfrags) { G_bprint(2, " + (%d) = %d", tmStats[i].gfrags, tmStats[i].frags + tmStats[i].gfrags); } // effi G_bprint( 2, " \217 %.1f%%\n", (sumfrags > 0 ? ((float)(tmStats[i].frags + tmStats[i].gfrags)) / sumfrags * 100 : 0.0)); wasPrint = 1; } if (wasPrint) { G_bprint( 2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } } // Statistic file generation const char* GetMode(void) { if (cvar("k_instagib")) { return "instagib"; } else if (cvar("k_midair")) { return "midair"; } else if (isHoonyModeAny()) { return "hoonymode"; } else if (isRACE()) { return "race"; } else if (isCA()) { return "clan-arena"; } else if (isRA()) { return "rocket-arena"; } else if (isDuel()) { return "duel"; } else if (isTeam()) { return "team"; } else if (isCTF()) { return "ctf"; } else if (isFFA()) { return "ffa"; } else { return "unknown"; } } // Also used in //wps transmission char* WpName(weaponName_t wp) { switch (wp) { case wpAXE: return "axe"; case wpSG: return "sg"; case wpSSG: return "ssg"; case wpNG: return "ng"; case wpSNG: return "sng"; case wpGL: return "gl"; case wpRL: return "rl"; case wpLG: return "lg"; // shut up gcc case wpNONE: case wpMAX: return "unknown"; } return "unknown"; } char* ItName(itemName_t it) { switch (it) { case itHEALTH_15: return "health_15"; case itHEALTH_25: return "health_25"; case itHEALTH_100: return "health_100"; case itGA: return "ga"; case itYA: return "ya"; case itRA: return "ra"; case itQUAD: return "q"; case itPENT: return "p"; case itRING: return "r"; // shut up gcc case itNONE: case itMAX: return "unknown"; } return "unknown"; } qbool itPowerup(itemName_t it) { return ((it == itQUAD) || (it == itPENT) || (it == itRING)); } void S2di(fileHandle_t file_handle, const char *fmt, ...) { va_list argptr; char text[1024]; va_start(argptr, fmt); Q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); text[sizeof(text) - 1] = 0; trap_FS_WriteFile(text, strlen(text), file_handle); } static stats_format_t* FindStatsFormat(const char* requested_format) { int i; for (i = 0; i < sizeof(file_formats) / sizeof(file_formats[0]); ++i) { if (streq(requested_format, file_formats[i].name)) { return &file_formats[i]; } } // default to xml return &file_formats[0]; } static qbool CreateStatsFile(char* filename, char* ip, int port, stats_format_t* format) { gedict_t *p, *p2; fileHandle_t di_handle; int from1, from2; char *team = ""; int player_num = 0; int i = 0; if (format == NULL) { return false; } if (trap_FS_OpenFile(va("%s.%s", filename, format->name), &di_handle, FS_WRITE_BIN) < 0) { return false; } format->match_header(di_handle, ip, port); if (isRACE()) { format->race_detail(di_handle); } else { format->teams_header(di_handle); for (i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { format->team_detail(di_handle, i, &tmStats[i]); } format->teams_footer(di_handle, i); // } TEAMS // { PLAYERS for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { p->ready = 0; // clear mark } // get one player and search all his mates, mark served players via ->ready field // ghosts is served too format->players_header(di_handle); for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { team = getteam(p); if (p->ready /* || strnull( team ) */) { continue; // served or wrong team } for (from2 = 0, p2 = world; (p2 = find_plrghst(p2, &from2));) { if (p2->ready || strneq(team, getteam(p2))) { continue; // served or on different team } format->player_detail(di_handle, player_num++, p2, team); p2->ready = 1; // set mark } } format->players_footer(di_handle, player_num); // } PLAYERS } format->match_footer(di_handle); trap_FS_CloseFile(di_handle); return true; } void StatsToFile(void) { char name[256] = { 0 }, *ip = "", *port = ""; int i = 0; qbool written = false; qbool send_to_website = !strnull(cvar_string("sv_www_address")); qbool embed_in_mvd = (sv_extensions & SV_EXTENSIONS_MVDHIDDEN); stats_format_t* json_format = NULL; stats_format_t* format = NULL; if (strnull(ip = cvar_string("sv_local_addr")) || strnull(port = strchr(ip, ':')) || !(i = atoi(port + 1))) { return; } port[0] = 0; port++; if (strnull(cvar_string("serverdemo")) || (cvar("sv_demotxt") != 2)) { return; // doesn't record demo or doesn't want stats to be put in file } format = FindStatsFormat(cvar_string("k_demotxt_format")); json_format = FindStatsFormat("json"); // This file over-written every time snprintf(name, sizeof(name), "demoinfo_%s_%d", ip, i); // Always write json, so it can be embedded in demo if (json_format != NULL) { written = CreateStatsFile(name, ip, i, json_format); if (written) { // submit to central website if (send_to_website) { localcmd( "\nsv_web_postfile ServerApi/UploadGameStats \"\" \"%s.%s\" *internal authinfo\n", name, json_format->name); trap_executecmd(); } // if server supports embedding in .mvd/qtv stream, do that if (embed_in_mvd) { localcmd("\nsv_demoembedinfo \"%s.%s\"\n", name, json_format->name); trap_executecmd(); } } written = true; } // If non-json version required, generate now if (!streq(format->name, "json")) { written = CreateStatsFile(name, ip, i, format); } // add info if (written) { localcmd("\n" // why new line? "sv_demoinfoadd ** %s.%s\n", name, format->name); trap_executecmd(); } } float maxfrags, maxdeaths, maxfriend, maxeffi, maxcaps, maxdefends, maxsgeffi; int maxspree, maxspree_q, maxdmgg, maxdmgtd, maxrlkills; void OnePlayerStats(gedict_t *p, int tp) { float dmg_g; float dmg_t; float dmg_team; float dmg_self; float dmg_eweapon; float dmg_g_rl; float dmg_td; int dmg_sg; int dmg_ssg; int ra; int ya; int ga; int mh; int d_rl; int k_rl; int t_rl; int d_lg; int k_lg; int t_lg; int quad; int pent; int ring; float ph_rl; float vh_rl; float h_rl; float a_rl; float ph_gl; float vh_gl; float a_gl; float h_lg; float a_lg; float h_sg; float a_sg; float h_ssg; float a_ssg; float e_sg; float e_ssg; float e_lg; int res; int str; int hst; int rgn; dmg_g = p->ps.dmg_g; dmg_g_rl = p->ps.dmg_g_rl; dmg_t = p->ps.dmg_t; dmg_team = p->ps.dmg_team; dmg_self = p->ps.dmg_self; dmg_eweapon = p->ps.dmg_eweapon; dmg_td = p->deaths <= 0 ? 99999 : (int)(p->ps.dmg_t / p->deaths); ra = p->ps.itm[itRA].tooks; ya = p->ps.itm[itYA].tooks; ga = p->ps.itm[itGA].tooks; mh = p->ps.itm[itHEALTH_100].tooks; quad = p->ps.itm[itQUAD].tooks; pent = p->ps.itm[itPENT].tooks; ring = p->ps.itm[itRING].tooks; h_rl = p->ps.wpn[wpRL].hits; vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; vh_gl = p->ps.wpn[wpGL].vhits; a_gl = p->ps.wpn[wpGL].attacks; h_lg = p->ps.wpn[wpLG].hits; a_lg = p->ps.wpn[wpLG].attacks; h_sg = p->ps.wpn[wpSG].hits; a_sg = p->ps.wpn[wpSG].attacks; dmg_sg = p->ps.wpn[wpSG].edamage; dmg_ssg = p->ps.wpn[wpSSG].edamage; h_ssg = p->ps.wpn[wpSSG].hits; a_ssg = p->ps.wpn[wpSSG].attacks; e_sg = 100.0 * h_sg / max(1, a_sg); e_ssg = 100.0 * h_ssg / max(1, a_ssg); ph_gl = 100.0 * vh_gl / max(1, a_gl); ph_rl = 100.0 * vh_rl / max(1, a_rl); e_lg = 100.0 * h_lg / max(1, a_lg); d_rl = p->ps.wpn[wpRL].drops; k_rl = p->ps.wpn[wpRL].ekills; t_rl = p->ps.wpn[wpRL].tooks; d_lg = p->ps.wpn[wpLG].drops; k_lg = p->ps.wpn[wpLG].ekills; t_lg = p->ps.wpn[wpLG].tooks; if (isCTF() && ((g_globalvars.time - match_start_time) > 0)) { res = (p->ps.res_time / (g_globalvars.time - match_start_time)) * 100; str = (p->ps.str_time / (g_globalvars.time - match_start_time)) * 100; hst = (p->ps.hst_time / (g_globalvars.time - match_start_time)) * 100; rgn = (p->ps.rgn_time / (g_globalvars.time - match_start_time)) * 100; } else { res = str = hst = rgn = 0; } if (tp) { G_bprint(2, "\235\236\236\236\236\236\236\236\236\237\n"); } G_bprint( 2, "\207 %s%s:\n" " %d (%d) %s%.1f%%\n", (isghost(p) ? "\203" : ""), getname(p), (isCTF() ? (int)(p->s.v.frags - p->ps.ctf_points) : (int)p->s.v.frags), (isCTF() ? (int)(p->s.v.frags - p->ps.ctf_points - p->deaths) : (int)(p->s.v.frags - p->deaths)), (tp ? va("%d ", (int)p->friendly) : ""), p->efficiency); // qqshka - force show this always // if ( !tp || cvar( "tp_players_stats" ) ) { // weapons G_bprint(2, "%s:%s%s%s%s%s\n", redtext("Wp"), (a_lg ? va(" %s%.1f%% (%d/%d)", redtext("lg"), e_lg, (int)h_lg, (int)a_lg) : ""), (ph_rl ? va(" %s%.1f%% (%d/%d)", redtext("rl"), ph_rl, (int)vh_rl, (int)a_rl) : ""), (ph_gl ? va(" %s%.1f%%", redtext("gl"), ph_gl) : ""), (e_sg ? va(" %s%.1f%% (%d)", redtext("sg"), e_sg, dmg_sg) : ""), (e_ssg ? va(" %s%.1f%% (%d)", redtext("ssg"), e_ssg, dmg_ssg) : "")); // rockets detail if (!lgc_enabled()) { G_bprint(2, "%s: %s:%.1f %s:%.0f\n", redtext("RL skill"), redtext("ad"), vh_rl ? (dmg_g_rl / vh_rl) : 0., redtext("dh"), h_rl); } // velocity if (isDuel()) { G_bprint(2, "%s: %s:%.1f %s:%.1f\n", redtext(" Speed"), redtext("max"), p->ps.velocity_max, redtext("average"), p->ps.vel_frames > 0 ? p->ps.velocity_sum / p->ps.vel_frames : 0.); } // armors + megahealths if (!lgc_enabled()) { G_bprint(2, "%s: %s:%d %s:%d %s:%d %s:%d\n", redtext("Armr&mhs"), redtext("ga"), ga, redtext("ya"), ya, redtext("ra"), ra, redtext("mh"), mh); } // powerups if (isTeam() || isCTF()) { G_bprint(2, "%s: %s:%d %s:%d %s:%d\n", redtext("Powerups"), redtext("Q"), quad, redtext("P"), pent, redtext("R"), ring); } if (isCTF()) { if (cvar("k_ctf_runes")) { G_bprint(2, "%s: %s:%d%% %s:%d%% %s:%d%% %s:%d%%\n", redtext("RuneTime"), redtext("res"), res, redtext("str"), str, redtext("hst"), hst, redtext("rgn"), rgn); } G_bprint(2, "%s: %s:%d %s:%d %s:%d\n", redtext(" CTF"), redtext("pickups"), p->ps.pickups, redtext("caps"), p->ps.caps, redtext("returns"), p->ps.returns); G_bprint(2, "%s: %s:%d %s:%d\n", redtext(" Defends"), redtext("flag"), p->ps.f_defends, redtext("carrier"), p->ps.c_defends); } // rl if (isTeam()) { G_bprint( 2, "%s: %s:%d %s:%d %s:%d%s\n", redtext(" RL"), redtext("Took"), t_rl, redtext("Killed"), k_rl, redtext("Dropped"), d_rl, (p->ps.transferred_RLpacks ? va(" %s:%d", redtext("Xfer"), p->ps.transferred_RLpacks) : "")); } // lg if (isTeam()) { G_bprint( 2, "%s: %s:%d %s:%d %s:%d%s\n", redtext(" LG"), redtext("Took"), t_lg, redtext("Killed"), k_lg, redtext("Dropped"), d_lg, (p->ps.transferred_LGpacks ? va(" %s:%d", redtext("Xfer"), p->ps.transferred_LGpacks) : "")); } // damage if (isTeam() && (deathmatch == 1)) { G_bprint(2, "%s: %s:%.0f %s:%.0f %s:%.0f %s:%.0f %s:%.0f %s:%.0f\n", redtext(" Damage"), redtext("Tkn"), dmg_t, redtext("Gvn"), dmg_g, redtext("EWep"), dmg_eweapon, redtext("Tm"), dmg_team, redtext("Self"), dmg_self, redtext("ToDie"), dmg_td == -1 ? 99999 : dmg_td); } else { G_bprint(2, "%s: %s:%.0f %s:%.0f %s:%.0f %s:%.0f %s:%.0f\n", redtext(" Damage"), redtext("Tkn"), dmg_t, redtext("Gvn"), dmg_g, redtext("Tm"), dmg_team, redtext("Self"), dmg_self, redtext("ToDie"), dmg_td == -1 ? 99999 : dmg_td); } // times if ((g_globalvars.time - match_start_time) > 0) { if (isDuel()) { G_bprint( 2, "%s: %s:%d (%d%%)\n", redtext(" Time"), redtext("Control"), (int)p->ps.control_time, (int)((p->ps.control_time / (g_globalvars.time - match_start_time)) * 100)); } else { G_bprint(2, "%s: %s:%d\n", redtext(" Time"), redtext("Quad"), (int)p->ps.itm[itQUAD].time); } } if (isDuel()) { // endgame h & a G_bprint(2, " %s: %s:%d %s:", redtext("EndGame"), redtext("H"), (int)p->s.v.health, redtext("A")); if ((int)p->s.v.armorvalue) { G_bprint(2, "%s%d\n", armor_type(p->s.v.items), (int)p->s.v.armorvalue); } else { G_bprint(2, "0\n"); } // overtime h & a if (k_overtime) { G_bprint(2, " %s: %s:%d %s:", redtext("OverTime"), redtext("H"), (int)p->ps.ot_h, redtext("A")); if ((int)p->ps.ot_a) { G_bprint(2, "%s%d\n", armor_type(p->ps.ot_items), (int)p->ps.ot_a); } else { G_bprint(2, "0\n"); } } } else { G_bprint(2, "%s: %s:%d %s:%d\n", redtext(" Streaks"), redtext("Frags"), p->ps.spree_max, redtext("QuadRun"), p->ps.spree_max_q); } // spawnfrags if (!isCTF() && !lgc_enabled()) { G_bprint(2, " %s: %d\n", redtext("SpawnFrags"), p->ps.spawn_frags); } if (lgc_enabled() && a_lg) { int over = p->ps.lgc_overshaft; int under = p->ps.lgc_undershaft; G_bprint(PRINT_HIGH, " %s : \20%d\21\n", redtext("LGC Score"), (int)(e_lg * p->s.v.frags)); G_bprint(PRINT_HIGH, " %s : %.1f%% (%d/%d)\n", redtext("Overshaft"), over * 100.0f / a_lg, (int)over, (int)a_lg); G_bprint(PRINT_HIGH, " %s: %.1f%% (%d/%d)\n", redtext("Undershaft"), under * 100.0f / a_lg, (int)under, (int)a_lg); } // } if (!tp) { G_bprint(2, "\235\236\236\236\236\236\236\236\236\237\n"); } maxfrags = max((isCTF() ? p->s.v.frags - p->ps.ctf_points : p->s.v.frags), maxfrags); maxdeaths = max(p->deaths, maxdeaths); maxfriend = max(p->friendly, maxfriend); maxeffi = max(p->efficiency, maxeffi); maxcaps = max(p->ps.caps, maxcaps); maxdefends = max(p->ps.f_defends, maxdefends); maxspree = max(p->ps.spree_max, maxspree); maxspree_q = max(p->ps.spree_max_q, maxspree_q); maxdmgg = max(p->ps.dmg_g, maxdmgg); maxdmgtd = max((int)(p->ps.dmg_t / p->deaths), maxdmgtd); maxrlkills = max(p->ps.wpn[wpRL].ekills, maxrlkills); maxsgeffi = max(e_sg, maxsgeffi); } // Players statistics printout here void PlayersStats(void) { gedict_t *p, *p2; char *tmp, *tmp2; int tp, first, from1, from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } // Probably low enough for a start value :) maxfrags = -999999; maxeffi = maxfriend = maxdeaths = maxcaps = maxdefends = maxsgeffi = 0; maxspree = maxspree_q = maxdmgtd = maxdmgg = maxrlkills = 0; tp = isTeam() || isCTF(); G_bprint( 2, "\n%s:\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Player statistics")); if (!cvar("k_midair")) { G_bprint(2, "%s (%s) %s\217 %s\n", redtext("Frags"), redtext("rank"), (tp ? redtext("friendkills ") : ""), redtext("efficiency")); } from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { first = 1; from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark if (first) { first = 0; if (tp) { G_bprint(2, "Team \220%s\221:\n", tmp); } } if (isCTF()) { if ((p2->s.v.frags - p2->ps.ctf_points) < 1) { p2->efficiency = 0; } else { p2->efficiency = (p2->s.v.frags - p2->ps.ctf_points) / (p2->s.v.frags - p2->ps.ctf_points + p2->deaths) * 100; } } else if (isRA()) { p2->efficiency = ( (p2->ps.loses + p2->ps.wins) ? (p2->ps.wins * 100.0f) / (p2->ps.loses + p2->ps.wins) : 0); } else { if (p2->s.v.frags < 1) { p2->efficiency = 0; } else { p2->efficiency = p2->s.v.frags / (p2->s.v.frags + p2->deaths) * 100; } } if (cvar("k_midair")) { OnePlayerMidairStats(p2, tp); } else if (cvar("k_instagib")) { OnePlayerInstagibStats(p2, tp); } else { OnePlayerStats(p2, tp); } } } p2 = find_plrghst(p2, &from2); if (!p2) { G_bprint(2, "\n"); // split players from different teams via \n } } } p = find_plrghst(p, &from1); } } // Print the high score table void TopStats(void) { gedict_t *p; float f1, h_sg, a_sg; int from, dmg_sg; G_bprint(2, "\220%s\221 %s:\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n" " Frags: ", mapname, redtext("top scorers")); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((!isCTF() && (p->s.v.frags == maxfrags)) || (isCTF() && ((p->s.v.frags - p->ps.ctf_points) == maxfrags))) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), (int)maxfrags); f1 = 1; } p = find_plrghst(p, &from); } G_bprint(2, " Deaths: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->deaths == maxdeaths) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), (int)maxdeaths); f1 = 1; } p = find_plrghst(p, &from); } if (maxfriend) { G_bprint(2, "Friendkills: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->friendly == maxfriend) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), (int)maxfriend); f1 = 1; } p = find_plrghst(p, &from); } } G_bprint(2, " Efficiency: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->efficiency == maxeffi) { G_bprint(2, "%s%s%s \220%.1f%%\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxeffi); f1 = 1; } p = find_plrghst(p, &from); } if (maxspree) { G_bprint(2, " FragStreak: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.spree_max == maxspree) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxspree); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspree_q) { G_bprint(2, " QuadRun: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.spree_max_q == maxspree_q) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxspree_q); f1 = 1; } p = find_plrghst(p, &from); } } if (maxrlkills && deathmatch == 1) { G_bprint(2, " RL Killer: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.wpn[wpRL].ekills == maxrlkills) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxrlkills); f1 = 1; } p = find_plrghst(p, &from); } } if (maxsgeffi && deathmatch == 1) { G_bprint(2, "Boomsticker: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { h_sg = p->ps.wpn[wpSG].hits; a_sg = p->ps.wpn[wpSG].attacks; dmg_sg = p->ps.wpn[wpSG].edamage; h_sg = 100.0 * h_sg / max(1, a_sg); if (h_sg == maxsgeffi) { G_bprint(2, "%s%s%s \220%.1f%% (%d)\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxsgeffi, dmg_sg); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdmgtd) { G_bprint(2, " Survivor: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((int)(p->deaths <= 0 ? 99999 : p->ps.dmg_t / p->deaths) == maxdmgtd) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxdmgtd); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdmgg) { G_bprint(2, "Annihilator: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.dmg_g == maxdmgg) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), maxdmgg); f1 = 1; } p = find_plrghst(p, &from); } } if (isCTF()) { if (maxcaps > 0) { G_bprint(2, " Captures: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.caps == maxcaps) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), (int)maxcaps); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdefends > 0) { G_bprint(2, "FlagDefends: "); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.f_defends == maxdefends) { G_bprint(2, "%s%s%s \220%d\221\n", (f1 ? " " : ""), (isghost(p) ? "\203" : ""), getname(p), (int)maxdefends); f1 = 1; } p = find_plrghst(p, &from); } } } G_bprint(2, "\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } void TopMidairStats(void) { gedict_t *p; float f1, vh_rl, a_rl, ph_rl, maxtopheight = 0, maxtopavgheight = 0, maxrlefficiency = 0; int from, maxscore = -99999, maxkills = 0, maxmidairs = 0, maxstomps = 0, maxstreak = 0, maxspawnfrags = 0, maxbonus = 0; from = f1 = 0; p = find_plrghst(world, &from); while (p) { maxscore = max(p->s.v.frags, maxscore); maxkills = max(p->ps.mid_total + p->ps.mid_stomps, maxkills); maxmidairs = max(p->ps.mid_total, maxmidairs); maxstomps = max(p->ps.mid_stomps, maxstomps); maxstreak = max(p->ps.spree_max, maxstreak); maxspawnfrags = max(p->ps.spawn_frags, maxspawnfrags); maxbonus = max(p->ps.mid_bonus, maxbonus); maxtopheight = max(p->ps.mid_maxheight, maxtopheight); maxtopavgheight = max(p->ps.mid_avgheight, maxtopavgheight); vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; ph_rl = 100.0 * vh_rl / max(1, a_rl); maxrlefficiency = max(ph_rl, maxrlefficiency); p = find_plrghst(p, &from); } G_bprint(2, "%s:\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Top performers")); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->s.v.frags == maxscore) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("score")), (isghost(p) ? "\203" : ""), getname(p), maxscore); f1 = 1; } p = find_plrghst(p, &from); } if (maxkills) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_total + p->ps.mid_stomps) == maxkills) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("kills")), (isghost(p) ? "\203" : ""), getname(p), maxkills); f1 = 1; } p = find_plrghst(p, &from); } } if (maxmidairs) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_total) == maxmidairs) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("midairs")), (isghost(p) ? "\203" : ""), getname(p), maxmidairs); f1 = 1; } p = find_plrghst(p, &from); } } if (maxstomps) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_stomps) == maxstomps) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("head stomps")), (isghost(p) ? "\203" : ""), getname(p), maxstomps); f1 = 1; } p = find_plrghst(p, &from); } } if (maxstreak) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.spree_max) == maxstreak) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("streak")), (isghost(p) ? "\203" : ""), getname(p), maxstreak); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspawnfrags) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.spawn_frags) == maxspawnfrags) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("spawn frags")), (isghost(p) ? "\203" : ""), getname(p), maxspawnfrags); f1 = 1; } p = find_plrghst(p, &from); } } if (maxbonus) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_bonus) == maxbonus) { G_bprint(2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("bonus fiend")), (isghost(p) ? "\203" : ""), getname(p), maxbonus); f1 = 1; } p = find_plrghst(p, &from); } } if (maxtopheight) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_maxheight) == maxtopheight) { G_bprint(2, " %-13s: %s%s (%.1f)\n", (f1 ? "" : redtext("highest kill")), (isghost(p) ? "\203" : ""), getname(p), maxtopheight); f1 = 1; } p = find_plrghst(p, &from); } } if (maxtopavgheight) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_avgheight) == maxtopavgheight) { G_bprint(2, " %-13s: %s%s (%.1f)\n", (f1 ? "" : redtext("avg height")), (isghost(p) ? "\203" : ""), getname(p), maxtopavgheight); f1 = 1; } p = find_plrghst(p, &from); } } from = f1 = 0; p = find_plrghst(world, &from); while (p) { vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; ph_rl = 100.0 * vh_rl / max(1, a_rl); if ((ph_rl) == maxrlefficiency) { G_bprint(2, " %-13s: %s%s (%.1f%%)\n", (f1 ? "" : redtext("rl efficiency")), (isghost(p) ? "\203" : ""), getname(p), maxrlefficiency); f1 = 1; } p = find_plrghst(p, &from); } G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } void OnePlayerInstagibStats(gedict_t *p, int tp) { float h_ax, a_ax, h_sg, a_sg, h_ssg, a_ssg; char *stats_text; h_sg = p->ps.wpn[wpSG].hits; a_sg = p->ps.wpn[wpSG].attacks; h_ssg = p->ps.wpn[wpSSG].hits; a_ssg = p->ps.wpn[wpSSG].attacks; h_ax = p->ps.wpn[wpAXE].hits; a_ax = p->ps.wpn[wpAXE].attacks; h_ax = 100.0 * h_ax / max(1, a_ax); h_sg = 100.0 * h_sg / max(1, a_sg); h_ssg = 100.0 * h_ssg / max(1, a_ssg); stats_text = va("\n\207 %s: %s%s \207\n", "PLAYER", (isghost(p) ? "\203" : ""), getname(p)); stats_text = va("%s \220%s\221\n", stats_text, "SCORES"); stats_text = va("%s %s: %.1f\n", stats_text, redtext("Efficiency"), p->efficiency); stats_text = va("%s %s: %d\n", stats_text, redtext("Points"), (int)p->s.v.frags); stats_text = va("%s %s: %d\n", stats_text, redtext("Frags"), p->ps.i_cggibs + p->ps.i_axegibs + p->ps.i_stompgibs); if (tp) stats_text = va("%s %s: %d\n", stats_text, redtext("Teamkills"), (int)p->friendly); stats_text = va("%s %s: %d\n", stats_text, redtext("Deaths"), (int)p->deaths); stats_text = va("%s %s: %d\n", stats_text, redtext("Streaks"), p->ps.spree_max); stats_text = va("%s %s: %d\n", stats_text, redtext("Spawns"), p->ps.spawn_frags); stats_text = va("%s \220%s\221\n", stats_text, "SPEED"); stats_text = va("%s %s: %.1f\n", stats_text, redtext("Maximum"), p->ps.velocity_max); stats_text = va("%s %s: %.1f\n", stats_text, redtext("Average"), p->ps.vel_frames > 0 ? p->ps.velocity_sum / p->ps.vel_frames : 0.); stats_text = va("%s \220%s\221\n", stats_text, "WEAPONS"); if (cvar("k_instagib")) { stats_text = va("%s %s: %s", stats_text, redtext("Coilgun"), (a_sg ? va("%.1f%% (%d)", h_sg, p->ps.i_cggibs) : "")); stats_text = va("%s%s", stats_text, (a_sg ? "" : "n/u")); } stats_text = va("%s\n", stats_text); stats_text = va("%s %s: %s", stats_text, redtext("Axe"), (a_ax ? va("%.1f%% (%d)", h_ax, p->ps.i_axegibs) : "")); stats_text = va("%s%s", stats_text, (a_ax ? "" : "n/u")); stats_text = va("%s\n", stats_text); stats_text = va("%s \220%s\221\n", stats_text, "GIBS"); stats_text = va("%s %s: %d\n", stats_text, redtext("Coilgun"), p->ps.i_cggibs); stats_text = va("%s %s: %d\n", stats_text, redtext("Axe"), p->ps.i_axegibs); stats_text = va("%s %s: %d\n", stats_text, redtext("Stomps"), p->ps.i_stompgibs); stats_text = va("%s \220%s\221\n", stats_text, "MULTIGIBS"); stats_text = va("%s %s: %d\n", stats_text, redtext("Total Multigibs"), p->ps.i_multigibs); stats_text = va("%s %s: %d\n", stats_text, redtext("Maximum Victims"), p->ps.i_maxmultigibs); stats_text = va("%s \220%s\221\n", stats_text, "AIRGIBS"); stats_text = va("%s %s: %d\n", stats_text, redtext("Total"), p->ps.i_airgibs); stats_text = va("%s %s: %d\n", stats_text, redtext("Total Height"), p->ps.i_height); stats_text = va("%s %s: %d\n", stats_text, redtext("Maximum Height"), p->ps.i_maxheight); stats_text = va("%s %s: %.1f\n", stats_text, redtext("Average Height"), p->ps.i_airgibs ? p->ps.i_height / p->ps.i_airgibs : 0.); G_bprint(2, "%s", stats_text); if (!tp) { G_bprint( 2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } maxfrags = max((isCTF() ? p->s.v.frags - p->ps.ctf_points : p->s.v.frags), maxfrags); maxdeaths = max(p->deaths, maxdeaths); maxfriend = max(p->friendly, maxfriend); maxeffi = max(p->efficiency, maxeffi); maxcaps = max(p->ps.caps, maxcaps); maxdefends = max(p->ps.f_defends, maxdefends); maxspree = max(p->ps.spree_max, maxspree); maxspree_q = max(p->ps.spree_max_q, maxspree_q); maxdmgg = max(p->ps.dmg_g, maxdmgg); maxrlkills = max(p->ps.wpn[wpRL].ekills, maxrlkills); maxsgeffi = max(h_sg, maxsgeffi); } void OnePlayerMidairStats(gedict_t *p, int tp) { float vh_rl, a_rl, ph_rl; vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; ph_rl = 100.0 * vh_rl / max(1, a_rl); G_bprint(2, "\207 %s%s: %d\n", (isghost(p) ? "\203" : ""), getname(p), (int)p->s.v.frags); G_bprint(2, " %-13s: %d\n", redtext("total midairs"), p->ps.mid_total); G_bprint(2, " %12s: %d\n", "bronze", p->ps.mid_bronze); G_bprint(2, " %12s: %d\n", "silver", p->ps.mid_silver); G_bprint(2, " %12s: %d\n", "gold", p->ps.mid_gold); G_bprint(2, " %12s: %d\n", "platinum", p->ps.mid_platinum); G_bprint(2, " %-13s: %d\n", redtext("stomps"), p->ps.mid_stomps); G_bprint(2, " %-13s: %d\n", redtext("streak"), p->ps.spree_max); G_bprint(2, " %-13s: %d\n", redtext("spawnfrags"), p->ps.spawn_frags); G_bprint(2, " %-13s: %d\n", redtext("bonuses"), p->ps.mid_bonus); G_bprint(2, " %-13s: %.1f\n", redtext("max height"), p->ps.mid_maxheight); G_bprint(2, " %-13s: %.1f\n", redtext("avg height"), (p->ps.mid_maxheight ? p->ps.mid_avgheight : 0)); G_bprint(2, " %-13s: %s\n", redtext("rl efficiency"), (ph_rl ? va("%.1f%%", ph_rl) : " 0.0%")); G_bprint(2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n"); } void EM_CorrectStats(void) { gedict_t *p; int i; for (p = world; (p = find_plr(p));) { // take away powerups so scoreboard looks normal p->s.v.items = (int)p->s.v.items & ~(IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD); p->s.v.effects = (int)p->s.v.effects & ~(EF_DIMLIGHT | EF_BRIGHTLIGHT | EF_BLUE | EF_RED | EF_GREEN); p->invisible_finished = 0; p->invincible_finished = 0; p->super_damage_finished = 0; p->radsuit_finished = 0; p->ps.spree_max = max(p->ps.spree_current, p->ps.spree_max); p->ps.spree_max_q = max(p->ps.spree_current_q, p->ps.spree_max_q); for (i = itNONE; i < itMAX; i++) { adjust_pickup_time(&p->it_pickup_time[i], &p->ps.itm[i].time); } for (i = wpNONE; i < wpMAX; i++) { adjust_pickup_time(&p->wp_pickup_time[i], &p->ps.wpn[i].time); } if (p->control_start_time) { p->ps.control_time += g_globalvars.time - p->control_start_time; p->control_start_time = 0; } if (isCTF()) { // if a player ends the game with a rune adjust their rune time if (p->ctf_flag & CTF_RUNE_RES) { p->ps.res_time += g_globalvars.time - p->rune_pickup_time; } else if (p->ctf_flag & CTF_RUNE_STR) { p->ps.str_time += g_globalvars.time - p->rune_pickup_time; } else if (p->ctf_flag & CTF_RUNE_HST) { p->ps.hst_time += g_globalvars.time - p->rune_pickup_time; } else if (p->ctf_flag & CTF_RUNE_RGN) { p->ps.rgn_time += g_globalvars.time - p->rune_pickup_time; } } } } void MatchEndStats(void) { gedict_t *p; if (isHoonyModeAny() && !HM_is_game_over()) { return; } if (isTeam() || isCTF()) { CollectTpStats(); } if (isRACE()) { race_match_stats(); } else { PlayersStats(); // all info about any player if (!cvar("k_midair")) { if (isTeam() || isCTF()) { SummaryTPStats(); // print summary stats like armos powerups weapons etc.. } if (!isDuel()) // top stats only in non duel modes { TopStats(); // print top frags tkills deaths... } } else { TopMidairStats(); } if (isTeam() || isCTF()) { TeamsStats(); // print basic info like frags for each team } if ((p = find(world, FOFCLSN, "ghost"))) // show legend :) { G_bprint(2, "\n\203 - %s player\n\n", redtext("disconnected")); } } StatsToFile(); lastStatsData = true; } void SM_PrepareTeamsStats(void) { int i; tmStats_cnt = 0; memset(tmStats, 0, sizeof(tmStats)); memset(tmStats_names, 0, sizeof(tmStats_names)); for (i = 0; i < MAX_TM_STATS; i++) { tmStats[i].name = tmStats_names[i]; } } QW-Group-ktx-d05d6ca/src/statsTables.c000066400000000000000000001424001475442401000176550ustar00rootroot00000000000000/* * This file contains the logic to print the overhauled Endgame Statistics, invoked with the /laststats command */ #include "g_local.h" #include "stats.h" static void onePlayerMidairStats(gedict_t *p); static void onePlayerMidairKillStats(gedict_t *p); static void onePlayerInstagibStats(gedict_t *p); static void onePlayerInstagibKillStats(gedict_t *p); static void onePlayerLGCStats(gedict_t *p); static void onePlayerKillStats(gedict_t *p, int tp); static void onePlayerItemStats(gedict_t *p, int tp); static void onePlayerWeaponEffiStats(gedict_t *p); static void onePlayerWeaponDmgStats(gedict_t *p); static void onePlayerWeaponTakenStats(gedict_t *p); static void onePlayerWeaponDroppedStats(gedict_t *p); static void onePlayerWeaponKillStats(gedict_t *p); static void onePlayerEnemyWeaponKillStats(gedict_t *p); static void onePlayerDamageStats(gedict_t *p); static void onePlayerItemTimeStats(gedict_t *p, int tp); static void onePlayerWeaponTimeStats(gedict_t *p); static void onePlayerCTFStats(gedict_t *p); static void calculateEfficiency(gedict_t *player); static void playerMidairStats(void); static void playerMidairKillStats(void); static void topMidairStats(void); static void playerInstagibStats(void); static void playerInstagibKillStats(void); static void playerLGCStats(void); static void playersKillStats(void); static void playersItemStats(void); static void playersWeaponEffiStats(void); static void playersWeaponDmgStats(void); static void playersWeaponTakenStats(void); static void playersWeaponDroppedStats(void); static void playersWeaponKillStats(void); static void playersEnemyWeaponKillStats(void); static void playersDamageStats(void); static void playersItemTimeStats(void); static void playersWeaponTimeStats(void); static void playersCTFStats(void); static void collectTpStats(void); static void summaryTPStats(void); static void topStats(void); static teamStats_t tmStatsTables[MAX_TM_STATS]; static int tmStatsTables_cnt = 0; qbool lastStatsData = false; void MatchEndStatsTables(void) { gedict_t *p; if (isHoonyModeAny() && !HM_is_game_over()) { return; } if (!lastStatsData) { G_sprint(self, 2, "Laststats data empty\n"); return; } if (cvar("k_midair")) { playerMidairStats(); playerMidairKillStats(); topMidairStats(); } else if (cvar("k_instagib")) { playerInstagibStats(); playerInstagibKillStats(); } else if (lgc_enabled()) { playerLGCStats(); } else { playersKillStats(); playersItemStats(); playersWeaponEffiStats(); playersWeaponDmgStats(); playersWeaponTakenStats(); playersWeaponDroppedStats(); playersWeaponKillStats(); playersEnemyWeaponKillStats(); playersDamageStats(); playersItemTimeStats(); playersWeaponTimeStats(); if (isCTF()) { playersCTFStats(); } if (isTeam() || isCTF()) { collectTpStats(); summaryTPStats(); // print summary stats like armos powerups weapons etc.. } if (!isDuel()) // top stats only in non duel modes { topStats(); // print top frags tkills deaths... } if ((p = find(world, FOFCLSN, "ghost"))) // show legend :) { G_sprint(self, 2, "\n\203 - %s player\n\n", redtext("disconnected")); } } StatsToFile(); } static void onePlayerMidairStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%5s|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.mid_total, p->ps.mid_bronze, p->ps.mid_silver, p->ps.mid_gold, p->ps.mid_platinum, p->ps.mid_stomps, p->ps.mid_bonus, va("%.1f", p->ps.mid_maxheight), va("%.1f", (p->ps.mid_maxheight ? p->ps.mid_avgheight : 0))); } static void onePlayerMidairKillStats(gedict_t *p) { float vh_rl; float a_rl; float e_rl; vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; e_rl = 100.0 * vh_rl / max(1, a_rl); G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)p->s.v.frags, p->ps.spawn_frags, p->ps.spree_max, (e_rl == 100 ? va("%.0f%%", e_rl) : va("%.1f%%", e_rl))); } static void onePlayerInstagibStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%4d|%4d|%4d|%4d|%4d|%4d|%4d|%4d|%4d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.i_cggibs, p->ps.i_axegibs, p->ps.i_stompgibs, p->ps.i_multigibs, p->ps.i_maxmultigibs, p->ps.i_airgibs, p->ps.i_height, p->ps.i_maxheight, p->ps.i_rings); } static void onePlayerInstagibKillStats(gedict_t *p) { float h_sg; float a_sg; h_sg = p->ps.wpn[wpSG].hits; a_sg = p->ps.wpn[wpSG].attacks; G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)p->s.v.frags, p->ps.i_cggibs + p->ps.i_axegibs + p->ps.i_stompgibs, (int)p->deaths, p->ps.spawn_frags, p->ps.spree_max, (a_sg ? va("%.1f%%", h_sg) : "-")); } static void onePlayerLGCStats(gedict_t *p) { int over; int under; float a_lg; float h_lg; float e_lg; over = p->ps.lgc_overshaft; under = p->ps.lgc_undershaft; a_lg = p->ps.wpn[wpLG].attacks; h_lg = p->ps.wpn[wpLG].hits; e_lg = 100.0 * h_lg / max(1, a_lg); G_sprint(self, 2, "%-20s|%5d|%5s|%5s|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)(e_lg * p->s.v.frags), (a_lg != 0 ? va("%.1f%%", ((over * 100.0f) / a_lg)) : "0.0%"), (a_lg != 0 ? va("%.1f%%", ((under * 100.0f) / a_lg)) : "0.0%"), (e_lg == 100 ? va("%.0f%%", e_lg) : va("%.1f%%", e_lg))); } static void onePlayerKillStats(gedict_t *p, int tp) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5s|%5d|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (isCTF() ? (int)(p->s.v.frags - p->ps.ctf_points) : (int)p->s.v.frags), (int)(p->kills), (isCTF() ? (int)(p->ps.ctf_points - p->deaths) : (int)(p->deaths)), (int)(p->suicides), (tp ? va("%d", (int)p->friendly) : "-"), p->ps.spawn_frags, ((p->efficiency >= 100) ? va("%.0f%%", p->efficiency) : ((p->efficiency == 0)? va(" %.1f%%", p->efficiency) : va("%.1f%%", p->efficiency)))); } static void onePlayerItemStats(gedict_t *p, int tp) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5s|%5s|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.itm[itGA].tooks, p->ps.itm[itYA].tooks, p->ps.itm[itRA].tooks, p->ps.itm[itHEALTH_100].tooks, (tp ? va("%d", p->ps.itm[itQUAD].tooks) : "-"), (tp ? va("%d", p->ps.itm[itPENT].tooks) : "-"), (tp ? va("%d", p->ps.itm[itRING].tooks) : "-")); } static void onePlayerWeaponEffiStats(gedict_t *p) { float h_lg; float a_lg; float e_lg; float vh_rl; float a_rl; float e_rl; float vh_gl; float a_gl; float e_gl; float a_sng; float e_sng; float h_sng; float a_ng; float e_ng; float h_ng; float a_ssg; float e_ssg; float h_ssg; float h_sg; float a_sg; float e_sg; h_lg = p->ps.wpn[wpLG].hits; a_lg = p->ps.wpn[wpLG].attacks; vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; vh_gl = p->ps.wpn[wpGL].vhits; a_gl = p->ps.wpn[wpGL].attacks; h_sng = p->ps.wpn[wpSNG].hits; a_sng = p->ps.wpn[wpSNG].attacks; h_ng = p->ps.wpn[wpNG].hits; a_ng = p->ps.wpn[wpNG].attacks; h_ssg = p->ps.wpn[wpSSG].hits; a_ssg = p->ps.wpn[wpSSG].attacks; h_sg = p->ps.wpn[wpSG].hits; a_sg = p->ps.wpn[wpSG].attacks; e_lg = 100.0 * h_lg / max(1, a_lg); e_rl = 100.0 * vh_rl / max(1, a_rl); e_gl = 100.0 * vh_gl / max(1, a_gl); e_sng = 100.0 * h_sng / max(1, a_sng); e_ng = 100.0 * h_ng / max(1, a_ng); e_ssg = 100.0 * h_ssg / max(1, a_ssg); e_sg = 100.0 * h_sg / max(1, a_sg); G_sprint(self, 2, "%-20s|%5s|%5s|%5s|%5s|%5s|%5s|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (a_lg ? ((e_lg >= 100)? va("%.0f%%", e_lg) : va("%.1f%%", e_lg)) : "-"), (a_rl ? ((e_rl >= 100) ? va("%.0f%%", e_rl) : va("%.1f%%", e_rl)) : "-"), (a_gl ? ((e_gl >= 100) ? va("%.0f%%", e_gl) : va("%.1f%%", e_gl)) : "-"), (a_sng ? ((e_sng >= 100) ? va("%.0f%%", e_sng) : va("%.1f%%", e_sng)) : "-"), (a_ng ? ((e_ng >= 100) ? va("%.0f%%", e_ng) : va("%.1f%%", e_ng)) : "-"), (a_ssg ? ((e_ssg >= 100) ? va("%.0f%%", e_ssg) : va("%.1f%%", e_ssg)) : "-"), (a_sg ? ((e_sg >= 100) ? va("%.0f%%", e_sg) : va("%.1f%%", e_sg)) : "-")); } static void onePlayerWeaponDmgStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.wpn[wpLG].edamage, p->ps.wpn[wpRL].edamage, p->ps.wpn[wpGL].edamage, p->ps.wpn[wpSNG].edamage, p->ps.wpn[wpNG].edamage, p->ps.wpn[wpSSG].edamage, p->ps.wpn[wpSG].edamage); } static void onePlayerWeaponTakenStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.wpn[wpLG].tooks, p->ps.wpn[wpRL].tooks, p->ps.wpn[wpGL].tooks, p->ps.wpn[wpSNG].tooks, p->ps.wpn[wpNG].tooks, p->ps.wpn[wpSSG].tooks); } static void onePlayerWeaponDroppedStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.wpn[wpLG].drops, p->ps.wpn[wpRL].drops, p->ps.wpn[wpGL].drops, p->ps.wpn[wpSNG].drops, p->ps.wpn[wpNG].drops, p->ps.wpn[wpSSG].drops); } static void onePlayerWeaponKillStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.wpn[wpLG].kills, p->ps.wpn[wpRL].kills, p->ps.wpn[wpGL].kills, p->ps.wpn[wpSNG].kills, p->ps.wpn[wpNG].kills, p->ps.wpn[wpSSG].kills); } static void onePlayerEnemyWeaponKillStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.wpn[wpLG].ekills, p->ps.wpn[wpRL].ekills, p->ps.wpn[wpGL].ekills, p->ps.wpn[wpSNG].ekills, p->ps.wpn[wpNG].ekills, p->ps.wpn[wpSSG].ekills); } static void onePlayerDamageStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|%5d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)p->ps.dmg_t, (int)p->ps.dmg_g, (int)p->ps.dmg_eweapon, (int)p->ps.dmg_team, (int)p->ps.dmg_self, (p->deaths <= 0 ? 99999 : (int)(p->ps.dmg_t / p->deaths))); } static void onePlayerItemTimeStats(gedict_t *p, int tp) { G_sprint(self, 2, "%-20s|%.2d:%.2d|%.2d:%.2d|%.2d:%.2d|%5s|%5s|%5s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)(p->ps.itm[itRA].time / 60), ((int)(p->ps.itm[itRA].time)) % 60, (int)(p->ps.itm[itYA].time / 60), ((int)(p->ps.itm[itYA].time)) % 60, (int)(p->ps.itm[itGA].time / 60), ((int)(p->ps.itm[itGA].time)) % 60, tp ? va("%.2d:%.2d", (int)(p->ps.itm[itQUAD].time / 60), ((int)(p->ps.itm[itQUAD].time)) % 60) : " -", tp ? va("%.2d:%.2d", (int)(p->ps.itm[itPENT].time / 60), ((int)(p->ps.itm[itPENT].time)) % 60) : " -", tp ? va("%.2d:%.2d", (int)(p->ps.itm[itRING].time / 60), ((int)(p->ps.itm[itRING].time)) % 60) : " -"); } static void onePlayerWeaponTimeStats(gedict_t *p) { G_sprint(self, 2, "%-20s|%.2d:%.2d|%.2d:%.2d|%.2d:%.2d|%.2d:%.2d|%.2d:%.2d|%.2d:%.2d|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), (int)(p->ps.wpn[wpLG].time / 60), ((int)(p->ps.wpn[wpLG].time)) % 60, (int)(p->ps.wpn[wpRL].time / 60), ((int)(p->ps.wpn[wpRL].time)) % 60, (int)(p->ps.wpn[wpGL].time / 60), ((int)(p->ps.wpn[wpGL].time)) % 60, (int)(p->ps.wpn[wpSNG].time / 60), ((int)(p->ps.wpn[wpSNG].time)) % 60, (int)(p->ps.wpn[wpNG].time / 60), ((int)(p->ps.wpn[wpNG].time)) % 60, (int)(p->ps.wpn[wpSSG].time / 60), ((int)(p->ps.wpn[wpSSG].time)) % 60); } static void onePlayerCTFStats(gedict_t *p) { int res = 0; int str = 0; int hst = 0; int rgn = 0; if ((g_globalvars.time - match_start_time) > 0) { res = (p->ps.res_time / (g_globalvars.time - match_start_time)) * 100; str = (p->ps.str_time / (g_globalvars.time - match_start_time)) * 100; hst = (p->ps.hst_time / (g_globalvars.time - match_start_time)) * 100; rgn = (p->ps.rgn_time / (g_globalvars.time - match_start_time)) * 100; } G_sprint(self, 2, "%-20s|%3d|%3d|%3d|%3d|%3d|%3s|%3s|%3s|%3s|\n", va("%s%s", isghost(p) ? "\203" : "", getname(p)), p->ps.pickups, p->ps.caps, p->ps.returns, p->ps.f_defends, p->ps.c_defends, ((cvar("k_ctf_runes") ? va("%d%%", res) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", str) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", hst) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", rgn) : " - "))); } static void calculateEfficiency(gedict_t *player) { if (isCTF()) { if ((player->s.v.frags - player->ps.ctf_points) < 1) { player->efficiency = 0; } else { player->efficiency = (player->s.v.frags - player->ps.ctf_points) / (player->s.v.frags - player->ps.ctf_points + player->deaths) * 100; } } else if (isRA()) { player->efficiency = ( (player->ps.loses + player->ps.wins) ? (player->ps.wins * 100.0f) / (player->ps.loses + player->ps.wins) : 0); } else { if (player->s.v.frags < 1) { player->efficiency = 0; } else { player->efficiency = player->s.v.frags / (player->s.v.frags + player->deaths) * 100; } } } static void playerMidairStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Midair statistics"), redtext("Tot"), redtext("Bro"), redtext("Sil"), redtext("Gol"), redtext("Pla"), redtext("Sto"), redtext("Bon"), redtext("Max H"), redtext("Avg H")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerMidairStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playerMidairKillStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\237\n", redtext("Kill statistics"), redtext(" Frag"), redtext("SpwnF"), redtext(" Strk"), redtext(" RL %")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerMidairKillStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void topMidairStats(void) { gedict_t *p; float f1; float vh_rl; float a_rl; float ph_rl; float maxtopheight = 0; float maxtopavgheight = 0; float maxrlefficiency = 0; int from; int maxscore = -99999; int maxkills = 0; int maxmidairs = 0; int maxstomps = 0; int maxstreak = 0; int maxspawnfrags = 0; int maxbonus = 0; from = f1 = 0; p = find_plrghst(world, &from); while (p) { maxscore = max(p->s.v.frags, maxscore); maxkills = max(p->ps.mid_total + p->ps.mid_stomps, maxkills); maxmidairs = max(p->ps.mid_total, maxmidairs); maxstomps = max(p->ps.mid_stomps, maxstomps); maxstreak = max(p->ps.spree_max, maxstreak); maxspawnfrags = max(p->ps.spawn_frags, maxspawnfrags); maxbonus = max(p->ps.mid_bonus, maxbonus); maxtopheight = max(p->ps.mid_maxheight, maxtopheight); maxtopavgheight = max(p->ps.mid_avgheight, maxtopavgheight); vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; ph_rl = 100.0 * vh_rl / max(1, a_rl); maxrlefficiency = max(ph_rl, maxrlefficiency); p = find_plrghst(p, &from); } G_sprint(self, 2, "\n%s:\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Top performers")); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->s.v.frags == maxscore) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("score")), (isghost(p) ? "\203" : ""), getname(p), maxscore); f1 = 1; } p = find_plrghst(p, &from); } if (maxkills) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_total + p->ps.mid_stomps) == maxkills) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("kills")), (isghost(p) ? "\203" : ""), getname(p), maxkills); f1 = 1; } p = find_plrghst(p, &from); } } if (maxmidairs) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_total) == maxmidairs) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("midairs")), (isghost(p) ? "\203" : ""), getname(p), maxmidairs); f1 = 1; } p = find_plrghst(p, &from); } } if (maxstomps) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_stomps) == maxstomps) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("head stomps")), (isghost(p) ? "\203" : ""), getname(p), maxstomps); f1 = 1; } p = find_plrghst(p, &from); } } if (maxstreak) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.spree_max) == maxstreak) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("streak")), (isghost(p) ? "\203" : ""), getname(p), maxstreak); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspawnfrags) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.spawn_frags) == maxspawnfrags) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("spawn frags")), (isghost(p) ? "\203" : ""), getname(p), maxspawnfrags); f1 = 1; } p = find_plrghst(p, &from); } } if (maxbonus) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_bonus) == maxbonus) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("bonus fiend")), (isghost(p) ? "\203" : ""), getname(p), maxbonus); f1 = 1; } p = find_plrghst(p, &from); } } if (maxtopheight) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_maxheight) == maxtopheight) { G_sprint(self, 2, " %-13s: %s%s (%.1f)\n", (f1 ? "" : redtext("highest kill")), (isghost(p) ? "\203" : ""), getname(p), maxtopheight); f1 = 1; } p = find_plrghst(p, &from); } } if (maxtopavgheight) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->ps.mid_avgheight) == maxtopavgheight) { G_sprint(self, 2, " %-13s: %s%s (%.1f)\n", (f1 ? "" : redtext("avg height")), (isghost(p) ? "\203" : ""), getname(p), maxtopavgheight); f1 = 1; } p = find_plrghst(p, &from); } } from = f1 = 0; p = find_plrghst(world, &from); while (p) { vh_rl = p->ps.wpn[wpRL].vhits; a_rl = p->ps.wpn[wpRL].attacks; ph_rl = 100.0 * vh_rl / max(1, a_rl); if ((ph_rl) == maxrlefficiency) { G_sprint(self, 2, " %-13s: %s%s (%.1f%%)\n", (f1 ? "" : redtext("rl efficiency")), (isghost(p) ? "\203" : ""), getname(p), maxrlefficiency); f1 = 1; } p = find_plrghst(p, &from); } G_sprint(self, 2, "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n\n"); } static void playerInstagibStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\237\n", redtext("Instagib statistics"), redtext("Coil"), redtext(" Axe"), redtext("Stmp"), redtext("Mult"), redtext("MMax"), redtext(" Air"), redtext("TotH"), redtext("MaxH"), redtext("Ring")); // Coilgun Axe Stomps Multigibs MaxMG Airgibs TotalH. MaxH. Ring from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerInstagibStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playerInstagibKillStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Kill statistics"), redtext("Point"), redtext(" Frag"), redtext("Death"), redtext("SpwnF"), redtext(" Strk"), redtext(" CG %")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerInstagibKillStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playerLGCStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\237\n", redtext("LGC statistics"), redtext("Score"), redtext(" Over"), redtext("Under"), redtext(" LG %")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerLGCStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersKillStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int tp; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } tp = isTeam() || isCTF(); G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Kill Statistics"), redtext(" Frag"), redtext(" Kill"), redtext("Death"), redtext("Suici"), redtext("TKill"), redtext("SpwnF"), redtext("Effic")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark calculateEfficiency(p2); onePlayerKillStats(p2, tp); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersItemStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int tp; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } tp = isTeam() || isCTF(); G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Item Taken"), redtext(" GA"), redtext(" YA"), redtext(" RA"), redtext(" MH"), redtext(" Quad"), redtext(" Pent"), redtext(" Ring")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerItemStats(p2, tp); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponEffiStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\237\n", redtext("Weapon Efficiency"), redtext(" LG%"), redtext(" RL%"), redtext(" GL%"), redtext(" SNG%"), redtext(" NG%"), redtext(" SSG%"), redtext(" SG%")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponEffiStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponDmgStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\237\n", redtext("Weapon Damage"), redtext(" LG"), redtext(" RL"), redtext(" GL"), redtext(" SNG"), redtext(" NG"), redtext(" SSG"), redtext(" SG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponDmgStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponTakenStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Weapon Taken"), redtext(" LG"), redtext(" RL"), redtext(" GL"), redtext(" SNG"), redtext(" NG"), redtext(" SSG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponTakenStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponDroppedStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Weapon Dropped"), redtext(" LG"), redtext(" RL"), redtext(" GL"), redtext(" SNG"), redtext(" NG"), redtext(" SSG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponDroppedStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponKillStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Weapon Kills"), redtext(" LG"), redtext(" RL"), redtext(" GL"), redtext(" SNG"), redtext(" NG"), redtext(" SSG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponKillStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersEnemyWeaponKillStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Enemy Weapon Killed"), redtext(" LG"), redtext(" RL"), redtext(" GL"), redtext(" SNG"), redtext(" NG"), redtext(" SSG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerEnemyWeaponKillStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersDamageStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Damage statistics"), redtext("Taken"), redtext("Given"), redtext("EWeap"), redtext(" Team"), redtext(" Self"), redtext("ToDie")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerDamageStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersItemTimeStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; int tp; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\237\n", redtext("Item times"), redtext(" RA"), redtext(" YA"), redtext(" GA"), redtext(" Quad"), redtext(" Pent"), redtext(" Ring")); tp = isTeam() || isCTF(); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerItemTimeStats(p2, tp); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersWeaponTimeStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Weapon times"), redtext(" LG"), redtext(" RL"), redtext(" GL"),redtext(" SNG"), redtext(" NG"), redtext(" SSG")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerWeaponTimeStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void playersCTFStats(void) { gedict_t *p; gedict_t *p2; char *tmp; char *tmp2; int from1; int from2; from1 = 0; p = find_plrghst(world, &from1); while (p) { p->ready = 0; // clear mark p = find_plrghst(p, &from1); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("CTF statistics"), redtext("Fla"), redtext("Cap"), redtext("Ret"), redtext("DFl"), redtext("DCa"), redtext("Res"), redtext("Str"), redtext("Hst"), redtext("Rgn")); from1 = 0; p = find_plrghst(world, &from1); while (p) { if (!p->ready) { from2 = 0; p2 = find_plrghst(world, &from2); while (p2) { if (!p2->ready) { // sort by team tmp = getteam(p); tmp2 = getteam(p2); if (streq(tmp, tmp2)) { p2->ready = 1; // set mark onePlayerCTFStats(p2); } } p2 = find_plrghst(p2, &from2); } } p = find_plrghst(p, &from1); } } static void collectTpStats(void) { gedict_t *p; gedict_t *p2; int from1; int from2; int i; int *frags; char *tmp = ""; for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { p->ready = 0; // clear mark } // get one player and search all his mates, mark served players via ->ready field // ghosts is served too for (from1 = 0, p = world; (p = find_plrghst(p, &from1));) { if (p->ready || strnull(tmp = getteam(p))) { continue; // served or wrong team } if ((tmStatsTables_cnt < 0) || (tmStatsTables_cnt >= MAX_TM_STATS)) { return; // all slots busy } if (tmStatsTables[tmStatsTables_cnt].name == NULL) { return; } for (from2 = 0, p2 = world; (p2 = find_plrghst(p2, &from2));) { if (p2->ready || strneq(tmp, getteam(p2))) { continue; // served or on different team } if (strnull(tmStatsTables[tmStatsTables_cnt].name)) // we not yet done that, do that once { strlcpy(tmStatsTables[tmStatsTables_cnt].name, tmp, MAX_TEAM_NAME); } frags = (p2->ct == ctPlayer ? &tmStatsTables[tmStatsTables_cnt].frags : &tmStatsTables[tmStatsTables_cnt].gfrags); frags[0] += p2->s.v.frags; tmStatsTables[tmStatsTables_cnt].deaths += p2->deaths; tmStatsTables[tmStatsTables_cnt].tkills += p2->friendly; tmStatsTables[tmStatsTables_cnt].dmg_t += p2->ps.dmg_t; tmStatsTables[tmStatsTables_cnt].dmg_g += p2->ps.dmg_g; tmStatsTables[tmStatsTables_cnt].dmg_team += p2->ps.dmg_team; tmStatsTables[tmStatsTables_cnt].dmg_eweapon += p2->ps.dmg_eweapon; for (i = itNONE; i < itMAX; i++) { // summ each field of items tmStatsTables[tmStatsTables_cnt].itm[i].tooks += p2->ps.itm[i].tooks; tmStatsTables[tmStatsTables_cnt].itm[i].time += p2->ps.itm[i].time; } for (i = wpNONE; i < wpMAX; i++) { // summ each field of weapons tmStatsTables[tmStatsTables_cnt].wpn[i].hits += p2->ps.wpn[i].hits; tmStatsTables[tmStatsTables_cnt].wpn[i].attacks += p2->ps.wpn[i].attacks; tmStatsTables[tmStatsTables_cnt].wpn[i].kills += p2->ps.wpn[i].kills; tmStatsTables[tmStatsTables_cnt].wpn[i].deaths += p2->ps.wpn[i].deaths; tmStatsTables[tmStatsTables_cnt].wpn[i].tkills += p2->ps.wpn[i].tkills; tmStatsTables[tmStatsTables_cnt].wpn[i].ekills += p2->ps.wpn[i].ekills; tmStatsTables[tmStatsTables_cnt].wpn[i].drops += p2->ps.wpn[i].drops; tmStatsTables[tmStatsTables_cnt].wpn[i].tooks += p2->ps.wpn[i].tooks; tmStatsTables[tmStatsTables_cnt].wpn[i].ttooks += p2->ps.wpn[i].ttooks; } tmStatsTables[tmStatsTables_cnt].transferred_RLpacks += p2->ps.transferred_RLpacks; tmStatsTables[tmStatsTables_cnt].transferred_LGpacks += p2->ps.transferred_LGpacks; // ctf related tmStatsTables[tmStatsTables_cnt].res += p2->ps.res_time; tmStatsTables[tmStatsTables_cnt].str += p2->ps.str_time; tmStatsTables[tmStatsTables_cnt].hst += p2->ps.hst_time; tmStatsTables[tmStatsTables_cnt].rgn += p2->ps.rgn_time; tmStatsTables[tmStatsTables_cnt].caps += p2->ps.caps; tmStatsTables[tmStatsTables_cnt].pickups += p2->ps.pickups; tmStatsTables[tmStatsTables_cnt].returns += p2->ps.returns; tmStatsTables[tmStatsTables_cnt].f_defends += p2->ps.f_defends; tmStatsTables[tmStatsTables_cnt].c_defends += p2->ps.c_defends; p2->ready = 1; // set mark } if (strnull(tmStatsTables[tmStatsTables_cnt].name)) { continue; // wtf, empty team? } if (isCTF() && g_globalvars.time - match_start_time > 0) { tmStatsTables[tmStatsTables_cnt].res = (tmStatsTables[tmStatsTables_cnt].res / (g_globalvars.time - match_start_time)) * 100; tmStatsTables[tmStatsTables_cnt].str = (tmStatsTables[tmStatsTables_cnt].str / (g_globalvars.time - match_start_time)) * 100; tmStatsTables[tmStatsTables_cnt].hst = (tmStatsTables[tmStatsTables_cnt].hst / (g_globalvars.time - match_start_time)) * 100; tmStatsTables[tmStatsTables_cnt].rgn = (tmStatsTables[tmStatsTables_cnt].rgn / (g_globalvars.time - match_start_time)) * 100; } tmStatsTables_cnt++; } } static void summaryTPStats(void) { int i; G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\237\n", redtext("Team Items Taken"), redtext("RA"), redtext("YA"), redtext("GA"), redtext("MH"), redtext(" Q"), redtext(" P"), redtext(" R")); for (i = 0; i < min(tmStatsTables_cnt, MAX_TM_STATS); i++) { G_sprint(self, 2, "%-20s|%2d|%2d|%2d|%2d|%2d|%2d|%2d|\n", va("\220%s\221", tmStatsTables[i].name), tmStatsTables[i].itm[itRA].tooks, tmStatsTables[i].itm[itYA].tooks, tmStatsTables[i].itm[itGA].tooks, tmStatsTables[i].itm[itHEALTH_100].tooks, tmStatsTables[i].itm[itQUAD].tooks, tmStatsTables[i].itm[itPENT].tooks, tmStatsTables[i].itm[itRING].tooks); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Team Weapons"), redtext("LGT"), redtext("LGK"), redtext("LGD"), redtext("LGX"), redtext("RLT"), redtext("RLK"), redtext("RLD"), redtext("RLX")); for (i = 0; i < min(tmStatsTables_cnt, MAX_TM_STATS); i++) { G_sprint(self, 2, "%-20s|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|\n", va("\220%s\221", tmStatsTables[i].name), tmStatsTables[i].wpn[wpLG].tooks, tmStatsTables[i].wpn[wpLG].ekills, tmStatsTables[i].wpn[wpLG].drops, tmStatsTables[i].transferred_LGpacks, tmStatsTables[i].wpn[wpRL].tooks, tmStatsTables[i].wpn[wpRL].ekills, tmStatsTables[i].wpn[wpRL].drops, tmStatsTables[i].transferred_RLpacks); } G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\237\n", redtext("Team Frags+Damage"), redtext("Frags"), redtext("Given"), redtext("Taken"), redtext(" EWep"), redtext(" Team")); for (i = 0; i < min(tmStatsTables_cnt, MAX_TM_STATS); i++) { G_sprint(self, 2, "%-20s|%5d|%5d|%5d|%5d|%5d|\n", va("\220%s\221", tmStatsTables[i].name), tmStatsTables[i].frags, (int)tmStatsTables[i].dmg_g, (int)tmStatsTables[i].dmg_t, (int)tmStatsTables[i].dmg_eweapon, (int)tmStatsTables[i].dmg_team); } if (isCTF()) { G_sprint(self, 2, "\n%s |%s|%s|%s|%s|%s|%s|%s|%s|%s|\n" "\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Team CTF statistics"), redtext("Fla"), redtext("Cap"), redtext("Ret"), redtext("DFl"), redtext("DCa"), redtext("Res"), redtext("Str"), redtext("Hst"), redtext("Rgn")); for (i = 0; i < min(tmStatsTables_cnt, MAX_TM_STATS); i++) { G_sprint(self, 2, "%-20s|%3d|%3d|%3d|%3d|%3d|%3s|%3s|%3s|%3s|\n", va("\220%s\221", tmStatsTables[i].name), tmStatsTables[i].pickups, tmStatsTables[i].caps, tmStatsTables[i].returns, tmStatsTables[i].f_defends, tmStatsTables[i].c_defends, ((cvar("k_ctf_runes") ? va("%d%%", (int)tmStatsTables[i].res) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", (int)tmStatsTables[i].str) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", (int)tmStatsTables[i].hst) : " - ")), ((cvar("k_ctf_runes") ? va("%d%%", (int)tmStatsTables[i].rgn) : " - "))); } } } static void topStats(void) { gedict_t *p; float f1; int from; float maxfrags = -99999; float maxdeaths = -1; float maxfriend = -1; float maxeffi = -1; float maxspree = -1; float maxspree_q = -1; float maxdmgg = -1; float maxdmgtd = -1; int maxspawnfrags = 0; int maxcaps = 0; int maxdefends = 0; from = f1 = 0; p = find_plrghst(world, &from); while (p) { maxfrags = max((isCTF() ? p->s.v.frags - p->ps.ctf_points : p->s.v.frags), maxfrags); maxdeaths = max(p->deaths, maxdeaths); maxfriend = max(p->friendly, maxfriend); maxeffi = max(p->efficiency, maxeffi); maxspree = max(p->ps.spree_max, maxspree); maxspree_q = max(p->ps.spree_max_q, maxspree_q); maxdmgg = max(p->ps.dmg_g, maxdmgg); maxdmgtd = max((int)(p->ps.dmg_t / p->deaths), maxdmgtd); maxspawnfrags = max(p->ps.spawn_frags, maxspawnfrags); maxcaps = max(p->ps.caps, maxcaps); maxdefends = max(p->ps.f_defends, maxdefends); p = find_plrghst(p, &from); } G_sprint(self, 2, "\n%s:\n\235\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236" "\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\236\237\n", redtext("Top performers")); from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((!isCTF() && (p->s.v.frags == maxfrags)) || (isCTF() && ((p->s.v.frags - p->ps.ctf_points) == maxfrags))) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Frags")), (isghost(p) ? "\203" : ""), getname(p), (int)maxfrags); f1 = 1; } p = find_plrghst(p, &from); } if (maxdeaths != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->deaths == maxdeaths) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Deaths")), (isghost(p) ? "\203" : ""), getname(p), (int)maxdeaths); f1 = 1; } p = find_plrghst(p, &from); } } if (maxfriend > 0) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->friendly == maxfriend) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Friendkills")), (isghost(p) ? "\203" : ""), getname(p), (int)maxfriend); f1 = 1; } p = find_plrghst(p, &from); } } if (maxeffi != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->efficiency == maxeffi) { G_sprint(self, 2, " %-13s: %s%s (%d%%)\n", (f1 ? "" : redtext("Efficiency")), (isghost(p) ? "\203" : ""), getname(p), (int)maxeffi); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspree != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.spree_max == maxspree) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Fragstreak")), (isghost(p) ? "\203" : ""), getname(p), (int)maxspree); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspree_q > 0) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.spree_max_q == maxspree_q) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Quadrun")), (isghost(p) ? "\203" : ""), getname(p), (int)maxspree_q); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdmgg != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.dmg_g == maxdmgg) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Annihilator")), (isghost(p) ? "\203" : ""), getname(p), (int)maxdmgg); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdmgtd != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if ((p->deaths <= 0 ? 99999 : p->ps.dmg_t / p->deaths) == maxdmgtd) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Survivor")), (isghost(p) ? "\203" : ""), getname(p), (int)maxdmgtd); f1 = 1; } p = find_plrghst(p, &from); } } if (maxspawnfrags > 0) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.spawn_frags == maxspawnfrags) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Spawnfrags")), (isghost(p) ? "\203" : ""), getname(p), maxspawnfrags); f1 = 1; } p = find_plrghst(p, &from); } } if (isCTF()) { if (maxcaps != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.caps == maxcaps) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("Captures")), (isghost(p) ? "\203" : ""), getname(p), maxcaps); f1 = 1; } p = find_plrghst(p, &from); } } if (maxdefends != -1) { from = f1 = 0; p = find_plrghst(world, &from); while (p) { if (p->ps.f_defends == maxdefends) { G_sprint(self, 2, " %-13s: %s%s (%d)\n", (f1 ? "" : redtext("FlagDefends")), (isghost(p) ? "\203" : ""), getname(p), maxdefends); f1 = 1; } p = find_plrghst(p, &from); } } } } QW-Group-ktx-d05d6ca/src/stats_json.c000066400000000000000000000447721475442401000175700ustar00rootroot00000000000000#include "g_local.h" #include "stats.h" // TODO // - Hoonymode stats: would be interesting to see spawn A vs B result... could always get from demo tho // - //#define USER_FRIENDLY_JSON #ifdef USER_FRIENDLY_JSON #define INDENT2 " " #define INDENT4 " " #define INDENT6 " " #define INDENT8 " " #define INDENT10 " " #define INDENT12 " " #define JSON_CR "\n" #else #define INDENT2 #define INDENT4 #define INDENT6 #define INDENT8 #define INDENT10 #define INDENT12 #define JSON_CR "" #endif static void json_player_ctf_stats(fileHandle_t handle, player_stats_t *stats); static void json_player_instagib_stats(fileHandle_t handle, player_stats_t *stats); static void json_player_midair_stats(fileHandle_t handle, player_stats_t *stats); static void json_player_ra_stats(fileHandle_t handle, player_stats_t *stats); static void json_player_hoonymode_stats(fileHandle_t handle, gedict_t *player); static void json_player_lgc_stats(fileHandle_t handle, gedict_t *player); #define STATS_VERSION_NUMBER 3 #define SIMPLE_CHECK(handle, any, string) {\ if (any) { \ S2di(handle, "%s", string); \ } \ any = true; \ } #define NEWLINE_CHECK(handle, any) SIMPLE_CHECK(handle, any, JSON_CR) #define COMMA_CHECK(handle, any) SIMPLE_CHECK(handle, any, "," JSON_CR) static char* json_string(const char *input) { // >>>> like va(...) ... eugh static char string[MAX_STRINGS][1024]; static int index = 0; char *ch, *start; index %= MAX_STRINGS; // <<<< start = ch = string[index++]; while (*input) { unsigned char current = *input; if ((ch - start) >= 1000) { break; } if ((current == '\\') || (current == '"')) { *ch++ = '\\'; *ch++ = current; } else if (current == '\n') { *ch++ = '\\'; *ch++ = 'n'; } else if (current == '\r') { *ch++ = '\\'; *ch++ = 'r'; } else if (current == '\b') { *ch++ = '\\'; *ch++ = 'b'; } else if (current == '\t') { *ch++ = '\\'; *ch++ = 't'; } else if (current == '\f') { *ch++ = '\\'; *ch++ = 'f'; } else if ((current < ' ') || (current >= 128)) { *ch++ = '\\'; *ch++ = 'u'; *ch++ = '0'; *ch++ = '0'; if (current < 16) { *ch++ = '0'; *ch++ = "0123456789ABCDEF"[(int)current]; } else { *ch++ = "0123456789ABCDEF"[((int)(current)) >> 4]; *ch++ = "0123456789ABCDEF"[((int)(current)) & 15]; } } else { *ch++ = current; } ++input; } *ch = '\0'; return start; } static void json_weap_header(fileHandle_t handle) { S2di(handle, INDENT6 "\"weapons\": {" JSON_CR); } static void json_weap_detail(fileHandle_t handle, const char *name, int weapon_num, wpType_t *stats) { qbool any = false; if (weapon_num) { S2di(handle, "," JSON_CR); } S2di(handle, INDENT8 "\"%s\": {" JSON_CR, json_string(name)); if (stats->attacks || stats->hits || stats->rhits || stats->vhits) { S2di(handle, INDENT10 "\"acc\": { \"attacks\": %d, \"hits\": %d", stats->attacks, stats->hits); if (stats->rhits || stats->vhits) { S2di(handle, ", \"real\": %d, \"virtual\": %d", stats->rhits, stats->vhits); } S2di(handle, " }"); any = true; } if (stats->kills || stats->tkills || stats->ekills || stats->suicides) { COMMA_CHECK(handle, any); S2di(handle, INDENT10 "\"kills\": { \"total\": %d, \"team\": %d, \"enemy\": %d, \"self\": %d }", stats->kills, stats->tkills, stats->ekills, stats->suicides); } if (deathmatch < 4) { COMMA_CHECK(handle, any); S2di(handle, INDENT10 "\"deaths\": %d", stats->deaths); } if ((deathmatch < 4) && (stats->drops || stats->tooks || stats->ttooks || stats->stooks || stats->sttooks)) { qbool inner_any = false; COMMA_CHECK(handle, any); S2di(handle, INDENT10 "\"pickups\": {" JSON_CR); if (stats->drops) { COMMA_CHECK(handle, inner_any); S2di(handle, INDENT12 "\"dropped\": %d", stats->drops); } if (stats->tooks) { COMMA_CHECK(handle, inner_any); S2di(handle, INDENT12 "\"taken\": %d", stats->tooks); } if (stats->ttooks) { COMMA_CHECK(handle, inner_any); S2di(handle, INDENT12 "\"total-taken\": %d", stats->ttooks); } if (stats->stooks) { COMMA_CHECK(handle, inner_any); S2di(handle, INDENT12 "\"spawn-taken\": %d", stats->stooks); } if (stats->sttooks) { COMMA_CHECK(handle, inner_any); S2di(handle, INDENT12 "\"spawn-total-taken\": %d", stats->sttooks); } NEWLINE_CHECK(handle, inner_any); S2di(handle, INDENT10 "}"); } if (stats->edamage || stats->tdamage) { COMMA_CHECK(handle, any); S2di(handle, INDENT10 "\"damage\": { \"enemy\": %d, \"team\": %d }", stats->edamage, stats->tdamage); } NEWLINE_CHECK(handle, any); S2di(handle, INDENT8 "}"); } static void json_weap_footer(fileHandle_t handle, int num) { if (num) { S2di(handle, "%s", JSON_CR); } S2di(handle, INDENT6 "}," JSON_CR); } void json_teams_header(fileHandle_t handle) { char tmp[1024] = { 0 }; int i = 0; for (tmp[0] = i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { if (i) { strlcat(tmp, ", ", sizeof(tmp)); } strlcat(tmp, "\"", sizeof(tmp)); strlcat(tmp, json_string(tmStats[i].name), sizeof(tmp)); strlcat(tmp, "\"", sizeof(tmp)); } if (i) { S2di(handle, INDENT2 "\"teams\": [%s]," JSON_CR, tmp); } } void json_teams_footer(fileHandle_t handle, int teams) { } void json_team_detail(fileHandle_t handle, int num, teamStats_t *stats) { } void json_team_footer(fileHandle_t handle) { } static void json_items_header(fileHandle_t handle) { S2di(handle, INDENT6 "\"items\": {" JSON_CR); } static void json_item_detail(fileHandle_t handle, const char *name, int item_num, itType_t *stats) { qbool any = false; if (item_num) { S2di(handle, "," JSON_CR); } S2di(handle, INDENT8 "\"%s\": { ", json_string(name)); if (stats->tooks) { COMMA_CHECK(handle, any); S2di(handle, "\"took\": %d", stats->tooks); } if ((int)stats->time) { COMMA_CHECK(handle, any); S2di(handle, "\"time\": %d", (int)stats->time); } S2di(handle, " }"); } static void json_items_footer(fileHandle_t handle, int item_num) { if (item_num) { S2di(handle, "%s", JSON_CR); } S2di(handle, INDENT6 "}"); } void json_players_header(fileHandle_t handle) { S2di(handle, INDENT2 "\"players\": [" JSON_CR); } void json_players_footer(fileHandle_t handle, int player_count) { if (player_count) { S2di(handle, "%s", JSON_CR); } S2di(handle, INDENT2 "]" JSON_CR); } #ifdef BOT_SUPPORT void json_player_bot_info(fileHandle_t handle, fb_botskill_t* skill) { S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"bot\": {" JSON_CR); S2di(handle, INDENT8 "\"skill\": %d," JSON_CR, skill->skill_level); S2di(handle, INDENT8 "\"customised\": %s" JSON_CR, skill->customised ? "true" : "false"); S2di(handle, INDENT6 "}"); } #endif void json_player_detail(fileHandle_t handle, int player_num, gedict_t *player, const char *team) { int j; player_stats_t *stats = &player->ps; int count = 0; if (player_num) { S2di(handle, "," JSON_CR); } S2di(handle, INDENT4 "{" JSON_CR); S2di(handle, INDENT6 "\"top-color\": %d," JSON_CR, iKey(player, "topcolor")); S2di(handle, INDENT6 "\"bottom-color\": %d," JSON_CR, iKey(player, "bottomcolor")); S2di(handle, INDENT6 "\"ping\": %d," JSON_CR, iKey(player, "ping")); S2di(handle, INDENT6 "\"login\": \"%s\"," JSON_CR, ezinfokey(player, "login")); S2di(handle, INDENT6 "\"name\": \"%s\"," JSON_CR, json_string(getname(player))); S2di(handle, INDENT6 "\"team\": \"%s\"," JSON_CR, json_string(team)); S2di(handle, INDENT6 "\"stats\": { \"frags\": %d, \"deaths\": %d, \"tk\": %d, \"spawn-frags\": %d, \"kills\": %d, \"suicides\": %d }," JSON_CR, (int)player->s.v.frags, (int)player->deaths, (int)player->friendly, player->ps.spawn_frags, (int)player->kills, (int)player->suicides); S2di(handle, INDENT6 "\"dmg\": { \"taken\": %d, \"given\": %d, \"team\": %d, \"self\": %d, \"team-weapons\": %d, \"enemy-weapons\": %d, \"taken-to-die\": %d }," JSON_CR, (int)player->ps.dmg_t, (int)player->ps.dmg_g, (int)player->ps.dmg_team, (int)player->ps.dmg_self, (int)player->ps.dmg_tweapon, (int)player->ps.dmg_eweapon, (int)player->deaths == 0 ? 99999 : (int)player->ps.dmg_t / (int)player->deaths); S2di(handle, INDENT6 "\"xferRL\": %d," JSON_CR, player->ps.transferred_RLpacks); S2di(handle, INDENT6 "\"xferLG\": %d," JSON_CR, player->ps.transferred_LGpacks); S2di(handle, INDENT6 "\"spree\": { \"max\": %d, \"quad\": %d }," JSON_CR, player->ps.spree_max, player->ps.spree_max_q); S2di(handle, INDENT6 "\"control\": %f," JSON_CR, player->ps.control_time); S2di(handle, INDENT6 "\"speed\": { \"max\": %f, \"avg\": %f }," JSON_CR, player->ps.velocity_max, player->ps.vel_frames > 0 ? player->ps.velocity_sum / player->ps.vel_frames : 0.); if (GetHandicap(player) != 100) { S2di(handle, INDENT6 "\"handicap\": %d," JSON_CR, GetHandicap(player)); } json_weap_header(handle); for (j = 1; j < wpMAX; j++) { wpType_t *weap = &stats->wpn[j]; int old_ekills = weap->ekills; if ((deathmatch >= 4) || (j == wpAXE) || (j == wpSG) || cvar("k_instagib")) { weap->ekills = 0; } if (!((weap->attacks == 0) && (weap->deaths == 0) && (weap->drops == 0) && (weap->sttooks == 0) && (weap->ttooks == 0))) { json_weap_detail(handle, WpName(j), count, weap); ++count; } weap->ekills = old_ekills; } json_weap_footer(handle, count); count = 0; json_items_header(handle); for (j = 1; j < itMAX; j++) { itType_t *item = &stats->itm[j]; if ((item->tooks != 0) || ((deathmatch <= 3) && (item->time != 0))) { json_item_detail(handle, ItName(j), count, item); ++count; } } json_items_footer(handle, count); if (isCTF()) { json_player_ctf_stats(handle, stats); } if (cvar("k_instagib")) { json_player_instagib_stats(handle, stats); } if (cvar("k_midair")) { json_player_midair_stats(handle, stats); } if (isRA()) { json_player_ra_stats(handle, stats); } if (isHoonyModeAny()) { json_player_hoonymode_stats(handle, player); } if (lgc_enabled()) { json_player_lgc_stats(handle, player); } #ifdef BOT_SUPPORT if (player->isBot) { json_player_bot_info(handle, &player->fb.skill); } #endif S2di(handle, "%s", JSON_CR); S2di(handle, INDENT4 "}"); } void json_match_header(fileHandle_t handle, char *ip, int port) { char date[64] = { 0 }; char matchtag[64] = { 0 }; const char *mode = GetMode(); int duration = (g_globalvars.time - match_start_time); infokey(world, "matchtag", matchtag, sizeof(matchtag)); if (!QVMstrftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %z", 0)) { date[0] = 0; // bad date } S2di(handle, "{" JSON_CR); S2di(handle, INDENT2 "\"version\": %d," JSON_CR, STATS_VERSION_NUMBER); S2di(handle, INDENT2 "\"date\": \"%s\"," JSON_CR, date); S2di(handle, INDENT2 "\"map\": \"%s\"," JSON_CR, json_string(mapname)); S2di(handle, INDENT2 "\"hostname\": \"%s\"," JSON_CR, json_string(striphigh(cvar_string("hostname")))); S2di(handle, INDENT2 "\"ip\": \"%s\"," JSON_CR, json_string(ip)); S2di(handle, INDENT2 "\"port\": %d," JSON_CR, port); if (!strnull(matchtag)) { S2di(handle, INDENT2 "\"matchtag\": \"%s\"," JSON_CR, json_string(matchtag)); } if (!strnull(mode)) { S2di(handle, INDENT2 "\"mode\": \"%s\"," JSON_CR, json_string(mode)); } if (timelimit) { S2di(handle, INDENT2 "\"tl\": %d," JSON_CR, timelimit); } if (fraglimit) { S2di(handle, INDENT2 "\"fl\": %d," JSON_CR, timelimit); } if (deathmatch) { S2di(handle, INDENT2 "\"dm\": %d," JSON_CR, deathmatch); } if (teamplay) { S2di(handle, INDENT2 "\"tp\": %d," JSON_CR, teamplay); } S2di(handle, INDENT2 "\"duration\": %d," JSON_CR, duration); if (!strnull(cvar_string("serverdemo"))) { const char *server_demo = cvar_string("serverdemo"); S2di(handle, INDENT2 "\"demo\": \"%s\"," JSON_CR, json_string(server_demo)); } } void json_match_footer(fileHandle_t handle) { S2di(handle, "}" JSON_CR); } static void json_player_ctf_stats(fileHandle_t handle, player_stats_t *stats) { qbool any = false; S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"ctf\": {" JSON_CR); if (stats->ctf_points) { S2di(handle, INDENT8 "\"points\": %d", stats->ctf_points); any = true; } if (stats->caps) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"caps\": %d", stats->caps); } if (stats->f_defends) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"defends\": %d", stats->f_defends); } if (stats->c_defends) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"carrier-defends\": %d", stats->c_defends); } if (stats->c_frags) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"carrier-frags\": %d", stats->c_frags); } if (stats->pickups) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"pickups\": %d", stats->pickups); } if (stats->returns) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"returns\": %d", stats->returns); } COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"runes\": [%d, %d, %d, %d]" JSON_CR, (int)(stats->res_time + 0.5f), (int)(stats->str_time + 0.5f), (int)(stats->hst_time + 0.5f), (int)(stats->rgn_time + 0.5f)); S2di(handle, INDENT6 "}"); } static void json_player_instagib_stats(fileHandle_t handle, player_stats_t *stats) { qbool any = false; S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"instagib\": {" JSON_CR); if (stats->i_height || stats->i_maxheight) { S2di(handle, INDENT8 "\"height\": [%d, %d]", stats->i_height, stats->i_maxheight); COMMA_CHECK(handle, any); } if (stats->i_rings) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"rings\": %d", stats->i_rings); } COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"gibs\": { \"coil\": %d, \"axe\": %d, \"stomp\": %d, \"multi\": %d, \"air\": %d, \"best-multi\": %d }" JSON_CR, stats->i_cggibs, stats->i_axegibs, stats->i_stompgibs, stats->i_multigibs, stats->i_airgibs, stats->i_maxmultigibs); S2di(handle, INDENT6 "}"); } static void json_player_midair_stats(fileHandle_t handle, player_stats_t *stats) { qbool any = false; S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"midair\": {" JSON_CR); if (stats->mid_stomps) { S2di(handle, INDENT8 "\"stomps\": %d", stats->mid_stomps); any = true; } if (stats->mid_bronze || stats->mid_silver || stats->mid_gold || stats->mid_platinum) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"midairs\": { \"bronze\": %d, \"silver\": %d, \"gold\": %d, \"platinum\": %d }", stats->mid_bronze, stats->mid_silver, stats->mid_gold, stats->mid_platinum); } if (stats->mid_total) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"total\": %d", stats->mid_total); } if (stats->mid_bonus) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"bonus\": %d", stats->mid_bonus); } if (stats->mid_totalheight || stats->mid_maxheight || stats->mid_avgheight) { COMMA_CHECK(handle, any); S2di(handle, INDENT8 "\"heights\": { \"total\": %f, \"max\": %f, \"avg\": %f }", stats->mid_totalheight, stats->mid_maxheight, stats->mid_avgheight); } NEWLINE_CHECK(handle, any); S2di(handle, INDENT6 "}"); } static void json_player_ra_stats(fileHandle_t handle, player_stats_t *stats) { S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"ra\": { \"wins\": %d, \"losses\": %d }", stats->wins, stats->loses); } static void json_player_lgc_stats(fileHandle_t handle, gedict_t *player) { int i; S2di(handle, "," JSON_CR); S2di(handle, INDENT6 "\"lgc\": {" JSON_CR); S2di(handle, INDENT8 "\"under\": %d," JSON_CR, player->ps.lgc_undershaft); S2di(handle, INDENT8 "\"over\": %d," JSON_CR, player->ps.lgc_overshaft); S2di(handle, INDENT8 "\"hits\": ["); for (i = 0; i < LGCMODE_DISTANCE_BUCKETS; ++i) { S2di(handle, "%s%d", i ? ", " : "", player->lgc_distance_hits[i]); } S2di(handle, "]," JSON_CR); S2di(handle, INDENT8 "\"misses\": ["); for (i = 0; i < LGCMODE_DISTANCE_BUCKETS; ++i) { S2di(handle, "%s%d", i ? ", " : "", player->lgc_distance_misses[i]); } S2di(handle, "]" JSON_CR); S2di(handle, "}" JSON_CR); } static void json_player_hoonymode_stats(fileHandle_t handle, gedict_t *player) { S2di(handle, "," JSON_CR); if (isHoonyModeDuel()) { S2di(handle, INDENT6 "\"hm-rounds\": \"%s\"" JSON_CR, json_string(HM_round_results(player))); } else { int i; S2di(handle, INDENT6 "\"hm-frags\": ["); for (i = 0; i < HM_current_point(); ++i) { S2di(handle, "%s%d", i ? ", " : "", player->hoony_results[i]); } S2di(handle, "]" JSON_CR); } } void json_race_detail(fileHandle_t handle) { extern gedict_t* race_find_racer(gedict_t *p); qbool any = false; race_stats_score_t *stats; S2di(handle, INDENT2 "\"race\": {" JSON_CR); S2di(handle, INDENT4 "\"route\": %d," JSON_CR, race.active_route - 1); S2di(handle, INDENT4 "\"weapon-mode\": \"%s\"," JSON_CR, race.weapon == raceWeaponAllowed ? "allowed" : race.weapon == raceWeapon2s ? "delayed" : "none"); S2di(handle, INDENT4 "\"can-false-start\": %s," JSON_CR, race.falsestart == raceFalseStartYes ? "true" : "false"); S2di(handle, INDENT4 "\"match\": %s," JSON_CR, race_match_mode() ? "true" : "false"); if (!strnull(race.pacemaker_nick)) { S2di(handle, INDENT4 "\"pacemaker\": { \"time\": %.3f, \"name\": \"%s\" }," JSON_CR, race.pacemaker_time * 0.001f, json_string(race.pacemaker_nick)); } if (race_match_mode()) { int player_count; int i; S2di(handle, INDENT4 "\"scoring\": \"%s\"," JSON_CR, race_scoring_system_name()); stats = race_get_player_stats(&player_count); S2di(handle, INDENT4 "\"racers\": [" JSON_CR); for (i = 0; i < player_count; ++i) { COMMA_CHECK(handle, any); S2di(handle, INDENT6 "{ \"bestTime\": %.3f, \"completions\": %d, \"score\": %d, " "\"racer\": \"%s\", \"distance\": %f, \"time\": %.3f, \"wins\": %d }", stats[i].best_time / 1000.0f, stats[i].completions, stats[i].score, json_string(stats[i].name), stats[i].total_distance, stats[i].total_time / 1000.0f, stats[i].wins); } NEWLINE_CHECK(handle, any); S2di(handle, INDENT4 "]" JSON_CR); } else { gedict_t *p; S2di(handle, INDENT4 "\"racers\": [" JSON_CR); for (p = world; (p = race_find_race_participants(p)); /**/) { int player_number = NUM_FOR_EDICT(p) - 1; raceRecord_t *record = NULL; if ((player_number < 0) || (player_number >= (sizeof(race.currentrace) / sizeof(race.currentrace[0])))) { continue; } record = &race.currentrace[player_number]; if (!record->time) { continue; } COMMA_CHECK(handle, any); S2di(handle, INDENT6 "{ \"avgspeed\": %f, \"distance\": %f, \"time\": %f, " "\"racer\": \"%s\", \"maxspeed\": %f }", record->avgspeed / record->avgcount, record->distance, record->time / 1000.0f, json_string(p->netname), record->maxspeed); } NEWLINE_CHECK(handle, any); S2di(handle, INDENT4 "]" JSON_CR); } S2di(handle, INDENT2 "}" JSON_CR); } QW-Group-ktx-d05d6ca/src/stats_xml.c000066400000000000000000000247541475442401000174150ustar00rootroot00000000000000// stats_xml.c #include "g_local.h" #include "stats.h" #ifdef USER_FRIENDLY_XML #define INDENT2 " " #define INDENT4 " " #define INDENT6 " " #define INDENT8 " " #define INDENT10 " " #define INDENT12 " " #define JSON_CR "\n" #else #define INDENT2 #define INDENT4 #define INDENT6 #define INDENT8 #define INDENT10 #define INDENT12 #define JSON_CR "" #endif char* xml_string(const char *original); static void xml_weap_header(fileHandle_t handle) { S2di(handle, INDENT6 "\n"); } static void xml_weap_footer(fileHandle_t handle) { S2di(handle, INDENT6 "\n"); } static void xml_weap_stats(fileHandle_t handle, int weapon, wpType_t *stats) { S2di(handle, INDENT8 "\n", xml_string(WpName(weapon)), stats->hits, stats->attacks, stats->rhits, stats->vhits, stats->kills, stats->tkills, stats->ekills, stats->suicides, stats->deaths, stats->drops, stats->tooks, stats->ttooks, stats->stooks, stats->sttooks); } void xml_teams_header(fileHandle_t handle) { char tmp[1024] = { 0 }, buf[1024] = { 0 }; int i = 0; for (tmp[0] = i = 0; i < min(tmStats_cnt, MAX_TM_STATS); i++) { snprintf(buf, sizeof(buf), " team%d=\"%s\"", i + 1, xml_string(tmStats[i].name)); strlcat(tmp, buf, sizeof(tmp)); } if (i) { S2di(handle, INDENT2 "\n", tmp); } } void xml_teams_footer(fileHandle_t handle, int num) { if (num) { S2di(handle, INDENT2 "\n"); } } static void xml_team_header(fileHandle_t handle, int num, teamStats_t *stats) { S2di(handle, INDENT4 "\n", xml_string(stats->name), stats->frags + stats->gfrags, stats->deaths, stats->tkills, (int)stats->dmg_t, (int)stats->dmg_g, (int)stats->dmg_team); } static void xml_team_footer(fileHandle_t handle) { S2di(handle, "\t\t\n"); } static void xml_items_header(fileHandle_t handle) { S2di(handle, INDENT6 "\n"); } static void xml_item_stats(fileHandle_t handle, int j, itType_t *stats) { char buf[1024] = { 0 }; if ((j == itQUAD) || (j == itPENT) || (j == itRING)) { snprintf(buf, sizeof(buf), " time=\"%d\"", (int)stats->time); } else { buf[0] = 0; } S2di(handle, INDENT8 "\n", ItName(j), stats->tooks, buf); } static void xml_items_footer(fileHandle_t handle) { S2di(handle, INDENT6 "\n"); } void xml_players_header(fileHandle_t handle) { S2di(handle, INDENT2 "\n"); } void xml_players_footer(fileHandle_t handle, int player_count) { S2di(handle, INDENT2 "\n"); } static void xml_player_header(fileHandle_t handle, gedict_t *player, const char *team) { S2di(handle, INDENT4 "\n", xml_string(getname(player)), xml_string(team), (int)player->s.v.frags, (int)player->deaths, (int)player->friendly, (int)player->ps.dmg_t, (int)player->ps.dmg_g, (int)player->ps.dmg_team, player->ps.spawn_frags, player->ps.transferred_RLpacks, player->ps.transferred_LGpacks, player->ps.spree_max, player->ps.spree_max_q, player->ps.control_time, xml_string(ezinfokey(player, "login"))); } static void xml_player_footer(fileHandle_t handle) { S2di(handle, INDENT4 "\n"); } char* xml_string(const char *original) { static char string[MAX_STRINGS][1024]; static int index = 0; int length = strlen(original); int newlength = 0; int i = 0; index %= MAX_STRINGS; memset(string[index], 0, sizeof(string[0])); for (i = 0; i < length; ++i) { unsigned char ch = (unsigned char) original[i]; if (ch == '<') { if (newlength < sizeof(string[0]) - 4) { string[index][newlength++] = '&'; string[index][newlength++] = 'l'; string[index][newlength++] = 't'; string[index][newlength++] = ';'; } } else if (ch == '>') { if (newlength < sizeof(string[0]) - 4) { string[index][newlength++] = '&'; string[index][newlength++] = 'g'; string[index][newlength++] = 't'; string[index][newlength++] = ';'; } } else if (ch == '"') { if (newlength < sizeof(string[0]) - 5) { string[index][newlength++] = '&'; string[index][newlength++] = '#'; string[index][newlength++] = '3'; string[index][newlength++] = '4'; string[index][newlength++] = ';'; } } else if (ch == '&') { if (newlength < sizeof(string[0]) - 5) { string[index][newlength++] = '&'; string[index][newlength++] = 'a'; string[index][newlength++] = 'm'; string[index][newlength++] = 'p'; string[index][newlength++] = ';'; } } else if (ch == '\'') { if (newlength < sizeof(string[0]) - 5) { string[index][newlength++] = '&'; string[index][newlength++] = '#'; string[index][newlength++] = '3'; string[index][newlength++] = '9'; string[index][newlength++] = ';'; } } else { string[index][newlength++] = ch; } } return string[index++]; } void xml_match_header(fileHandle_t handle, char *ip, int port) { char date[64] = { 0 }; char matchtag[64] = { 0 }; const char *mode = cvar("k_instagib") ? "instagib" : (isRACE() ? "race" : GetMode()); infokey(world, "matchtag", matchtag, sizeof(matchtag)); if (!QVMstrftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %Z", 0)) date[0] = 0; // bad date S2di(handle, "%s", "\n"); S2di(handle, "\n", date, mapname, xml_string(cvar_string("hostname")), ip, port, mode, timelimit, fraglimit, deathmatch, teamplay); if (!strnull(cvar_string("serverdemo"))) { S2di(handle, INDENT2 "%s\n", xml_string(cvar_string("serverdemo"))); } } void xml_match_footer(fileHandle_t handle) { S2di(handle, "\n"); } static void xml_player_ctf_stats(fileHandle_t handle, player_stats_t *stats) { S2di(handle, INDENT6 "\n", stats->ctf_points, stats->caps, stats->f_defends, stats->c_defends, stats->c_frags, stats->pickups, stats->returns, stats->res_time, stats->str_time, stats->hst_time, stats->rgn_time); } static void xml_player_instagib_stats(fileHandle_t handle, player_stats_t *stats) { S2di(handle, INDENT6 "\n", stats->i_height, stats->i_maxheight, stats->i_cggibs, stats->i_axegibs, stats->i_stompgibs, stats->i_multigibs, stats->i_airgibs, stats->i_maxmultigibs, stats->i_rings); } static void xml_player_midair_stats(fileHandle_t handle, player_stats_t *stats) { S2di(handle, INDENT6 "\n", stats->mid_stomps, stats->mid_bronze, stats->mid_silver, stats->mid_gold, stats->mid_platinum, stats->mid_total, stats->mid_bonus, stats->mid_totalheight, stats->mid_maxheight, stats->mid_avgheight); } static void xml_player_ra_stats(fileHandle_t handle, player_stats_t *stats) { S2di(handle, INDENT6 "\n", stats->wins, stats->loses); } void xml_race_detail(fileHandle_t handle) { extern gedict_t* race_find_racer(gedict_t *p); gedict_t *p; S2di(handle, INDENT2 "", race.active_route - 1, race.weapon, race.falsestart); if (!strnull(race.pacemaker_nick)) { S2di(handle, INDENT4 "%s\n", race.pacemaker_time * 1.0f, xml_string(race.pacemaker_nick)); } for (p = world; (p = race_find_racer(p)); /**/) { int player_number = NUM_FOR_EDICT(p) - 1; raceRecord_t *record = NULL; if ((player_number < 0) || (player_number >= (sizeof(race.currentrace) / sizeof(race.currentrace[0])))) { continue; } record = &race.currentrace[player_number]; S2di(handle, INDENT4 "\n", record->avgspeed / record->avgcount, record->distance, record->time, xml_string(p->netname), record->weaponmode, record->startmode, record->maxspeed); S2di(handle, INDENT2 "\n"); } } void xml_team_detail(fileHandle_t handle, int num, teamStats_t *stats) { int j; xml_team_header(handle, num, stats); xml_weap_header(handle); for (j = 1; j < wpMAX; j++) { xml_weap_stats(handle, j, &stats->wpn[j]); } xml_weap_footer(handle); xml_items_header(handle); for (j = 1; j < itMAX; j++) { xml_item_stats(handle, j, &stats->itm[j]); } xml_items_footer(handle); xml_team_footer(handle); } #ifdef BOT_SUPPORT void xml_player_bot_info(fileHandle_t handle, fb_entvars_t* vars) { } #endif void xml_player_detail(fileHandle_t handle, int num, gedict_t *player, const char *team) { int j; xml_player_header(handle, player, team); xml_weap_header(handle); for (j = 1; j < wpMAX; j++) { xml_weap_stats(handle, j, &player->ps.wpn[j]); } xml_weap_footer(handle); xml_items_header(handle); for (j = 1; j < itMAX; j++) { xml_item_stats(handle, j, &player->ps.itm[j]); } xml_items_footer(handle); if (cvar("k_midair")) { xml_player_midair_stats(handle, &player->ps); } if (cvar("k_instagib")) { xml_player_instagib_stats(handle, &player->ps); } if (isCTF()) { xml_player_ctf_stats(handle, &player->ps); } if (isRA()) { xml_player_ra_stats(handle, &player->ps); } if (isHoonyModeDuel()) { S2di(handle, INDENT4 "%s\n", xml_string(HM_round_results(player))); } else { int i; S2di(handle, INDENT4 ""); for (i = 0; i < HM_current_point(); ++i) { S2di(handle, "%s%d", i ? "," : "", player->hoony_results[i]); } S2di(handle, "\n"); } #ifdef BOT_SUPPORT if (player->isBot) { xml_player_bot_info(handle, &player->fb); } #endif xml_player_footer(handle); } QW-Group-ktx-d05d6ca/src/subs.c000066400000000000000000000157521475442401000163510ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" /* QuakeEd only writes a single float for angles (bad idea), so up and down are just constant angles. */ void SetMovedir(void) { if (VectorCompareF(self->s.v.angles, 0, -1, 0)) { SetVector(self->s.v.movedir, 0, 0, 1); } else if (VectorCompareF(self->s.v.angles, 0, -2, 0)) { SetVector(self->s.v.movedir, 0, 0, -1); } else { trap_makevectors(self->s.v.angles); VectorCopy(g_globalvars.v_forward, self->s.v.movedir); } SetVector(self->s.v.angles, 0, 0, 0); } /* ================ InitTrigger ================ */ void InitTrigger(void) { // trigger angles are used for one-way touches. An angle of 0 is assumed // to mean no restrictions, so use a yaw of 360 instead. if (!VectorCompareF(self->s.v.angles, 0, 0, 0)) { SetMovedir(); } self->s.v.solid = SOLID_TRIGGER; setmodel(self, self->model); // set size and link into world self->s.v.movetype = MOVETYPE_NONE; self->s.v.modelindex = 0; self->model = ""; } /* ============= SUB_CalcMove calculate self.velocity and self.nextthink to reach dest from self.origin traveling at speed =============== */ void SUB_CalcMoveDone(void); void SUB_CalcMoveEnt(gedict_t *ent, vec3_t tdest, float tspeed, void (*func)(void)) { gedict_t *stemp; stemp = self; self = ent; SUB_CalcMove(tdest, tspeed, func); self = stemp; } void SUB_CalcMove(vec3_t tdest, float tspeed, void (*func)(void)) { vec3_t vdestdelta; float len, traveltime; if (!tspeed) { G_Error("No speed is defined!"); } self->think1 = func; VectorCopy(tdest, self->finaldest); self->think = (func_t) SUB_CalcMoveDone; if (VectorCompare(tdest, self->s.v.origin)) { SetVector(self->s.v.velocity, 0, 0, 0); self->s.v.nextthink = self->s.v.ltime + 0.1; return; } // set destdelta to the vector needed to move VectorSubtract(tdest, self->s.v.origin, vdestdelta) // calculate length of vector len = vlen(vdestdelta); // divide by speed to get time to reach dest traveltime = len / tspeed; if (traveltime < 0.03) { traveltime = 0.03; } // set nextthink to trigger a think when dest is reached self->s.v.nextthink = self->s.v.ltime + traveltime; // scale the destdelta vector by the time spent traveling to get velocity VectorScale(vdestdelta, (1 / traveltime), self->s.v.velocity); //self.velocity = vdestdelta * (1/traveltime); // qcc won't take vec/float } /* ============ After moving, set origin to exact final destination ============ */ void SUB_CalcMoveDone(void) { setorigin(self, PASSVEC3(self->finaldest)); SetVector(self->s.v.velocity, 0, 0, 0); //self->s.v.nextthink = -1; if (self->think1) { self->think1(); } } /* ============= SUB_CalcAngleMove calculate self.avelocity and self.nextthink to reach destangle from self.angles rotating The calling function should make sure self.think is valid =============== */ /*void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt = { local entity stemp; stemp = self; self = ent; SUB_CalcAngleMove (destangle, tspeed, func); self = stemp; } void SUB_CalcAngleMove(vector destangle, float tspeed, void() func) { local vector destdelta; local float len, traveltime; if (!tspeed) objerror("No speed is defined!"); // set destdelta to the vector needed to move destdelta = destangle - self.angles; // calculate length of vector len = vlen (destdelta); // divide by speed to get time to reach dest traveltime = len / tspeed; // set nextthink to trigger a think when dest is reached self.nextthink = self.ltime + traveltime; // scale the destdelta vector by the time spent traveling to get velocity self.avelocity = destdelta * (1 / traveltime); self.think1 = func; self.finalangle = destangle; self.think = SUB_CalcAngleMoveDone; }*/ /* ============ After rotating, set angle to exact final angle ============ */ /*void SUB_CalcAngleMoveDone(gedict_t*self) { VectorCopy(self->finalangle,self->s.v.angles ); SetVector(self->s.v.avelocity,0,0,0); self->s.v.nextthink = -1; if (self->think1) self->think1(); }*/ //============================================================================= void SUB_UseTargets(void); gedict_t *activator; void DelayThink(void) { activator = PROG_TO_EDICT(self->s.v.enemy); SUB_UseTargets(); ent_remove(self); } /* ============================== SUB_UseTargets the global "activator" should be set to the entity that initiated the firing. If self.delay is set, a DelayedUse entity will be created that will actually do the SUB_UseTargets after that many seconds have passed. Centerprints any self.message to the activator. Removes all entities with a targetname that match self.killtarget, and removes them, so some events can remove other triggers. Search for (string)targetname in all entities that match (string)self.target and call their .use function ============================== */ void SUB_UseTargets(void) { gedict_t *t, *stemp, *otemp, *act; // // check for a delay // if (self->delay) { // create a temp object to fire at a later time t = spawn(); t->classname = "DelayedUse"; t->s.v.nextthink = g_globalvars.time + self->delay; t->think = (func_t) DelayThink; t->s.v.enemy = EDICT_TO_PROG(activator); t->message = self->message; t->killtarget = self->killtarget; t->target = self->target; return; } // // print the message //activator->classname && if ((activator->ct == ctPlayer) && self->message) { if (strneq(self->message, "")) { G_centerprint(activator, "%s", self->message); if (!self->noise) { sound(activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM); } } } // // kill the killtagets // if (self->killtarget) { t = world; do { t = find(t, FOFS(targetname), self->killtarget); if (!t) { return; } ent_remove(t); } while (1); } // // fire targets // if (self->target) { act = activator; t = world; do { t = find(t, FOFS(targetname), self->target); if (!t) { return; } stemp = self; otemp = other; self = t; other = stemp; //if (self.use != SUB_Null) { if (self->use) { ((void (*)(void))(self->use))(); } } self = stemp; other = otemp; activator = act; } while (1); } } QW-Group-ktx-d05d6ca/src/teamplay.c000066400000000000000000001200521475442401000171770ustar00rootroot00000000000000// Teamplay.c // Format & logic of messages based on ezQuake's built-in team messages // Future development: // - Allow (based on fpd) automatic reporting server-side // - If client supports it, send raw stats to client and allow it to construct format of message #include "g_local.h" // Time before we forget item (ezquake allows this to be specified) #define TOOK_TIMEOUT 5 #define POINT_TIMEOUT 5 #define TP_THRESHOLD_NEED_RA 120 #define TP_THRESHOLD_NEED_YA 80 #define TP_THRESHOLD_NEED_GA 60 #define TP_THRESHOLD_NEED_HEALTH 50 #define TP_THRESHOLD_NEED_WEAPON 87 #define TP_THRESHOLD_NEED_RL 1 #define TP_THRESHOLD_NEED_CELLS 13 #define TP_THRESHOLD_NEED_ROCKETS 5 #define TP_THRESHOLD_NEED_NAILS 0 #define TP_THRESHOLD_NEED_SHELLS 0 #define TP_NAME_SG "sg" #define TP_NAME_SSG "ssg" #define TP_NAME_NG "ng" #define TP_NAME_SNG "sng" #define TP_NAME_GL "gl" #define TP_NAME_RLG "{&cf13rl&cfff}{&c2aag&cfff}" #define TP_NAME_RL "{&cf13rl&cfff}" #define TP_NAME_LG "{&c2aalg&cfff}" #define TP_NAME_SHELLS "shells" #define TP_NAME_NAILS "nails" #define TP_NAME_ROCKETS "rox" #define TP_NAME_CELLS "cells" #define TP_NAME_RL_PACK "{&cf13rl pack&cfff}" #define TP_NAME_LG_PACK "{&c2aalg pack&cfff}" #define TP_NAME_BACKPACK "pack" #define TP_NAME_MEGA "{&c0a0mega&cfff}" #define TP_NAME_RA "{&cf00ra&cfff}" #define TP_NAME_YA "{&cff0ya&cfff}" #define TP_NAME_GA "{&c0b0ga&cfff}" #define TP_NAME_QUAD "{&c05fquad&cfff}" #define TP_NAME_PENT "{&cf00pent&cfff}" #define TP_NAME_RING "{&cff0ring&cfff}" #define TP_NAME_SUIT "suit" #define TP_NAME_FLAG "flag" #define TP_NAME_RUNE1 "{&c0f0resistance&cfff}" #define TP_NAME_RUNE2 "{&cf00strength&cfff}" #define TP_NAME_RUNE3 "{&cff0haste&cfff}" #define TP_NAME_RUNE4 "{&c0ffregeneration&cfff}" #define TP_NAME_ARMOR "armor" #define TP_SEPARATOR "/" #define TP_NAME_HEALTH "health" #define TP_NAME_AMMO "ammo" #define TP_NAME_WEAPON "weapon" #define TP_NAME_QUADDED "{&c05fquaded&cfff}" #define TP_NAME_PENTED "{&cf00pented&cfff}" #define TP_NAME_EYES "{&cff0eyes&cfff}" #define TP_NAME_ENEMY "{&cf00enemy&cfff}" #define TP_NAME_SOMEPLACE "someplace" #define TP_NAME_HASQUAD "{&c05fquaded&cfff}" #define TP_NAME_HADPENT "{&cf00pented&cfff}" char* LocationName(float x, float y, float z); static void TeamplayQuadDead(gedict_t *client); static void TeamplayAreaLost(gedict_t *client); static void TeamplayAreaSecure(gedict_t *client); static void TeamplayAreaHelp(gedict_t *client); unsigned long item_flags[] = { it_rl, it_lg, it_gl, it_sng, it_pack, it_cells, it_rockets, it_mh, it_ra, it_ya, it_ga, it_flag, it_rune1, it_rune2, it_rune3, it_rune4, it_quad, it_pent, it_ring }; char *item_names[] = { TP_NAME_RL, TP_NAME_LG, TP_NAME_GL, TP_NAME_SNG, TP_NAME_BACKPACK, TP_NAME_CELLS, TP_NAME_ROCKETS, TP_NAME_MEGA, TP_NAME_RA, TP_NAME_YA, TP_NAME_GA, TP_NAME_FLAG, TP_NAME_RUNE1, TP_NAME_RUNE2, TP_NAME_RUNE3, TP_NAME_RUNE4, TP_NAME_QUAD, TP_NAME_PENT, TP_NAME_RING }; #ifdef Q3_VM unsigned long strtoul(const char* str, char** endptr, int base) { unsigned long value = 0; while (*str >= '0' && *str <= '9') { value *= 10 + (*str - '0'); ++str; } return value; } #endif void TeamplayEventItemTaken(gedict_t *client, gedict_t *item) { char *took_flags_s = ezinfokey(client, "tptook"); unsigned long took_flags = ~0U; if (!strnull(took_flags_s)) { took_flags = strtoul(took_flags_s, NULL, 10); } if (took_flags == 0) { took_flags = ~0U; } if (!(took_flags & item->tp_flags)) { return; } client->tp.took.flags = 0; if (streq(item->classname, "weapon_lightning")) { client->tp.took.item = it_lg; } else if (streq(item->classname, "weapon_rocketlauncher")) { client->tp.took.item = it_rl; } else if (streq(item->classname, "weapon_grenadelauncher")) { client->tp.took.item = it_gl; } else if (streq(item->classname, "weapon_supernailgun")) { client->tp.took.item = it_sng; } else if (streq(item->classname, "weapon_nailgun")) { client->tp.took.item = it_ng; } else if (streq(item->classname, "weapon_supershotgun")) { client->tp.took.item = it_ssg; } else if (streq(item->classname, "item_armorInv")) { client->tp.took.item = it_ra; } else if (streq(item->classname, "item_armor2")) { client->tp.took.item = it_ya; } else if (streq(item->classname, "item_armor1")) { client->tp.took.item = it_ga; } else if (streq(item->classname, "item_artifact_envirosuit")) { client->tp.took.item = it_suit; } else if (streq(item->classname, "item_artifact_invulnerability")) { client->tp.took.item = it_pent; } else if (streq(item->classname, "item_artifact_invisibility")) { client->tp.took.item = it_ring; } else if (streq(item->classname, "item_artifact_super_damage")) { client->tp.took.item = it_quad; } else if (streq(item->classname, "backpack")) { client->tp.took.item = it_pack; client->tp.took.flags = item->s.v.items; } else if (streq(item->classname, "item_shells")) { client->tp.took.item = it_shells; } else if (streq(item->classname, "item_spikes")) { client->tp.took.item = it_nails; } else if (streq(item->classname, "item_rockets")) { client->tp.took.item = it_rockets; } else if (streq(item->classname, "item_cells")) { client->tp.took.item = it_cells; } else if (streq(item->classname, "item_health")) { client->tp.took.item = (item->healamount >= 100 ? it_mh : it_health); } else { return; } VectorCopy(item->s.v.origin, client->tp.took.location); client->tp.took.time = g_globalvars.time; } static qbool TookEmpty(gedict_t *client) { return ((client->tp.took.time == 0) || (client->tp.took.time < (g_globalvars.time - TOOK_TIMEOUT))); } static qbool Took(gedict_t *client, unsigned long flag) { return (!TookEmpty(client) && (client->tp.took.item == flag)); } static qbool TookSpecific(gedict_t *client, unsigned long flag, unsigned long specific) { return (Took(client, flag) && (client->tp.took.flags == specific)); } static qbool NEED(unsigned long player_flags, unsigned long flags) { return (player_flags & flags); } static qbool HAVE_POWERUP(gedict_t *client) { return (client && ((int)client->s.v.items & (IT_QUAD | IT_INVULNERABILITY | IT_INVISIBILITY))); } static qbool HAVE_RING(gedict_t *client) { return (client && ((int)client->s.v.items & IT_INVISIBILITY)); } static qbool HAVE_QUAD(gedict_t *client) { return (client && ((int)client->s.v.items & IT_QUAD)); } static qbool HAVE_PENT(gedict_t *client) { return (client && ((int)client->s.v.items & IT_INVULNERABILITY)); } static qbool HAVE_GA(gedict_t *client) { return (client && ((int)client->s.v.items & IT_ARMOR1)); } /* static qbool HAVE_YA (gedict_t* client) { return (int)client->s.v.items & IT_ARMOR2; } static qbool HAVE_RA (gedict_t* client) { return (int)client->s.v.items & IT_ARMOR3; } */ static qbool HAVE_RL(gedict_t *client) { return ((int)client->s.v.items & IT_ROCKET_LAUNCHER); } static qbool HAVE_LG(gedict_t *client) { return ((int)client->s.v.items & IT_LIGHTNING); } static qbool HAVE_SNG(gedict_t *client) { return ((int)client->s.v.items & IT_SUPER_NAILGUN); } /* static qbool HAVE_NG (gedict_t* client) { return ((int)client->s.v.items & IT_NAILGUN); } */ static qbool HAVE_GL(gedict_t *client) { return ((int)client->s.v.items & IT_GRENADE_LAUNCHER); } static qbool HAVE_SSG(gedict_t *client) { return ((int)client->s.v.items & IT_SUPER_SHOTGUN); } typedef struct item_vis_s { vec3_t vieworg; vec3_t forward; vec3_t right; vec3_t up; vec3_t entorg; float radius; vec3_t dir; float dist; gedict_t *viewent; } item_vis_t; // TODO: Do not support tp_pointpriorities at the moment static float TeamplayRankPoint(item_vis_t *visitem) { vec3_t v2, v3; float miss; if (visitem->dist < 10) { return -1; } VectorScale(visitem->forward, visitem->dist, v2); VectorSubtract(v2, visitem->dir, v3); miss = VectorLength(v3); if (miss > 300) { return -1; } if (miss > (visitem->dist * 1.7)) { return -1; // over 60 degrees off } if (visitem->dist < (3000.0 / 8.0)) { return (miss * (visitem->dist * 8.0 * 0.0002f + 0.3f)); } else { return miss; } } static qbool TP_IsItemVisible(item_vis_t *visitem) { vec3_t end, v; if (visitem->dist <= visitem->radius) { return true; } VectorScale(visitem->dir, -1, v); VectorNormalize(v); VectorMA(visitem->entorg, visitem->radius, v, end); traceline(PASSVEC3(visitem->vieworg), PASSVEC3(end), 0, visitem->viewent); if (g_globalvars.trace_fraction == 1) { return true; } VectorMA(visitem->entorg, visitem->radius, visitem->right, end); VectorSubtract(visitem->vieworg, end, v); VectorNormalize(v); VectorMA(end, visitem->radius, v, end); traceline(PASSVEC3(visitem->vieworg), PASSVEC3(end), 0, visitem->viewent); if (g_globalvars.trace_fraction == 1) { return true; } VectorMA(visitem->entorg, -visitem->radius, visitem->right, end); VectorSubtract(visitem->vieworg, end, v); VectorNormalize(v); VectorMA(end, visitem->radius, v, end); traceline(PASSVEC3(visitem->vieworg), PASSVEC3(end), 0, visitem->viewent); if (g_globalvars.trace_fraction == 1) { return true; } VectorMA(visitem->entorg, visitem->radius, visitem->up, end); VectorSubtract(visitem->vieworg, end, v); VectorNormalize(v); VectorMA(end, visitem->radius, v, end); traceline(PASSVEC3(visitem->vieworg), PASSVEC3(end), 0, visitem->viewent); if (g_globalvars.trace_fraction == 1) { return true; } // use half the radius, otherwise it's possible to see through floor in some places VectorMA(visitem->entorg, -visitem->radius / 2, visitem->up, end); VectorSubtract(visitem->vieworg, end, v); VectorNormalize(v); VectorMA(end, visitem->radius, v, end); traceline(PASSVEC3(visitem->vieworg), PASSVEC3(end), 0, visitem->viewent); if (g_globalvars.trace_fraction == 1) { return true; } return false; } static gedict_t* TeamplayFindPoint(gedict_t *client) { int i; unsigned long pointflags = ~0U; vec3_t ang; item_vis_t visitem; float best = -1; gedict_t *bestent = NULL; byte visible[MAX_EDICTS]; if (deathmatch >= 1 && deathmatch <= 4) { if (deathmatch == 4) { pointflags &= ~(unsigned long) it_ammo; } if (deathmatch != 1) { pointflags &= ~(unsigned long) it_weapons; } } VectorCopy(client->s.v.v_angle, ang); ang[2] = 0; AngleVectors(ang, visitem.forward, visitem.right, visitem.up); VectorCopy(client->s.v.origin, visitem.vieworg); visitem.viewent = client; VectorAdd(visitem.vieworg, client->s.v.view_ofs, visitem.vieworg); // FIXME: v_viewheight not taken into account visible_to(client, g_edicts, MAX_EDICTS, visible); for (i = 0; i < MAX_EDICTS; i++) { gedict_t *e = &g_edicts[i]; vec3_t size; float rank; if (!visible[i]) continue; if ((e->ct == ctPlayer && !ISLIVE(e)) || e->ct == ctSpec) { continue; } if (strnull(e->model)) { continue; } if ((e->ct != ctPlayer) && !(e->tp_flags & pointflags)) { continue; } VectorSubtract(e->s.v.absmax, e->s.v.absmin, size); if (e->ct == ctPlayer) { VectorAdd(e->s.v.origin, e->s.v.view_ofs, visitem.entorg) } else { VectorCopy(e->s.v.origin, visitem.entorg); visitem.entorg[2] += size[2] / 2; } VectorSubtract(visitem.entorg, visitem.vieworg, visitem.dir); visitem.dist = DotProduct(visitem.dir, visitem.forward); visitem.radius = (int)e->s.v.effects & (EF_BLUE | EF_RED | EF_DIMLIGHT | EF_BRIGHTLIGHT) ? 200 : max(max(size[0] / 2, size[1] / 2), size[2] / 2); if ((rank = TeamplayRankPoint(&visitem)) < 0) { continue; } // check if we can actually see the object (TODO: with pointflags, player detection is different) if (((rank < best) || (best < 0)) && TP_IsItemVisible(&visitem)) { best = rank; bestent = e; } } return bestent; } static char* PowerupText(gedict_t *client) { static char buffer[128]; buffer[0] = '\0'; if (HAVE_PENT(client)) { strlcat(buffer, TP_NAME_PENT, sizeof(buffer)); } if (HAVE_QUAD(client)) { strlcat(buffer, TP_NAME_QUAD, sizeof(buffer)); } if (HAVE_RING(client)) { strlcat(buffer, TP_NAME_RING, sizeof(buffer)); } return buffer; } static void TeamplayMM2(gedict_t *client, char *text) { extern qbool ClientSay(qbool isTeamSay); char buffer[128]; gedict_t *oldself = self; char *name = NULL; self = client; g_globalvars.self = EDICT_TO_PROG(self); strlcpy(buffer, "say_team \"", sizeof(buffer)); name = ezinfokey(client, "k_nick"); if (strnull(name)) { name = ezinfokey(client, "k"); } if (strnull(name) && client->isBot) { name = client->netname; } if (!strnull(name)) { strlcat(buffer, "\r", sizeof(buffer)); strlcat(buffer, name, sizeof(buffer)); strlcat(buffer, " ", sizeof(buffer)); } strlcat(buffer, text, sizeof(buffer)); strlcat(buffer, "\"", sizeof(buffer)); trap_CmdTokenize(buffer); ClientSay(true); self = oldself; g_globalvars.self = EDICT_TO_PROG(oldself); } static char* TeamplayNeedText(unsigned long needFlags) { static char buffer[128]; buffer[0] = '\0'; if (needFlags & it_armor) { strlcat(buffer, TP_NAME_ARMOR, sizeof(buffer)); } if (needFlags & it_health) { if (buffer[0]) { strlcat(buffer, TP_SEPARATOR, sizeof(buffer)); } strlcat(buffer, TP_NAME_HEALTH, sizeof(buffer)); } if (needFlags & it_ammo) { if (buffer[0]) { strlcat(buffer, TP_SEPARATOR, sizeof(buffer)); } strlcat(buffer, TP_NAME_AMMO, sizeof(buffer)); } if (needFlags & (it_rl | it_lg)) { if (buffer[0]) { strlcat(buffer, TP_SEPARATOR, sizeof(buffer)); } strlcat(buffer, TP_NAME_WEAPON, sizeof(buffer)); } return buffer; } static unsigned long TeamplayNeedFlags(gedict_t *client) { unsigned long needflags = 0; int items = (int)client->s.v.items; const char *need_weapons = ezinfokey(self, "tp_need_weapon"); if (strnull(need_weapons)) { need_weapons = NEED_WEAPONS_DEFAULT; } if (((items & IT_ARMOR1) && client->s.v.armorvalue < TP_THRESHOLD_NEED_GA) || ((items & IT_ARMOR2) && client->s.v.armorvalue < TP_THRESHOLD_NEED_YA) || ((items & IT_ARMOR3) && client->s.v.armorvalue < TP_THRESHOLD_NEED_RA) || (!(items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)))) { needflags |= it_armor; } if (client->s.v.health < TP_THRESHOLD_NEED_HEALTH) { needflags |= it_health; } // (team fortress logic removed) { qbool found_weapon = false; const char *needammo = NULL; while (*need_weapons) { int weapon = *need_weapons - '0' - 1; if ((weapon == 8) && (items & IT_LIGHTNING)) { if (client->s.v.ammo_cells < TP_THRESHOLD_NEED_CELLS) { needflags |= it_cells; needammo = "cells"; found_weapon = true; } break; } else if (((weapon == 7) && (items & IT_ROCKET_LAUNCHER)) || ((weapon == 6) && (items & IT_GRENADE_LAUNCHER))) { if (client->s.v.ammo_rockets < TP_THRESHOLD_NEED_ROCKETS) { needflags |= it_rockets; needammo = "rox"; found_weapon = true; } } else if (((weapon == 5) && (items & IT_SUPER_NAILGUN)) || ((weapon == 4) && (items & IT_NAILGUN))) { if (client->s.v.ammo_nails < TP_THRESHOLD_NEED_NAILS) { needflags |= it_nails; needammo = "nails"; found_weapon = true; } } else if (((weapon == 3) && (items & IT_SUPER_SHOTGUN)) || ((weapon == 2) && (items & IT_SHOTGUN))) { if (client->s.v.ammo_shells < TP_THRESHOLD_NEED_SHELLS) { needflags |= it_shells; needammo = "shells"; found_weapon = true; } } ++need_weapons; } if (needammo) { needflags |= it_ammo; } else if (!found_weapon) { needflags |= it_weapons; } else if (!(items & IT_ROCKET_LAUNCHER)) { needflags |= it_rl; } } return needflags; } // Cmd_AddCommand ("tp_msgtook", TP_Msg_Took_f); static void TeamplayReportTaken(gedict_t *client) { char message[128]; char *at_location = LocationName(PASSVEC3(client->tp.took.location)); if (TookEmpty(client)) { return; } message[0] = '\0'; if (client->tp.took.item & it_powerups) { unsigned long needFlags = TeamplayNeedFlags(client); if (!ISLIVE(client)) { TeamplayQuadDead(client); return; } else if ((NEED(needFlags, it_health) || NEED(needFlags, it_armor) || NEED(needFlags, it_rl) || NEED(needFlags, it_lg) || NEED(needFlags, it_rockets) || NEED(needFlags, it_cells)) && HAVE_POWERUP(client)) { // Note that we check if you are holding powerup. This is because TOOK remembers for 15 seconds. // So a case could arise where you took quad then died less than 15 seconds later, and you'd be reporting "team need %u" (because $colored_powerups would be empty) strlcpy(message, "{&c0b0team&cfff} ", sizeof(message)); strlcat(message, PowerupText(client), sizeof(message)); strlcat(message, " need ", sizeof(message)); strlcat(message, TeamplayNeedText(needFlags), sizeof(message)); } else if (HAVE_QUAD(client) || HAVE_RING(client)) { // notice we can't send this check to tp_msgenemypwr, because if enemy with powerup is in your view, tp_enemypwr reports enemypwr first, but in this function you want to report TEAM powerup. strlcpy(message, "{&c0b0team&cfff} ", sizeof(message)); strlcat(message, PowerupText(client), sizeof(message)); } else { // In this case, you took quad or ring and died before 15 secs later. So just report what you need, nothing about powerups. strlcat(message, "need ", sizeof(message)); strlcat(message, TeamplayNeedText(needFlags), sizeof(message)); } } else { int i = 0; if (HAVE_POWERUP(client)) { strlcpy(message, PowerupText(client), sizeof(message)); strlcat(message, " ", sizeof(message)); } if (TookSpecific(client, it_pack, IT_ROCKET_LAUNCHER)) { strlcat(message, "took " TP_NAME_RL_PACK, sizeof(message)); } else if (TookSpecific(client, it_pack, IT_LIGHTNING)) { strlcat(message, "took " TP_NAME_LG_PACK, sizeof(message)); } else { for (i = 0; i < (sizeof(item_flags) / sizeof(item_flags[0])); ++i) { if (Took(client, item_flags[i])) { strlcat(message, "took ", sizeof(message)); strlcat(message, item_names[i], sizeof(message)); break; } } if (i > (sizeof(item_flags) / sizeof(item_flags[0]))) { G_bprint(2, "TOOK ITEM FLAG: %u\n", (unsigned) client->tp.took.item); } } } strlcat(message, " \20{", sizeof(message)); strlcat(message, at_location, sizeof(message)); strlcat(message, "}\21", sizeof(message)); TeamplayMM2(client, message); } static char* ColoredArmor(gedict_t *client) { if (HAVE_GA(client)) { return va("{&c0b0%d&cfff}", (int)client->s.v.armorvalue); } if (HAVE_GA(client)) { return va("{&c0b0%d&cfff}", (int)client->s.v.armorvalue); } if (HAVE_GA(client)) { return va("{&c0b0%d&cfff}", (int)client->s.v.armorvalue); } return "0"; } // Cmd_AddCommand ("tp_msgreport", TP_Msg_Report_f); static void TeamplayReportPersonalStatus(gedict_t *client) { char buffer[128]; buffer[0] = '\0'; if (!ISLIVE(client)) { TeamplayAreaLost(client); return; } if (HAVE_POWERUP(client)) { strlcpy(buffer, PowerupText(client), sizeof(buffer)); } strlcat(buffer, va("%s/%d ", ColoredArmor(client), (int)max(0, client->s.v.health)), sizeof(buffer)); if (HAVE_RL(client) && HAVE_LG(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_RL, (int)client->s.v.ammo_rockets), sizeof(buffer)); strlcat(buffer, va("%s:%d ", TP_NAME_LG, (int)client->s.v.ammo_cells), sizeof(buffer)); } else if (HAVE_RL(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_RL, (int)client->s.v.ammo_rockets), sizeof(buffer)); } else if (HAVE_LG(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_LG, (int)client->s.v.ammo_cells), sizeof(buffer)); } else if (HAVE_GL(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_GL, (int)client->s.v.ammo_rockets), sizeof(buffer)); } else if (HAVE_SNG(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_SNG, (int)client->s.v.ammo_nails), sizeof(buffer)); } else if (HAVE_SSG(client)) { strlcat(buffer, va("%s:%d ", TP_NAME_SSG, (int)client->s.v.ammo_shells), sizeof(buffer)); } strlcat(buffer, "\20{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}\21", sizeof(buffer)); if (!HAVE_RL(client) && client->s.v.ammo_rockets) { strlcat(buffer, va(" {&cf13r&cfff}:%d", (int)client->s.v.ammo_rockets), sizeof(buffer)); } if (!HAVE_LG(client) && client->s.v.ammo_cells) { strlcat(buffer, va(" {&c2aac&cfff}:%d", (int)client->s.v.ammo_cells), sizeof(buffer)); } TeamplayMM2(client, buffer); } // Cmd_AddCommand ("tp_msgsafe", TP_Msg_Safe_f); static void TeamplayAreaSecure(gedict_t *client) { qbool have_armor = (int)client->s.v.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3); qbool have_weapon = (int)client->s.v.items & (IT_ROCKET_LAUNCHER | IT_LIGHTNING); char buffer[128]; buffer[0] = '\0'; if (!ISLIVE(client)) { return; } // TODO: if pointing at enemy, degrade to TP_EnemyPowerup or no-op strlcpy(buffer, "{&c0b0safe&cfff} {&c0b0[&cfff}{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}{&c0b0]&cfff} ", sizeof(buffer)); if (have_armor) { strlcat(buffer, ColoredArmor(client), sizeof(buffer)); } if (have_armor && have_weapon) { strlcat(buffer, " ", sizeof(buffer)); } if (HAVE_RL(client) && HAVE_LG(client)) { strlcat(buffer, TP_NAME_RLG, sizeof(buffer)); } else if (HAVE_RL(client)) { strlcat(buffer, TP_NAME_RL, sizeof(buffer)); } else if (HAVE_LG(client)) { strlcat(buffer, TP_NAME_LG, sizeof(buffer)); } TeamplayMM2(client, buffer); } // Cmd_AddCommand ("tp_msghelp", TP_Msg_Help_f); static void TeamplayAreaHelp(gedict_t *client) { char buffer[128]; buffer[0] = '\0'; strlcpy(buffer, PowerupText(client), sizeof(buffer)); strlcat(buffer, "{&cff0help&cfff} {&cff0[&cfff}{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, va("}{&cff0]&cfff} {%d}", client->tp.enemy_count), sizeof(buffer)); TeamplayMM2(client, buffer); } // Cmd_AddCommand ("tp_msglost", TP_Msg_Lost_f); static void TeamplayAreaLost(gedict_t *client) { char buffer[128]; buffer[0] = '\0'; if (!ISLIVE(client)) { if (client->tp.death_items & IT_QUAD) { strlcpy(buffer, TP_NAME_QUAD, sizeof(buffer)); strlcat(buffer, " over ", sizeof(buffer)); } else { strlcpy(buffer, "{&cf00lost&cfff} ", sizeof(buffer)); } if (client->tp.death_weapon == IT_ROCKET_LAUNCHER) { strlcat(buffer, "{&cf00DROPPED} " TP_NAME_RL " ", sizeof(buffer)); } else if (client->tp.death_weapon == IT_LIGHTNING) { strlcat(buffer, "{&cf00DROPPED} " TP_NAME_LG " ", sizeof(buffer)); } } else { strlcpy(buffer, "{&cf00lost&cfff} ", sizeof(buffer)); } strlcat(buffer, "{&cf00[&cfff}{", sizeof(buffer)); if (client->tp.death_time > 0) { strlcat(buffer, LocationName(PASSVEC3(client->tp.death_location)), sizeof(buffer)); } else { strlcat(buffer, TP_NAME_SOMEPLACE, sizeof(buffer)); } strlcat(buffer, va("}{&cf00]&cfff} {%d}", client->tp.enemy_count), sizeof(buffer)); TeamplayMM2(client, buffer); } // Cmd_AddCommand ("tp_msgkillme", TP_Msg_KillMe_f); static void TeamplayKillMe(gedict_t *client) { char buffer[128]; gedict_t *point = NULL; if (!ISLIVE(client)) { return; } buffer[0] = '\0'; point = TeamplayFindPoint(client); if (point && (point->ct == ctPlayer) && SameTeam(client, point)) { strlcpy(buffer, "{&c0b0", sizeof(buffer)); strlcat(buffer, point->netname, sizeof(buffer)); strlcat(buffer, "&cfff} ", sizeof(buffer)); } strlcat(buffer, "{&cb1akill me [&cfff}{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}{&cf2a]&cfff} ", sizeof(buffer)); if ((int)client->s.v.weapon & IT_ROCKET_LAUNCHER) { strlcat(buffer, TP_NAME_RL, sizeof(buffer)); strlcat(buffer, va(":%d ", (int)client->s.v.ammo_rockets), sizeof(buffer)); } else if ((int)client->s.v.weapon & IT_LIGHTNING) { strlcat(buffer, TP_NAME_LG, sizeof(buffer)); strlcat(buffer, va(":%d ", (int)client->s.v.ammo_cells), sizeof(buffer)); } if (!HAVE_RL(client) && client->s.v.ammo_rockets > 0) { strlcat(buffer, va("{&cf13r&cfff}:%d ", (int)client->s.v.ammo_rockets), sizeof(buffer)); } if (!HAVE_LG(client) && client->s.v.ammo_cells > 0) { strlcat(buffer, va("{&c2aac&cfff}:%d", (int)client->s.v.ammo_cells), sizeof(buffer)); } TeamplayMM2(client, buffer); } // Cmd_AddCommand ("tp_msgutake", TP_Msg_YouTake_f); static void TeamplayYouTake(gedict_t *client) { char buffer[128]; gedict_t *point = NULL; buffer[0] = '\0'; point = TeamplayFindPoint(client); if (point && (point->ct == ctPlayer) && SameTeam(client, point)) { strlcpy(buffer, "{&c0b0", sizeof(buffer)); strlcpy(buffer, point->netname, sizeof(buffer)); strlcpy(buffer, "&cfff} take \20{", sizeof(buffer)); } else { strlcpy(buffer, "you take \20{", sizeof(buffer)); } strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}\21", sizeof(buffer)); } // Cmd_AddCommand ("tp_msgneed", TP_Msg_Need_f); static void TeamplayReportNeeds(gedict_t *client) { unsigned long needFlags; char buffer[128]; if (!ISLIVE(client)) { return; } needFlags = TeamplayNeedFlags(client); buffer[0] = '\0'; if (NEED(needFlags, it_health) || NEED(needFlags, it_armor) || NEED(needFlags, it_rl) || NEED(needFlags, it_lg) || NEED(needFlags, it_rockets) || NEED(needFlags, it_cells) || NEED(needFlags, it_shells) || NEED(needFlags, it_nails)) { if (HAVE_POWERUP(client)) { strlcpy(buffer, "{&c0b0team&cfff} ", sizeof(buffer)); strlcat(buffer, PowerupText(client), sizeof(buffer)); strlcat(buffer, " ", sizeof(buffer)); } strlcat(buffer, "need ", sizeof(buffer)); strlcat(buffer, TeamplayNeedText(needFlags), sizeof(buffer)); strlcat(buffer, " \20{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}\21", sizeof(buffer)); TeamplayMM2(client, buffer); } } static char* TeamplayLastEnemyPowerupText(gedict_t *client, qbool *location_included) { static char buffer[128]; buffer[0] = '\0'; // whatever last seen powerup was (or quad if not) if ((client->tp.enemy_items == 0) || ((g_globalvars.time - client->tp.enemy_itemtime) > 5)) { // too long ago, assume quad strlcat(buffer, TP_NAME_QUAD, sizeof(buffer)); *location_included = false; } else { qbool eyes = client->tp.enemy_items & IT_INVISIBILITY; qbool quaded = client->tp.enemy_items & IT_QUAD; qbool pented = client->tp.enemy_items & IT_INVULNERABILITY; if (quaded && pented) { strlcat(buffer, TP_NAME_QUAD " " TP_NAME_PENT, sizeof(buffer)); } else if (quaded) { strlcat(buffer, TP_NAME_QUAD, sizeof(buffer)); } else if (pented) { strlcat(buffer, TP_NAME_PENT, sizeof(buffer)); } if (eyes && (quaded || pented)) { strlcat(buffer, " " TP_NAME_RING, sizeof(buffer)); } else if (eyes) { strlcat(buffer, TP_NAME_RING, sizeof(buffer)); } strlcat(buffer, " \20{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->tp.enemy_location)), sizeof(buffer)); strlcat(buffer, "}\21", sizeof(buffer)); *location_included = true; } return buffer; } // Cmd_AddCommand ("tp_msgenemypwr", TP_Msg_EnemyPowerup_f); static void TeamplayEnemyPowerup(gedict_t *client) { gedict_t *point = TeamplayFindPoint(client); qbool quaded = HAVE_QUAD(point); qbool pented = HAVE_PENT(point); qbool suppressLocation = false; char buffer[128]; buffer[0] = '\0'; if (HAVE_RING(point)) { if (quaded && pented) { strlcpy(buffer, TP_NAME_QUADDED " " TP_NAME_PENTED " " TP_NAME_EYES, sizeof(buffer)); } else if (quaded) { strlcpy(buffer, TP_NAME_QUADDED " " TP_NAME_EYES, sizeof(buffer)); } else if (pented) { strlcpy(buffer, TP_NAME_PENTED " " TP_NAME_EYES, sizeof(buffer)); } else { strlcpy(buffer, TP_NAME_EYES, sizeof(buffer)); } } else if (point && point->ct == ctPlayer && !SameTeam(client, point)) { strlcpy(buffer, TP_NAME_ENEMY, sizeof(buffer)); strlcat(buffer, " ", sizeof(buffer)); if (quaded && pented) { strlcat(buffer, TP_NAME_QUAD " " TP_NAME_PENT " ", sizeof(buffer)); } else if (quaded) { strlcat(buffer, TP_NAME_QUAD " ", sizeof(buffer)); } else if (pented) { strlcat(buffer, TP_NAME_PENT " ", sizeof(buffer)); } else { strlcat(buffer, TeamplayLastEnemyPowerupText(client, &suppressLocation), sizeof(buffer)); } } else if (HAVE_POWERUP(client)) { unsigned long needFlags = 0; if (!ISLIVE(client)) { TeamplayAreaLost(client); return; } needFlags = TeamplayNeedFlags(client); if (NEED(needFlags, it_health) || NEED(needFlags, it_armor) || NEED(needFlags, it_rockets) || NEED(needFlags, it_cells) || NEED(needFlags, it_rl) || NEED(needFlags, it_lg)) { TeamplayReportNeeds(client); return; } strlcpy(buffer, "{&c0b0team&cfff} ", sizeof(buffer)); strlcat(buffer, PowerupText(client), sizeof(buffer)); strlcat(buffer, " ", sizeof(buffer)); } else if (point && point->ct == ctPlayer && SameTeam(point, client)) { quaded = HAVE_QUAD(point); pented = HAVE_PENT(point); if (quaded && pented) { strlcpy(buffer, "{&c0b0team&cfff} " TP_NAME_QUAD " " TP_NAME_PENT, sizeof(buffer)); } else if (quaded) { strlcpy(buffer, "{&c0b0team&cfff} " TP_NAME_QUAD, sizeof(buffer)); } else if (pented) { strlcpy(buffer, "{&c0b0team&cfff} " TP_NAME_PENT, sizeof(buffer)); } else { strlcpy(buffer, TP_NAME_ENEMY " ", sizeof(buffer)); strlcat(buffer, TeamplayLastEnemyPowerupText(client, &suppressLocation), sizeof(buffer)); } } else { strlcpy(buffer, TP_NAME_ENEMY " ", sizeof(buffer)); strlcat(buffer, TeamplayLastEnemyPowerupText(client, &suppressLocation), sizeof(buffer)); } if (!suppressLocation) { strlcat(buffer, " at \20{", sizeof(buffer)); if (point) { strlcat(buffer, LocationName(PASSVEC3(point->s.v.origin)), sizeof(buffer)); } else { strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); } strlcat(buffer, "}\21", sizeof(buffer)); } TeamplayMM2(client, buffer); } static void TeamplaySetEnemyFlags(gedict_t *client) { gedict_t *plr = world; int enemy_items = 0; int enemy_count = 0; int friend_count = 0; byte visible[MAX_CLIENTS]; visible_to(client, g_edicts + 1, MAX_CLIENTS, visible); for (plr = g_edicts + 1; plr <= g_edicts + MAX_CLIENTS; plr++) { if (plr == client || plr->ct == ctSpec) { continue; } if (!visible[plr - (g_edicts + 1)]) { continue; } enemy_items |= ((int)plr->s.v.items & (IT_INVISIBILITY)); if (SameTeam(plr, client)) { ++friend_count; } else { enemy_items |= ((int)plr->s.v.items & (IT_QUAD | IT_INVULNERABILITY)); ++enemy_count; } } if (enemy_items) { client->tp.enemy_items = enemy_items; client->tp.enemy_itemtime = g_globalvars.time; VectorAdd(client->s.v.origin, client->s.v.view_ofs, client->tp.enemy_location); } client->tp.enemy_count = enemy_count; client->tp.teammate_count = friend_count; } void TeamplayGameTick(void) { // Set all enemy powerup flags gedict_t *plr = NULL; for (plr = world; (plr = find_plr(plr));) { TeamplaySetEnemyFlags(plr); } } // Cmd_AddCommand ("tp_msgquaddead", TP_Msg_QuadDead_f); static void TeamplayQuadDead(gedict_t *client) { gedict_t *point = NULL; if (HAVE_QUAD(client) && !ISLIVE(client)) { TeamplayAreaLost(client); return; } point = TeamplayFindPoint(client); if (HAVE_QUAD(point)) { TeamplayEnemyPowerup(client); return; } TeamplayMM2(client, TP_NAME_QUAD " dead/over"); } // Cmd_AddCommand ("tp_msggetquad", TP_Msg_GetQuad_f); static void TeamplayGetQuad(gedict_t *client) { gedict_t *point = TeamplayFindPoint(client); if (HAVE_RING(point) && HAVE_QUAD(point)) { return; // Don't know for sure if it's enemy or not, and can't assume like we do in tp_enemypwr because this isn't tp_ENEMYpwr } else if (HAVE_QUAD(client) || HAVE_QUAD(point)) { TeamplayEnemyPowerup(client); return; } else { TeamplayMM2(client, "get " TP_NAME_QUAD); } } // Cmd_AddCommand ("tp_msggetpent", TP_Msg_GetPent_f); static void TeamplayGetPent(gedict_t *client) { gedict_t *point = TeamplayFindPoint(client); if (HAVE_RING(point) && HAVE_PENT(point)) { return; } else if (HAVE_PENT(client) || HAVE_PENT(point)) { TeamplayEnemyPowerup(client); return; } else { TeamplayMM2(client, "get " TP_NAME_PENT); } } // GLOBAL void TP_Msg_Point_f (void) static void TeamplayPoint(gedict_t *client) { char buffer[128]; gedict_t *point = NULL; int point_items = 0; buffer[0] = '\0'; point = TeamplayFindPoint(client); if (point == NULL) { return; } point_items = (int)point->s.v.items; if ((match_in_progress == 2) && (point_items & (IT_INVISIBILITY | IT_QUAD | IT_INVULNERABILITY))) { TeamplayEnemyPowerup(client); return; } if (point->ct == ctPlayer) { if (!SameTeam(point, client)) { strlcat(buffer, va("{%d} %s at \20{%s}\21", client->tp.enemy_count, TP_NAME_ENEMY, LocationName(PASSVEC3(point->s.v.origin))), sizeof(buffer)); } else { strlcat(buffer, "{&c0b0", sizeof(buffer)); strlcat(buffer, point->netname, sizeof(buffer)); strlcat(buffer, "&cfff}", sizeof(buffer)); } } else { int i; for (i = 0; i < (sizeof(item_flags) / sizeof(item_flags[0])); ++i) { if (point->tp_flags & item_flags[i]) { strlcat(buffer, va("%s at \20{%s}\21 {%d}", item_names[i], LocationName(PASSVEC3(point->s.v.origin)), client->tp.enemy_count), sizeof(buffer)); break; } } if (i >= (sizeof(item_flags) / sizeof(item_flags[0]))) { return; } } TeamplayMM2(client, buffer); } static void TeamplayBasicCommand(gedict_t *client, char *text) { char buffer[128]; buffer[0] = '\0'; if (HAVE_POWERUP(client)) { strlcpy(buffer, PowerupText(client), sizeof(buffer)); strlcat(buffer, " ", sizeof(buffer)); } strlcat(buffer, text, sizeof(buffer)); strlcat(buffer, " \20{", sizeof(buffer)); strlcat(buffer, LocationName(PASSVEC3(client->s.v.origin)), sizeof(buffer)); strlcat(buffer, "}\21", sizeof(buffer)); TeamplayMM2(client, buffer); } #define TEAMPLAY_BASIC(FunctionName, Text) static void FunctionName(gedict_t* client) { TeamplayBasicCommand(client, Text); } // Cmd_AddCommand ("tp_msgyesok", TP_Msg_YesOk_f); TEAMPLAY_BASIC(TeamplayYesOk, "{yes/ok}") // Cmd_AddCommand ("tp_msgnocancel", TP_Msg_NoCancel_f); TEAMPLAY_BASIC(TeamplayNoCancel, "{&cf00no/cancel&cfff}") // Cmd_AddCommand ("tp_msgitemsoon", TP_Msg_ItemSoon_f); TEAMPLAY_BASIC(TeamplayItemSoon, "item soon") // Cmd_AddCommand ("tp_msgwaiting", TP_Msg_Waiting_f); TEAMPLAY_BASIC(TeamplayWaiting, "waiting") // Cmd_AddCommand ("tp_msgslipped", TP_Msg_Slipped_f); TEAMPLAY_BASIC(TeamplaySlipped, "enemy slipped") // Cmd_AddCommand ("tp_msgreplace", TP_Msg_Replace_f); TEAMPLAY_BASIC(TeamplayReplace, "replace") // Cmd_AddCommand ("tp_msgtrick", TP_Msg_Trick_f); TEAMPLAY_BASIC(TeamplayTrick, "trick") // Cmd_AddCommand ("tp_msgcoming", TP_Msg_Coming_f); TEAMPLAY_BASIC(TeamplayComing, "coming") void TeamplayDeathEvent(gedict_t *client) { VectorCopy(client->s.v.origin, client->tp.death_location); client->tp.death_items = (int)client->s.v.items; client->tp.death_weapon = (int)client->s.v.weapon; client->tp.death_time = g_globalvars.time; } // Cmd_AddCommand ("tp_msgpoint", TP_Msg_Point_f); typedef struct location_node_s { vec3_t point; char name[64]; } location_node_t; typedef struct locmacro_s { char *name; char *value; } locmacro_t; static locmacro_t locmacros[] = { { "ssg", "ssg" }, { "ng", "ng" }, { "sng", "sng" }, { "gl", "gl" }, { "rl", "rl" }, { "lg", "lg" }, { "separator", "-" }, { "ga", "ga" }, { "ya", "ya" }, { "ra", "ra" }, { "quad", "quad" }, { "pent", "pent" }, { "ring", "ring" }, { "suit", "suit" }, { "mh", "mega" }, }; static int node_count = 0; static location_node_t nodes[256]; char* LocationName(float x, float y, float z) { int i = 0; int best = -1; float best_distance = 0.0f; vec3_t point; VectorSet(point, x, y, z); for (i = 0; i < node_count; ++i) { float distance = VectorDistance(point, nodes[i].point); if ((best < 0) || (distance < best_distance)) { best = i; best_distance = distance; } } if (best < 0) { return TP_NAME_SOMEPLACE; } return nodes[best].name; } void LocationInitialise(void) { fileHandle_t file = -1; char *entityFile = cvar_string("k_entityfile"); char lineData[128]; char argument[128]; if (!strnull(entityFile)) { file = std_fropen("locs/%s.loc", entityFile); } if (file == -1) { file = std_fropen("locs/%s.loc", mapname); } if (file == -1) { G_Printf("Couldn't load %s.loc\n", mapname); return; } while (std_fgets(file, lineData, sizeof(lineData))) { char x[16], y[16], z[16]; char *name; int i = 0; name = nodes[node_count].name; trap_CmdTokenize(lineData); trap_CmdArgv(0, x, sizeof(x)); trap_CmdArgv(1, y, sizeof(y)); trap_CmdArgv(2, z, sizeof(z)); VectorSet(nodes[node_count].point, atof(x) / 8, atof(y) / 8, atof(z) / 8); name[0] = '\0'; for (i = 3; i < trap_CmdArgc(); ++i) { trap_CmdArgv(i, argument, sizeof(argument)); if (i > 3) { strlcat(name, " ", sizeof(nodes[node_count].name)); } strlcat(name, argument, sizeof(nodes[node_count].name)); } // Replace tokens (don't allow customisation) for (i = 0; i < (int)strlen(name); ++i) { if (!strncmp(name + i, "$loc_name_", 10)) { char *stub = name + i + 10; int j; qbool found = false; for (j = 0; j < sizeof(locmacros) / sizeof(locmacros[0]); ++j) { if (!strncmp(stub, locmacros[j].name, strlen(locmacros[j].name))) { int old_length = 10 + strlen(locmacros[j].name); int new_length = strlen(locmacros[j].value); if (new_length < old_length) { memmove(name + i, locmacros[j].value, new_length); memmove(name + i + new_length, name + i + old_length, strlen(name + i + old_length) + 1); found = true; --i; } break; } } if (!found) { i += 10; } } } ++node_count; if (node_count >= (sizeof(nodes) / sizeof(nodes[0]))) { break; } } G_Printf("Loaded %d locations\n", node_count); std_fclose(file); } typedef struct teamplay_message_s { char *cmdname; char *description; void (*function)(gedict_t *client); } teamplay_message_t; static teamplay_message_t messages[] = { { "yesok", "yes/ok", TeamplayYesOk }, { "nocancel", "no/cancel", TeamplayNoCancel }, { "soon", "item soon", TeamplayItemSoon }, { "waiting", "waiting", TeamplayWaiting }, { "slipped", "enemy slipped", TeamplaySlipped }, { "replace", "replace me", TeamplayReplace }, { "trick", "trick", TeamplayTrick }, { "coming", "coming", TeamplayComing }, { "getquad", "get quad", TeamplayGetQuad }, { "getpent", "get pent", TeamplayGetPent }, { "quaddead", "quad dead", TeamplayQuadDead }, { "enemypwr", "enemy powerup", TeamplayEnemyPowerup }, { "youtake", "you take", TeamplayYouTake }, { "kill me", "kill me", TeamplayKillMe }, { "lost", "area lost", TeamplayAreaLost }, { "secure", "area secure", TeamplayAreaSecure }, { "help", "area needs help", TeamplayAreaHelp }, { "need", "report needs", TeamplayReportNeeds }, { "report", "report status", TeamplayReportPersonalStatus }, { "took", "item taken", TeamplayReportTaken }, { "point", "player/item point", TeamplayPoint } }; qbool TeamplayMessageByName(gedict_t *client, const char *message) { int i; for (i = 0; i < (sizeof(messages) / sizeof(messages[0])); ++i) { if (streq(messages[i].cmdname, message)) { messages[i].function(client); return true; } } return false; } void TeamplayMessage(void) { int i, max_len = 0; char dots[64]; if (trap_CmdArgc() == 2) { char argument[32]; trap_CmdArgv(1, argument, sizeof(argument)); if (TeamplayMessageByName(self, argument)) { return; } } // Print usage for (i = 0; i < (sizeof(messages) / sizeof(messages[0])); ++i) { max_len = max(max_len, strlen(messages[i].cmdname)); } max_len += 2; G_sprint(self, 2, "Usage:\n"); for (i = 0; i < (sizeof(messages) / sizeof(messages[0])); ++i) { make_dots(dots, sizeof(dots), max_len, messages[i].cmdname); G_sprint(self, 2, " &cff0%s&r %s %s\n", messages[i].cmdname, dots, messages[i].description); } } qbool SameTeam(gedict_t *p1, gedict_t *p2) { return ((p1 == p2) || (teamplay && streq(ezinfokey(p1, "team"), ezinfokey(p2, "team")))); } QW-Group-ktx-d05d6ca/src/triggers.c000066400000000000000000000661741475442401000172270ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" gedict_t *stemp, *otemp, *old; qbool BotsPreTeleport(gedict_t *self, gedict_t *other); void BotsPostTeleport(gedict_t *self, gedict_t *other, gedict_t *teleport_destination); void trigger_reactivate(void) { self->s.v.solid = SOLID_TRIGGER; } //============================================================================= #define SPAWNFLAG_NOMESSAGE 1 #define SPAWNFLAG_NOTOUCH 1 // the wait g_globalvars.time has passed, so set back up for another activation void multi_wait(void) { if (self->s.v.max_health) { self->s.v.health = self->s.v.max_health; self->s.v.takedamage = DAMAGE_YES; self->s.v.solid = SOLID_BBOX; } } // the trigger was just touched/killed/used // self->s.v.enemy should be set to the activator so it can be held through a delay // so wait for the delay g_globalvars.time before firing void multi_trigger(void) { if (self->s.v.nextthink > g_globalvars.time) { return; // allready been triggered } if (streq(self->classname, "trigger_secret")) { if (PROG_TO_EDICT(self->s.v.enemy)->ct != ctPlayer) { return; } g_globalvars.found_secrets = g_globalvars.found_secrets + 1; WriteByte( MSG_ALL, SVC_FOUNDSECRET); } if (self->noise) { sound(self, CHAN_VOICE, self->noise, 1, ATTN_NORM); } // don't trigger again until reset self->s.v.takedamage = DAMAGE_NO; activator = PROG_TO_EDICT(self->s.v.enemy); SUB_UseTargets(); if (self->wait > 0) { self->think = (func_t) multi_wait; self->s.v.nextthink = g_globalvars.time + self->wait; } else { // we can't just ent_remove(self) here, because this is a touch function // called wheil C code is looping through area links... self->touch = (func_t) SUB_Null; self->s.v.nextthink = g_globalvars.time + 0.1; self->think = (func_t) SUB_Remove; } } void multi_killed(void) { self->s.v.enemy = EDICT_TO_PROG(damage_attacker); multi_trigger(); } void multi_use(void) { self->s.v.enemy = EDICT_TO_PROG(activator); multi_trigger(); } void multi_touch(void) { // #practice mode# if (!k_practice && (match_in_progress != 2)) { return; } if (!other->classname) { return; } if (other->ct != ctPlayer) { return; } // if the trigger has an angles field, check player's facing direction if ((self->s.v.movedir[0] != 0) && (self->s.v.movedir[1] != 0) && (self->s.v.movedir[2] != 0)) { trap_makevectors(other->s.v.angles); if (DotProduct(g_globalvars.v_forward, self->s.v.movedir) < 0) { return; // not facing the right way } } self->s.v.enemy = EDICT_TO_PROG(other); multi_trigger(); } /*QUAKED trigger_multiple (.5 .5 .5) ? notouch Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each g_globalvars.time. If "delay" is set, the trigger waits some time after activating before firing. "wait" : Seconds between triggerings. (.2 default) If notouch is set, the trigger is only fired by other entities, not by touching. NOTOUCH has been obsoleted by trigger_relay! sounds 1) secret 2) beep beep 3) large switch 4) set "message" to text string */ void SP_trigger_multiple(void) { if (self->s.v.sounds == 1) { trap_precache_sound("misc/secret.wav"); self->noise = "misc/secret.wav"; } else if (self->s.v.sounds == 2) { trap_precache_sound("misc/talk.wav"); self->noise = "misc/talk.wav"; } else if (self->s.v.sounds == 3) { trap_precache_sound("misc/trigger1.wav"); self->noise = "misc/trigger1.wav"; } if (!self->wait) { self->wait = 0.2; } self->use = (func_t) multi_use; InitTrigger(); if (ISLIVE(self)) { if ((int)(self->s.v.spawnflags) & SPAWNFLAG_NOTOUCH) { G_Error("health and notouch don't make sense\n"); } self->s.v.max_health = self->s.v.health; self->th_die = multi_killed; self->s.v.takedamage = DAMAGE_YES; self->s.v.solid = SOLID_BBOX; setorigin(self, PASSVEC3(self->s.v.origin)); // make sure it links into the world } else { if (!((int)(self->s.v.spawnflags) & SPAWNFLAG_NOTOUCH)) { self->touch = (func_t) multi_touch; } } } /*QUAKED trigger_once (.5 .5 .5) ? notouch Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching "targetname". If "health" is set, the trigger must be killed to activate. If notouch is set, the trigger is only fired by other entities, not by touching. if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired. if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0. sounds 1) secret 2) beep beep 3) large switch 4) set "message" to text string */ void SP_trigger_once(void) { self->wait = -1; SP_trigger_multiple(); } //============================================================================= /*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. It can contain killtargets, targets, delays, and messages. */ void SP_trigger_relay(void) { self->use = (func_t) SUB_UseTargets; } //============================================================================= /*QUAKED trigger_secret (.5 .5 .5) ? secret counter trigger sounds 1) secret 2) beep beep 3) 4) set "message" to text string */ void SP_trigger_secret(void) { g_globalvars.total_secrets = g_globalvars.total_secrets + 1; self->wait = -1; if (!self->s.v.sounds) { self->s.v.sounds = 1; } if (self->s.v.sounds == 1) { trap_precache_sound("misc/secret.wav"); self->noise = "misc/secret.wav"; } else if (self->s.v.sounds == 2) { trap_precache_sound("misc/talk.wav"); self->noise = "misc/talk.wav"; } SP_trigger_multiple(); } //============================================================================= void counter_use(void) { // char* junk; self->count = self->count - 1; if (self->count < 0) { return; } if (self->count != 0) { if (activator->ct == ctPlayer && ((int)(self->s.v.spawnflags) & SPAWNFLAG_NOMESSAGE) == 0) { if (self->count >= 4) { G_centerprint(activator, "There are more to go..."); } else if (self->count == 3) { G_centerprint(activator, "Only 3 more to go..."); } else if (self->count == 2) { G_centerprint(activator, "Only 2 more to go..."); } else { G_centerprint(activator, "Only 1 more to go..."); } } return; } if ((activator->ct == ctPlayer) && (((int)(self->s.v.spawnflags) & SPAWNFLAG_NOMESSAGE) == 0)) { G_centerprint(activator, "Sequence completed!"); } self->s.v.enemy = EDICT_TO_PROG(activator); multi_trigger(); } /*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" g_globalvars.times (default 2), it will fire all of it's targets and remove itself. */ void SP_trigger_counter(void) { self->wait = -1; if (!self->count) { self->count = 2; } self->use = (func_t) counter_use; } /* ============================================================================== TELEPORT TRIGGERS ============================================================================== */ #define PLAYER_ONLY 1 #define SILENT 2 // changed the function for rapid sound so sndspot parameter included void play_teleport(gedict_t *sndspot) { float v; char *tmpstr; v = g_random() * 5; if (v < 1) { tmpstr = "misc/r_tele1.wav"; } else if (v < 2) { tmpstr = "misc/r_tele2.wav"; } else if (v < 3) { tmpstr = "misc/r_tele3.wav"; } else if (v < 4) { tmpstr = "misc/r_tele4.wav"; } else { tmpstr = "misc/r_tele5.wav"; } sound(sndspot, CHAN_VOICE, tmpstr, 1, ATTN_NORM); } void spawn_tfog(vec3_t org) { // qqshka: no need for this // { // gedict_t *s = spawn(); // VectorCopy( org, s->s.v.origin );// s->s.v.origin = org; // s->s.v.nextthink = g_globalvars.time + 0.2; // s->think = ( func_t ) SUB_Remove; // } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_TELEPORT); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); trap_multicast(PASSVEC3(org), MULTICAST_PHS); } /* void tdeath_touch(void) { gedict_t *other2; // { ktpro way to reduce double telefrags if ( other->tdeath_time > self->tdeath_time ) return; // this mean we go through tele after some guy, so we must not be telefragged // } other2 = PROG_TO_EDICT(self->s.v.owner); if ( other == other2 ) return; if ( ISDEAD( other ) ) return; // frag anyone who teleports in on top of an invincible player if ( other->ct == ctPlayer ) { // check if both players have invincible if ( other->invincible_finished > g_globalvars.time && other2->invincible_finished > g_globalvars.time ) { // remove invincible for both players other->invincible_finished = other2->invincible_finished = 0; // probably this must kill both players other2->deathtype = other->deathtype = dtTELE3; T_Damage( other, self, other2, 50000 ); T_Damage( other2, self, other, 50000 ); return; } // mortal trying telefrag someone who has 666 if ( other->invincible_finished > g_globalvars.time ) { other2->deathtype = dtTELE2; T_Damage( other2, self, other, 50000 ); return; } } if ( ISLIVE( other ) ) { other->deathtype = dtTELE1; T_Damage( other, self, other2, 50000 ); } } */ // { NOTE: retarded code, just so monsters able double telefrag each other, for example "e1m7" void tdeath_touch(void) { gedict_t *other2; // should not be used against players if (other->ct == ctPlayer) { return; } if (ISDEAD(other)) { return; } // { ktpro way to reduce double telefrags if (other->tdeath_time > self->tdeath_time) { return; // this mean we go through tele after some guy, so we must not be telefragged } // } other2 = PROG_TO_EDICT(self->s.v.owner); if (other == other2) { return; } other->deathtype = dtTELE1; T_Damage(other, self, other2, 50000); } void spawn_tdeath(vec3_t org, gedict_t *death_owner) { gedict_t *death; death = spawn(); death->classname = "teledeath"; death->s.v.movetype = MOVETYPE_NONE; death->s.v.solid = SOLID_TRIGGER; SetVector(death->s.v.angles, 0, 0, 0); setsize(death, death_owner->s.v.mins[0] - 1, death_owner->s.v.mins[1] - 1, death_owner->s.v.mins[2] - 1, death_owner->s.v.maxs[0] + 1, death_owner->s.v.maxs[1] + 1, death_owner->s.v.maxs[2] + 1); setorigin(death, PASSVEC3(org)); death->touch = (func_t) tdeath_touch; // fixes the telefrag bug from previous kteams death->s.v.nextthink = g_globalvars.time + 0.1; death->think = (func_t) SUB_Remove; death->s.v.owner = EDICT_TO_PROG(death_owner); // { ktpro way to reduce double telefrags death_owner->tdeath_time = death->tdeath_time = g_globalvars.time; // } g_globalvars.force_retouch = 2; // make sure even still objects get hit } // } void teleport_player(gedict_t *player, vec3_t origin, vec3_t angles, int flags) { qbool dm = deathmatch; gedict_t *p, *p2; deathType_t dt = dtNONE; // protect(in some case) player from be spawnfragged for some time player->k_1spawn = g_globalvars.time + 0.78; // put a tfog where the player was and play teleporter sound // For some odd reason (latency?), no matter if the sound was issued to play // at the spot of the entity before it entered the teleporter, it actually // plays at the teleporter destination. So we just create a body double of the // player at the departure side which stands still, plays the sound and lives // for 1/10 of a second, then is removed. All these efforts were needed to get // rid of that annoying 2/10 second delay in playing the teleporter sound. // play sound where the player was if (flags & TFLAGS_SND_SRC) { gedict_t *othercopy = spawn(); setorigin(othercopy, PASSVEC3(player->s.v.origin)); othercopy->s.v.nextthink = g_globalvars.time + 0.1; othercopy->think = (func_t) SUB_Remove; play_teleport(othercopy); } //put a tfog where the player was if (flags & TFLAGS_FOG_SRC) { spawn_tfog(player->s.v.origin); } trap_makevectors(angles); // spawn a tfog flash in front of the destination if (flags & TFLAGS_FOG_DST) { vec3_t fog_org; VectorMA(origin, (flags & TFLAGS_FOG_DST_SPAWN) ? 20 : 32, g_globalvars.v_forward, fog_org); spawn_tfog(fog_org); } setorigin(player, PASSVEC3(origin)); // play sound at destination if (flags & TFLAGS_SND_DST) { play_teleport(player); } VectorCopy(angles, player->s.v.angles); // player.angles = angles; if (player->ct == ctPlayer) { if ((player->s.v.weapon == IT_HOOK) && player->hook_out) { GrappleReset(player->hook); player->attack_finished = g_globalvars.time + 0.25; } player->s.v.fixangle = 1; // turn this way immediately // qqshka|Tara, teleport_time these days is used by waterjump code // player->s.v.teleport_time = g_globalvars.time + 0.7; if (flags & TFLAGS_VELOCITY_ADJUST) { // Yawnmode: preserve velocity, I'm copying my own mod's code since i found it interesting to play with // - Molgrum if (k_yawnmode) { float vel; // Scale the original speed like airstep does player->s.v.velocity[2] = 0; vel = vlen(player->s.v.velocity) * (1.0 - k_teleport_cap / 100.0); // Only preserve speed above 300 vel = max(300, vel); VectorScale(g_globalvars.v_forward, vel, player->s.v.velocity); } else { // player->s.v.velocity = v_forward * 300; VectorScale(g_globalvars.v_forward, 300, player->s.v.velocity); } } } player->s.v.flags -= (int)player->s.v.flags & FL_ONGROUND; // perform telefragging code // { NOTE: retarded code, just so monsters able double telefrag each other, for example "e1m7" if (player->ct != ctPlayer) { spawn_tdeath(player->s.v.origin, player); } // } p2 = NULL; // If 'deathmatch' then use fast find_plr(), if non dm then more slow nextent(). // Since 'deathmatch' variable is global and may be changed during next 'for' we use local var 'dm' instead. for (p = world; (p = (dm ? find_plr(p) : nextent(p)));) { if (p == player) { continue; // ignore self } if (ISDEAD(p)) { continue; // alredy dead } if (p->s.v.solid != SOLID_SLIDEBOX) { continue; // not a monster or player } if ((player->s.v.absmin[0] > p->s.v.absmax[0]) || (player->s.v.absmin[1] > p->s.v.absmax[1]) || (player->s.v.absmin[2] > p->s.v.absmax[2]) || (player->s.v.absmax[0] < p->s.v.absmin[0]) || (player->s.v.absmax[1] < p->s.v.absmin[1]) || (player->s.v.absmax[2] < p->s.v.absmin[2])) { /* G_bprint(2, "%s do not intersects\n", p->netname); G_bprint(2, "%.1f %.1f\n", player->s.v.absmin[0] , p->s.v.absmax[0]); G_bprint(2, "%.1f %.1f\n", player->s.v.absmin[1] , p->s.v.absmax[1]); G_bprint(2, "%.1f %.1f\n", player->s.v.absmin[2] , p->s.v.absmax[2]); G_bprint(2, "%.1f %.1f\n", player->s.v.absmax[0] , p->s.v.absmin[0]); G_bprint(2, "%.1f %.1f\n", player->s.v.absmax[1] , p->s.v.absmin[1]); G_bprint(2, "%.1f %.1f\n", player->s.v.absmax[2] , p->s.v.absmin[2]); */ continue; // bboxes not intersects } // G_bprint(2, "%s intersects\n", p->netname); // frag anyone who teleports in on top of an invincible player if (p->ct == ctPlayer) { if (p->invincible_finished > g_globalvars.time) { if (player->invincible_finished > g_globalvars.time) { // both players have invincible p->invincible_finished = 0; // remove invincible p->deathtype = dt = dtTELE3; p2 = p; // remember T_Damage(p, player, player, 50000); continue; } else { // mortal trying telefrag someone who has 666, gib mortal instead dt = dtTELE2; p2 = p; // remember continue; } } } if (ISLIVE(p)) { p->deathtype = dtTELE1; T_Damage(p, player, player, 50000); } } if (p2 && dt != dtNONE) { // gib self player->invincible_finished = 0; // remove invincible player->deathtype = dt; T_Damage(player, p2, p2, 50000); } } void teleport_touch(void) { gedict_t *t; if (self->targetname) { if (self->s.v.nextthink < g_globalvars.time) { return; // not fired yet } } if ((int)(self->s.v.spawnflags) & PLAYER_ONLY) { if (other->ct != ctPlayer) { return; } } // only teleport living creatures if (ISDEAD(other) || (!isRACE() && (other->s.v.solid != SOLID_SLIDEBOX))) { return; } if (isRA() && !isWinner(other) && !isLoser(other)) { return; } if (isRACE() && race_handle_event(other, self, "touch")) { return; } // activator = other; SUB_UseTargets(); t = find(world, FOFS(targetname), self->target); if (!t) { // G_Error( "couldn't find target" ); return; } #ifdef BOT_SUPPORT if (bots_enabled() && BotsPreTeleport(self, other)) { return; } #endif if ((match_in_progress == 0) && !strnull(self->ktx_votemap)) { gedict_t *tele = self; self = other; VoteMapSpecific(tele->ktx_votemap); self = tele; } other->teleported = 1; teleport_player(other, t->s.v.origin, t->mangle, TFLAGS_FOG_SRC | TFLAGS_FOG_DST | TFLAGS_SND_SRC | TFLAGS_SND_DST | TFLAGS_VELOCITY_ADJUST); #ifdef BOT_SUPPORT if (bots_enabled()) { BotsPostTeleport(self, other, t); } #endif } /*QUAKED info_teleport_destination (.5 .5 .5) (-8 -8 -8) (8 8 32) This is the destination marker for a teleporter. It should have a "targetname" field with the same value as a teleporter's "target" field. */ void SP_info_teleport_destination(void) { // this does nothing, just serves as a target spot VectorCopy(self->s.v.angles, self->mangle); // self.mangle = self.angles; SetVector(self->s.v.angles, 0, 0, 0); self->model = ""; self->s.v.origin[2] += 27; if (!self->targetname) { G_Error("no targetname"); } } void teleport_use(void) { self->s.v.nextthink = g_globalvars.time + 0.2; g_globalvars.force_retouch = 2; // make sure even still objects get hit self->think = (func_t) SUB_Null; } /*QUAKED trigger_teleport (.5 .5 .5) ? PLAYER_ONLY SILENT Any object touching this will be transported to the corresponding info_teleport_destination gedict_t*. 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. */ void SP_trigger_teleport(void) { vec3_t o; InitTrigger(); self->touch = (func_t) teleport_touch; // find the destination if (!self->target) { G_Error("no target"); } self->use = (func_t) teleport_use; if (!((int)(self->s.v.spawnflags) & SILENT)) { trap_precache_sound("ambience/hum1.wav"); VectorAdd(self->s.v.mins, self->s.v.maxs, o); VectorScale(o, 0.5, o); //o = (self.mins + self.maxs)*0.5; trap_ambientsound(PASSVEC3(o), "ambience/hum1.wav", 0.5, ATTN_STATIC); } } void SP_trigger_custom_teleport(void) { // set real classname self->classname = "trigger_teleport"; // some size hack. setsize(self, -self->s.v.size[0], -self->s.v.size[1], -self->s.v.size[2], self->s.v.size[0], self->s.v.size[1], self->s.v.size[2]); // and call proper spawn function. SP_trigger_teleport(); // reset origin, well, you have to set origin each time you change solid type... setorigin(self, PASSVEC3(self->s.v.origin)); // G_cprint("SP_trigger_custom_teleport: size %.1f %.1f %.1f\n", PASSVEC3(self->s.v.size)); // G_cprint("SP_trigger_custom_teleport: org %.1f %.1f %.1f\n", PASSVEC3(self->s.v.origin)); } /* ============================================================================== trigger_setskill ============================================================================== */ void trigger_skill_touch(void) { if (other->ct != ctPlayer) { return; } cvar_set("skill", self->message); } /*QUAKED trigger_setskill (.5 .5 .5) ? sets skill level to the value of "message". Only used on start map. */ void SP_trigger_setskill(void) { if (deathmatch) { ent_remove(self); return; } if (!self->message) { self->message = ""; } InitTrigger(); self->touch = (func_t) trigger_skill_touch; } /* ============================================================================== ONLY REGISTERED TRIGGERS ============================================================================== */ void trigger_onlyregistered_touch(void) { if (other->ct != ctPlayer) { return; } if (self->attack_finished > g_globalvars.time) { return; } self->attack_finished = g_globalvars.time + 2; if (/*trap_cvar( "registered" )*/true) { self->message = ""; activator = other; SUB_UseTargets(); ent_remove(self); } else { if (self->message && strneq(self->message, "")) { G_centerprint(other, "%s", self->message); sound(other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM); } } } /*QUAKED trigger_onlyregistered (.5 .5 .5) ? Only fires if playing the registered version, otherwise prints the message */ void SP_trigger_onlyregistered(void) { trap_precache_sound("misc/talk.wav"); InitTrigger(); self->touch = (func_t) trigger_onlyregistered_touch; } //============================================================================ void hurt_on(void) { self->s.v.solid = SOLID_TRIGGER; self->s.v.nextthink = -1; setorigin(self, PASSVEC3(self->s.v.origin)); // it matter g_globalvars.force_retouch = 2; // make sure even still objects get hit } void hurt_items(void) { if (cvar("k_ctf_hurt_items")) { if (streq(other->classname, "item_flag_team1") || streq(other->classname, "item_flag_team2")) { // Cause flag to return to spawn position. other->super_time = g_globalvars.time; } else if (streq(other->classname, "rune")) { // Cause rune to respawn. other->s.v.nextthink = g_globalvars.time; } } } void hurt_touch(void) { if (!other->s.v.takedamage) { hurt_items(); return; } self->s.v.solid = SOLID_NOT; other->deathtype = dtTRIGGER_HURT; T_Damage(other, self, self, self->dmg); self->think = (func_t) hurt_on; self->s.v.nextthink = g_globalvars.time + 1; } /*QUAKED trigger_hurt (.5 .5 .5) ? Any object touching this will be hurt set dmg to damage amount defalt dmg = 5 */ void SP_trigger_hurt(void) { if (streq("end", mapname) && cvar("k_remove_end_hurt")) { soft_ent_remove(self); return; } InitTrigger(); self->touch = (func_t) hurt_touch; if (!self->dmg) { self->dmg = 5; } } //============================================================================ #define PUSH_ONCE 1 void trigger_push_touch(void) { if (streq(other->classname, "grenade")) { other->s.v.velocity[0] = self->speed * self->s.v.movedir[0] * 10; other->s.v.velocity[1] = self->speed * self->s.v.movedir[1] * 10; other->s.v.velocity[2] = self->speed * self->s.v.movedir[2] * 10; } else if (ISLIVE(other)) { // other->s.v.velocity = self->speed * self->s.v.movedir * 10; other->s.v.velocity[0] = self->speed * self->s.v.movedir[0] * 10; other->s.v.velocity[1] = self->speed * self->s.v.movedir[1] * 10; other->s.v.velocity[2] = self->speed * self->s.v.movedir[2] * 10; if (other->ct == ctPlayer) { if (other->fly_sound < g_globalvars.time) { other->fly_sound = g_globalvars.time + 1.5; sound(other, CHAN_AUTO, "ambience/windfly.wav", 1, ATTN_NORM); } } } if ((int)(self->s.v.spawnflags) & PUSH_ONCE) { ent_remove(self); } } /*QUAKED trigger_push (.5 .5 .5) ? PUSH_ONCE Pushes the player */ void SP_trigger_push(void) { InitTrigger(); self->touch = (func_t) trigger_push_touch; if (!self->speed) { self->speed = 1000; } } void SP_trigger_custom_push(void) { // set real classname self->classname = "trigger_push"; // some size hack. setsize(self, -self->s.v.size[0], -self->s.v.size[1], -self->s.v.size[2], self->s.v.size[0], self->s.v.size[1], self->s.v.size[2]); // and call proper spawn function. SP_trigger_push(); // reset origin, well, you have to set origin each time you change solid type... setorigin(self, PASSVEC3(self->s.v.origin)); } //============================================================================ void trigger_monsterjump_touch(void) { if (((int)other->s.v.flags & (FL_MONSTER | FL_FLY | FL_SWIM)) != FL_MONSTER) { return; } // set XY even if not on ground, so the jump will clear lips other->s.v.velocity[0] = self->s.v.movedir[0] * self->speed; other->s.v.velocity[1] = self->s.v.movedir[1] * self->speed; if (!((int)other->s.v.flags & FL_ONGROUND)) { return; } other->s.v.flags = other->s.v.flags - FL_ONGROUND; other->s.v.velocity[2] = self->height; } /*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 SP_trigger_monsterjump(void) { if (!self->speed) { self->speed = 200; } if (!self->height) { self->height = 200; } if ((self->s.v.angles[0] == 0) && (self->s.v.angles[1] == 0) && (self->s.v.angles[2] == 0)) { SetVector(self->s.v.angles, 0, 360, 0); } InitTrigger(); self->touch = (func_t) trigger_monsterjump_touch; } void SP_trigger_custom_monsterjump(void) { // set real classname self->classname = "trigger_monsterjump"; // some size hack. setsize(self, -self->s.v.size[0], -self->s.v.size[1], -self->s.v.size[2], self->s.v.size[0], self->s.v.size[1], self->s.v.size[2]); // and call proper spawn function. SP_trigger_monsterjump(); // reset origin, well, you have to set origin each time you change solid type... setorigin(self, PASSVEC3(self->s.v.origin)); } float T_Heal(gedict_t *e, float healamount, float ignore); static void trigger_heal_touch(void) { if ((match_in_progress == 1) || (!match_in_progress && cvar("k_freeze"))) { return; } if (!streq(other->classname, "player") || ISDEAD(other)) { return; } if (other->healtimer > g_globalvars.time) { return; } if (other->s.v.takedamage && (other->s.v.health < self->healmax)) { sound (self, CHAN_AUTO, self->noise, 1, ATTN_NORM); if ((other->s.v.health + self->healamount) > self->healmax) { T_Heal (other, (self->healmax - other->s.v.health), 1); } else { T_Heal (other, self->healamount, 1); } other->healtimer = g_globalvars.time + self->wait; } } void SP_trigger_heal(void) { if (strnull(self->noise)) self->noise = "items/r_item1.wav"; trap_precache_sound (self->noise); InitTrigger (); if (self->wait == 0) { self->wait = 1; } if (self->healamount == 0) { self->healamount = 5; } if (self->healmax == 0) { self->healmax = 100; } else if (self->healmax > 250) { self->healmax = 250; } self->healtimer = g_globalvars.time; self->touch = (func_t) trigger_heal_touch; } QW-Group-ktx-d05d6ca/src/vip.c000066400000000000000000000032321475442401000161610ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // vip.c // qqshka: // put here some vip stuff %) #include "g_local.h" // get vip bit flags of client, if any int VIP(gedict_t *cl) { return 0; //atoi(infokey(cl, "*VIP", vip, sizeof(vip))); } // check if client have ALL bit 'flags' int VIP_IsFlags(gedict_t *cl, int flags) { return ((VIP(cl) & flags) == flags); } void VIP_ShowRights(gedict_t *cl) { int flags = VIP(cl); char *rights = ""; if (!flags) { return; } if (flags & VIP_NORMAL) { flags &= ~VIP_NORMAL; rights = va("%s normal", rights); } if (flags & VIP_NOTKICKABLE) { flags &= ~VIP_NOTKICKABLE; rights = va("%s not_kick", rights); } if (flags & VIP_ADMIN) { flags &= ~VIP_ADMIN; rights = va("%s admin", rights); } if (flags & VIP_RCON) { flags &= ~VIP_RCON; rights = va("%s rcon_adm", rights); } if (strnull(rights) || flags) { rights = va("%s UNKNOWN", rights); } G_sprint(cl, 2, "You are a VIP with rights:%s\n", rights); } QW-Group-ktx-d05d6ca/src/vote.c000066400000000000000000000732051475442401000163470ustar00rootroot00000000000000/* * 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 * * * $Id$ */ // vote.c: election functions by rc\sturm #include "g_local.h" #define MAX_PLAYERCOUNT_RPICKUP 32 // These are the built-in teams for rpickup to choose from rpickupTeams_t builtinTeamInfo[] = { {"red", "4", "4", "color 4 4\nskin \"\"\nteam red\n"}, {"blue", "13", "13", "color 13 13\nskin \"\"\nteam blue\n"}, {"yell", "12", "12", "color 12 12\nskin \"\"\nteam yell\n"} }; //void BeginPicking(); void BecomeCaptain(gedict_t *p); void BecomeCoach(gedict_t *p); // AbortElect is used to terminate the voting // Important if player to be elected disconnects or levelchange happens void AbortElect(void) { gedict_t *p; for (p = world; (p = find_client(p));) { if (p->v.elect_type != etNone) { if (is_elected(p, etCaptain)) { k_captains = floor(k_captains); } if (is_elected(p, etCoach)) { k_coaches = floor(k_coaches); } p->v.elect_type = etNone; p->v.elect_block_till = g_globalvars.time + 30; // block election for some time } } vote_clear(OV_ELECT); // clear vote // Kill timeout checker entity for (p = world; (p = find(p, FOFCLSN, "electguard"));) { ent_remove(p); } } void ElectThink(void) { G_bprint(2, "The voting has timed out.\n" "Election aborted\n"); self->s.v.nextthink = -1; AbortElect(); } void VoteYes(void) { int votes; if (!get_votes(OV_ELECT)) { return; } if (self->v.elect_type != etNone) { G_sprint(self, 2, "You cannot vote for yourself\n"); return; } if (self->v.elect) { G_sprint(self, 2, "--- your vote is still good ---\n"); return; } // register the vote self->v.elect = 1; G_bprint(2, "%s gives %s vote\n", self->netname, g_his(self)); // calculate how many more votes are needed if ((votes = get_votes_req(OV_ELECT, true))) { G_bprint(2, "\x90%d\x91 more vote%s needed\n", votes, count_s(votes)); } vote_check_elect(); } void VoteNo(void) { int votes; // withdraw one's vote if (!get_votes(OV_ELECT) || (self->v.elect_type != etNone) || !self->v.elect) { return; } // unregister the vote self->v.elect = 0; G_bprint(2, "%s withdraws %s vote\n", self->netname, g_his(self)); // calculate how many more votes are needed if ((votes = get_votes_req(OV_ELECT, true))) { G_bprint(2, "\x90%d\x91 more vote%s needed\n", votes, count_s(votes)); } vote_check_elect(); } // get count of particular votes int get_votes(int fofs) { int votes = 0; gedict_t *p; for (p = world; (p = find_client(p));) { if (*(int*)((byte*)(&p->v) + fofs)) { votes++; } } return votes; } // get count of particular votes and filter by value int get_votes_by_value(int fofs, int value) { int votes = 0; gedict_t *p; for (p = world; (p = find_client(p));) { if (*((int*)(&(p->v) + fofs)) == value) { votes++; } } return votes; } int get_votes_req(int fofs, qbool diff) { float percent = 51; int votes, vt_req, idx, el_type; votes = get_votes(fofs); switch (fofs) { case OV_BREAK: percent = cvar(k_matchLess ? "k_vp_map" : "k_vp_break"); break; // in matchless mode there is no /break but /next_map so using "k_vp_map" case OV_PICKUP: percent = cvar("k_vp_pickup"); break; case OV_RPICKUP: case OV_SWAPALL: // don't need a dedicated 'swapall' percentage percent = cvar("k_vp_rpickup"); break; case OV_MAP: percent = cvar("k_vp_map"); idx = vote_get_maps(); if ((idx >= 0) && !strnull(GetMapName(maps_voted[idx].map_id))) { votes = maps_voted[idx].map_votes; } else { votes = 0; } break; case OV_ELECT: if ((el_type = get_elect_type()) == etAdmin) { percent = cvar("k_vp_admin"); break; } else if (el_type == etCaptain) { percent = cvar("k_vp_captain"); break; } else if (el_type == etCoach) { percent = cvar("k_vp_coach"); break; } else { percent = 100; break; // unknown/none election break; } break; case OV_NOSPECS: percent = cvar("k_vp_nospecs"); break; case OV_TEAMOVERLAY: percent = cvar("k_vp_teamoverlay"); break; case OV_COOP: percent = cvar("k_vp_coop"); break; case OV_HOOKSMOOTH: case OV_HOOKFAST: case OV_HOOKCLASSIC: percent = cvar("k_vp_hookstyle"); break; case OV_ANTILAG: percent = cvar("k_vp_antilag"); break; case OV_PRIVATE: percent = cvar("k_vp_privategame"); break; } percent = bound(0.51, bound(51, percent, 100) / 100, 1); // calc and bound percentage between 50% to 100% if (isRACE() && (fofs == OV_MAP)) { vt_req = race_count_votes_req(percent); } else if (isCA() && (fofs == OV_BREAK)) { // CA players who aren't playing in the current series can't vote to break vt_req = ceil(percent * (CA_count_ready_players() - CountBots())); } else { vt_req = ceil(percent * (CountPlayers() - CountBots())); } if (fofs == OV_ELECT) { vt_req = max(2, vt_req); // if election, at least 2 votes needed } else if ((fofs == OV_BREAK) && k_matchLess && (match_in_progress == 1)) { vt_req = max(2, vt_req); // at least 2 votes in this case } else if (fofs == OV_BREAK) { vt_req = max(1, vt_req); // at least 1 vote in any case } else if ((fofs == OV_RPICKUP) || (fofs == OV_SWAPALL)) { vt_req = max(3, vt_req); // at least 3 votes in this case } else if (fofs == OV_NOSPECS && cvar("_k_nospecs")) { vt_req = max(1, vt_req); // at least 1 vote in this case } else if (fofs == OV_NOSPECS) { vt_req = max(2, vt_req); // at least 2 votes in this case } else if (fofs == OV_TEAMOVERLAY) { vt_req = max(2, vt_req); // at least 2 votes in this case } else if (fofs == OV_COOP) { vt_req = max(1, vt_req); // at least 1 votes in this case } else if (fofs == OV_HOOKSMOOTH) { vt_req = max(1, vt_req); // at least 1 votes in this case } else if (fofs == OV_HOOKFAST) { vt_req = max(1, vt_req); // at least 1 votes in this case } else if (fofs == OV_HOOKCLASSIC) { vt_req = max(1, vt_req); // at least 1 votes in this case } else if (fofs == OV_ANTILAG) { vt_req = max(2, vt_req); // at least 2 votes in this case } else if (fofs == OV_PRIVATE) { vt_req = max(2, vt_req); // at least 2 votes in this case } if ((CountBots() > 0) && ((CountPlayers() - CountBots()) == 1) && (fofs != OV_PRIVATE) && (fofs != OV_ELECT)) { vt_req = 1; } if (diff) { return max(0, vt_req - votes); } return max(0, vt_req - CountBots()); } int is_admins_vote(int fofs) { int votes = 0; gedict_t *p; for (p = world; (p = find_client(p));) { if (*(int*)((byte*)(&p->v) + fofs) && is_adm(p)) { votes++; } } return votes; } void vote_clear(int fofs) { gedict_t *p; for (p = world; (p = find_client(p));) { *(int*)((byte*)(&p->v) + fofs) = 0; } } // return true if player invoke one of particular election qbool is_elected(gedict_t *p, electType_t et) { return (p->v.elect_type == et); } int get_elect_type(void) { gedict_t *p; for (p = world; (p = find_client(p));) { if (is_elected(p, etAdmin)) // elected admin { return etAdmin; } if (is_elected(p, etCaptain)) // elected captain { return etCaptain; } if (is_elected(p, etCoach)) // elected coach { return etCoach; } } return etNone; } char* get_elect_type_str(void) { switch (get_elect_type()) { case etNone: return "None"; case etCaptain: return "Captain"; case etCoach: return "Coach"; case etAdmin: return "Admin"; } return "Unknown"; } int maps_voted_idx; votemap_t maps_voted[MAX_CLIENTS]; // fill maps_voted[] with data, // return the index in maps_voted[] of most voted map // return -1 inf no votes at all or some failures // if admin votes for map - map will be treated as most voted int vote_get_maps(void) { int best_idx = -1, i; gedict_t *p; memset(maps_voted, 0, sizeof(maps_voted)); maps_voted_idx = -1; if (!get_votes(OV_MAP)) { return -1; // no one votes at all } for (p = world; (p = find_client(p));) { if (!p->v.map) { continue; // player is not voted } if (!race_allow_map_vote(p)) { continue; } for (i = 0; i < MAX_CLIENTS; i++) { if (!maps_voted[i].map_id) { break; // empty } if (maps_voted[i].map_id == p->v.map) { break; // already count votes for this map } } if (i >= MAX_CLIENTS) { continue; // heh, all slots is full, just for sanity } maps_voted[i].map_id = p->v.map; maps_voted[i].map_votes += 1; maps_voted[i].admins += (is_adm(p) ? 1 : 0); // find the most voted map if ((best_idx < 0) || (maps_voted[i].map_votes > maps_voted[best_idx].map_votes)) { best_idx = i; } // admin voted maps have priority if (maps_voted[i].admins > maps_voted[best_idx].admins) { best_idx = i; } } return (maps_voted_idx = best_idx); } void vote_check_map(void) { int vt_req; char *map; vt_req = get_votes_req(OV_MAP, true); if (maps_voted_idx < 0) { return; } map = GetMapName(maps_voted[maps_voted_idx].map_id); if (strnull(map)) { return; } if (!k_matchLess && match_in_progress) { return; } if (vt_req) { return; } G_bprint(2, "%s votes for mapchange.\n", redtext("Majority")); vote_clear(OV_MAP); changelevel(map); } void vote_check_break(void) { if (!match_in_progress || intermission_running || match_over) { return; } if (!get_votes_req(OV_BREAK, true)) { vote_clear(OV_BREAK); if (isHoonyModeAny()) { HM_match_break(); } G_bprint(2, "%s\n", redtext("Match stopped by majority vote")); EndMatch(0); } } void vote_check_elect(void) { gedict_t *p; if (!get_votes_req(OV_ELECT, true)) { for (p = world; (p = find_client(p));) { if (p->v.elect_type != etNone) { break; } } if (!p) { // nor admin nor captain nor coach found - probably bug AbortElect(); return; } if (!((p->ct == ctSpec) && match_in_progress)) { if (is_elected(p, etAdmin)) // s: election was admin election { BecomeAdmin(p, AF_ADMIN); } } if (!match_in_progress) { if (is_elected(p, etCaptain)) // s: election was captain election { BecomeCaptain(p); } } if (!match_in_progress) { if (is_elected(p, etCoach)) // s: election was coach election { BecomeCoach(p); } } AbortElect(); } } // !!! do not confuse rpickup and pickup void vote_check_pickup(void) { gedict_t *p; int veto; if (match_in_progress || k_captains) { return; } if (!get_votes(OV_PICKUP)) { return; } veto = is_admins_vote(OV_PICKUP); if (veto || !get_votes_req(OV_PICKUP, true)) { vote_clear(OV_PICKUP); if (veto) { G_bprint(2, "console: admin veto for pickup\n"); } else { G_bprint(2, "console: a pickup game it is then\n"); } for (p = world; (p = find_plr(p));) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "break\n" "color 0\n" "team \"\"\n" "skin base\n"); } } } // !!! do not confuse rpickup and pickup void vote_check_rpickup(int maxRecursion) { float frnd; int i, tn, pl_cnt, pl_idx; gedict_t *p; int veto; qbool needNewRpickup = true; // buffer reserved for 32 players (16on16). If more present, recursive auto-rpickup will not be activated int originalTeams[MAX_PLAYERCOUNT_RPICKUP]; if (match_in_progress || k_captains || k_coaches) { return; } if (!get_votes(OV_RPICKUP)) { return; } // Firstly obtain the number of players we have in total on server pl_cnt = CountPlayers(); if ((pl_cnt < 4) || (maxRecursion < 0)) { return; } veto = is_admins_vote(OV_RPICKUP); if (veto || !get_votes_req(OV_RPICKUP, true)) { // Save the original teams, and also clear them i = 0; for (p = world; (p = find_plr(p));) { if (i < MAX_PLAYERCOUNT_RPICKUP) { originalTeams[i++] = p->k_teamnumber; } p->k_teamnumber = 0; } for (tn = 1; pl_cnt > 0; pl_cnt--) { frnd = g_random(); // bound is macros - so u _can't_ put g_random inside bound pl_idx = bound(0, (int)(frnd * pl_cnt), pl_cnt - 1); // select random player between 0 and pl_cnt for (i = 0, p = world; (p = find_plr(p));) { if (p->k_teamnumber) { // This is a player that we already handled continue; } if (i == pl_idx) { p->k_teamnumber = tn; if ((current_umode >= um2on2on2) && (current_umode <= um4on4on4)) { // game modes with 3 teams ++tn; if (tn > 3) { tn = 1; } } else { tn = (tn == 1 ? 2 : 1); // next random player will be in other team } if (p->k_teamnumber == 1) { if (p->isBot) { trap_SetBotUserInfo(NUM_FOR_EDICT(p), "team", builtinTeamInfo[0].name, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "topcolor", builtinTeamInfo[0].topColor, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "bottomcolor", builtinTeamInfo[0].bottomColor, 0); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "%s", builtinTeamInfo[0].stuffCmd); } } else if (p->k_teamnumber == 2) { if (p->isBot) { trap_SetBotUserInfo(NUM_FOR_EDICT(p), "team", builtinTeamInfo[1].name, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "topcolor", builtinTeamInfo[1].topColor, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "bottomcolor", builtinTeamInfo[1].bottomColor, 0); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "%s", builtinTeamInfo[1].stuffCmd); } } else { if (p->isBot) { trap_SetBotUserInfo(NUM_FOR_EDICT(p), "team", builtinTeamInfo[2].name, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "topcolor", builtinTeamInfo[2].topColor, 0); trap_SetBotUserInfo(NUM_FOR_EDICT(p), "bottomcolor", builtinTeamInfo[2].bottomColor, 0); } else { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "%s", builtinTeamInfo[2].stuffCmd); } } break; } i++; } } if (veto) { G_bprint(2, "console: admin veto for %s\n", redtext("random pickup")); } else { G_bprint(2, "console: %s game it is then\n", redtext("random pickup")); } // check if rpickup really created new teams if (pl_cnt <= MAX_PLAYERCOUNT_RPICKUP) { for (p = world, i = 0; (p = find_plr(p)) && i < MAX_PLAYERCOUNT_RPICKUP && needNewRpickup; i++) { if (originalTeams[i] != p->k_teamnumber) { // there is a mismatch, meaning that at least 1 player gets a new team needNewRpickup = false; } } if (needNewRpickup) { G_bprint(2, "console: Team layout did not change. %s again (tries left: %d)\n", redtext("random pickup"), maxRecursion); vote_check_rpickup(maxRecursion - 1); } else { // we have a new team layout, let's clear the rpickup flag vote_clear(OV_RPICKUP); } } } } // { no specs feature void FixNoSpecs(void) { // turn off "no specs" mode if there no players left if ((g_globalvars.time > 10) && !match_in_progress && !CountPlayers() && cvar("_k_nospecs")) { G_bprint(2, "%s mode turned off\n", redtext("No spectators")); cvar_set("_k_nospecs", "0"); } } void vote_check_nospecs(void) { int veto; if (match_in_progress || intermission_running || match_over) { return; } if (!get_votes(OV_NOSPECS)) { return; } veto = is_admins_vote(OV_NOSPECS); if (veto || !get_votes_req(OV_NOSPECS, true)) { vote_clear(OV_NOSPECS); // set no specs mode cvar_fset("_k_nospecs", !cvar("_k_nospecs")); if (veto) { G_bprint( 2, "%s\n", redtext(va("No spectators mode %s by admin veto", OnOff(cvar("_k_nospecs"))))); } else { G_bprint( 2, "%s\n", redtext(va("No spectators mode %s by majority vote", OnOff(cvar("_k_nospecs"))))); } // kick specs if (cvar("_k_nospecs")) { gedict_t *spec; for (spec = world; (spec = find_spc(spec));) { if (VIP(spec) & ALLOWED_NOSPECS_VIPS) { continue; // don't kick this VIP } if (is_real_adm(spec)) { continue; // don't kick real admin } if (is_coach(spec)) { continue; // don't kick coaches } stuffcmd(spec, "disconnect\n"); // FIXME: stupid way } } } } void nospecs(void) { int votes; if (match_in_progress) { G_sprint(self, 2, "%s mode %s\n", redtext("No spectators"), OnOff(cvar("_k_nospecs"))); return; } // admin may turn this status alone on server... if (!is_adm(self)) { // Dont need to bother if less than 2 players if ((CountPlayers() < 2) && !cvar("_k_nospecs")) { G_sprint(self, 2, "You need at least 2 players to do this.\n"); return; } } self->v.nospecs = !self->v.nospecs; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.nospecs ? redtext(va("votes for nospecs %s", OnOff(!cvar("_k_nospecs")))) : redtext(va("withdraws %s nospecs vote", g_his(self)))), ((votes = get_votes_req(OV_NOSPECS, true)) ? va(" (%d)", votes) : "")); vote_check_nospecs(); } void vote_check_teamoverlay(void) { int veto; if (match_in_progress || intermission_running || match_over) { return; } if (!get_votes(OV_TEAMOVERLAY)) { return; } veto = is_admins_vote(OV_TEAMOVERLAY); if (veto || !get_votes_req(OV_TEAMOVERLAY, true)) { vote_clear(OV_TEAMOVERLAY); // Toggle teamoverlay. cvar_fset("k_teamoverlay", !cvar("k_teamoverlay")); if (veto) { G_bprint(2, "%s\n", redtext(va("Teamoverlay %s by admin veto", OnOff(cvar("k_teamoverlay"))))); } else { G_bprint( 2, "%s\n", redtext(va("Teamoverlay %s by majority vote", OnOff(cvar("k_teamoverlay"))))); } } } void teamoverlay(void) { int votes; if (match_in_progress) { G_sprint(self, 2, "%s %s\n", redtext("Teamoverlay"), OnOff(cvar("k_teamoverlay"))); return; } // admin may turn this status alone on server... if (!is_adm(self)) { // Dont need to bother if less than 2 players if (CountPlayers() < 2) { G_sprint(self, 2, "You need at least 2 players to do this.\n"); return; } } self->v.teamoverlay = !self->v.teamoverlay; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.teamoverlay ? redtext(va("votes for teamoverlay %s", OnOff(!cvar("k_teamoverlay")))) : redtext(va("withdraws %s teamoverlay vote", g_his(self)))), ((votes = get_votes_req(OV_TEAMOVERLAY, true)) ? va(" (%d)", votes) : "")); vote_check_teamoverlay(); } qbool force_map_reset = false; // { votecoop void vote_check_coop(void) { int veto; if ((deathmatch && match_in_progress) || intermission_running || match_over) { return; } if (!get_votes(OV_COOP)) { return; } veto = is_admins_vote(OV_COOP); if (veto || !get_votes_req(OV_COOP, true)) { vote_clear(OV_COOP); // toggle coop mode cvar_fset("coop", coop = !cvar("coop")); // set appropriate deathmatch cvar_fset("deathmatch", deathmatch = !coop); if (veto) { G_bprint(2, "%s\n", redtext(va("Coop mode %s by admin veto", OnOff(cvar("coop"))))); } else { G_bprint(2, "%s\n", redtext(va("Coop mode %s by majority vote", OnOff(cvar("coop"))))); } // and reload map if (coop && can_exec(va("configs/usermodes/matchless/%s.cfg", mapname))) { // Force the config to be executed force_map_reset = true; changelevel(mapname); } else if (cvar("k_bloodfest")) { changelevel(coop ? mapname : cvar_string("k_defmap")); } else { changelevel(coop ? "start" : mapname); } } } void votecoop(void) { int votes; if (deathmatch && match_in_progress) { G_sprint(self, 2, "Match in progress and deathmatch is non zero, you can't vote for coop\n"); return; } self->v.coop = !self->v.coop; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.coop ? redtext(va("votes for coop %s", OnOff(!cvar("coop")))) : redtext(va("withdraws %s coop vote", g_his(self)))), ((votes = get_votes_req(OV_COOP, true)) ? va(" (%d)", votes) : "")); vote_check_coop(); } // } // { votehook void hooksmooth(void) { int votes, veto; if (match_in_progress) { G_sprint(self, 2, "hook style can not be changed while match is in progress\n"); return; } if (!isCTF()) { G_sprint(self, 2, "hook style can only be set in CTF mode\n"); return; } if (intermission_running || match_over) { return; } self->v.hooksmooth = !self->v.hooksmooth; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.hooksmooth ? redtext("votes for smooth hook") : redtext(va("withdraws %s hookstyle vote", g_his(self)))), ((votes = get_votes_req(OV_HOOKSMOOTH, true)) ? va(" (%d)", votes) : "")); veto = is_admins_vote(OV_HOOKSMOOTH); if (veto || !get_votes_req(OV_HOOKSMOOTH, true)) { cvar_fset("k_ctf_hookstyle", 1); G_bprint(2, "%s\n", redtext(va("hook style set to smooth by %s", veto ? "admin veto" : "majority vote"))); vote_clear(OV_HOOKSMOOTH); } } void hookfast(void) { int votes, veto; if (match_in_progress) { G_sprint(self, 2, "hookstyle can not be changed while match is in progress\n"); return; } if (!isCTF()) { G_sprint(self, 2, "hookstyle can only be set in CTF mode\n"); return; } if (intermission_running || match_over) { return; } self->v.hookfast = !self->v.hookfast; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.hookfast ? redtext("votes for fast hook") : redtext(va("withdraws %s hookstyle vote", g_his(self)))), ((votes = get_votes_req(OV_HOOKFAST, true)) ? va(" (%d)", votes) : "")); veto = is_admins_vote(OV_HOOKFAST); if (veto || !get_votes_req(OV_HOOKFAST, true)) { cvar_fset("k_ctf_hookstyle", 2); G_bprint(2, "%s\n", redtext(va("hook style set to fast by %s", veto ? "admin veto" : "majority vote"))); vote_clear(OV_HOOKFAST); } } void hookclassic(void) { int votes, veto; if (match_in_progress) { G_sprint(self, 2, "hook style can not be changed while match is in progress\n"); return; } if (!isCTF()) { G_sprint(self, 2, "hook style can only be set in CTF mode\n"); return; } if (intermission_running || match_over) { return; } self->v.hookclassic = !self->v.hookclassic; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.hookclassic ? redtext("votes for classic hook") : redtext(va("withdraws %s hookstyle vote", g_his(self)))), ((votes = get_votes_req(OV_HOOKCLASSIC, true)) ? va(" (%d)", votes) : "")); veto = is_admins_vote(OV_HOOKCLASSIC); if (veto || !get_votes_req(OV_HOOKCLASSIC, true)) { cvar_fset("k_ctf_hookstyle", 3); G_bprint(2, "%s\n", redtext(va("hook style set to classic by %s", veto ? "admin veto" : "majority vote"))); vote_clear(OV_HOOKCLASSIC); return; } } void hookcrhook(void) { int votes, veto; if (match_in_progress) { G_sprint(self, 2, "hook style can not be changed while match is in progress\n"); return; } if (!isCTF()) { G_sprint(self, 2, "hook style can only be set in CTF mode\n"); return; } if (intermission_running || match_over) { return; } self->v.hookcrhook = !self->v.hookcrhook; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.hookcrhook ? redtext("votes for crhook") : redtext(va("withdraws %s hookstyle vote", g_his(self)))), ((votes = get_votes_req(OV_HOOKCRHOOK, true)) ? va(" (%d)", votes) : "")); veto = is_admins_vote(OV_HOOKCRHOOK); if (veto || !get_votes_req(OV_HOOKCRHOOK, true)) { cvar_fset("k_ctf_hookstyle", 4); G_bprint(2, "%s\n", redtext(va("hook style set to crhook by %s", veto ? "admin veto" : "majority vote"))); vote_clear(OV_HOOKCRHOOK); return; } } // } // { antilag vote feature void vote_check_antilag(void) { int veto; if (match_in_progress || intermission_running || match_over) { return; } if (!get_votes(OV_ANTILAG)) { return; } veto = is_admins_vote(OV_ANTILAG); if (veto || !get_votes_req(OV_ANTILAG, true)) { vote_clear(OV_ANTILAG); // toggle antilag mode. trap_cvar_set_float("sv_antilag", (float)(cvar("sv_antilag") ? 0 : 2)); if (veto) { G_bprint( 2, "%s\n", redtext(va("Antilag mode %s by admin veto", OnOff(2 == cvar("sv_antilag"))))); } else { G_bprint( 2, "%s\n", redtext(va("Antilag mode %s by majority vote", OnOff(2 == cvar("sv_antilag"))))); } } } void antilag(void) { int votes; if (match_in_progress) { G_sprint(self, 2, "%s mode %s\n", redtext("Antilag"), OnOff(2 == cvar("sv_antilag"))); return; } // admin may turn this status alone on server... if (!is_adm(self)) { // Dont need to bother if less than 2 players if (CountPlayers() < 2) { G_sprint(self, 2, "You need at least 2 players to do this.\n"); return; } } self->v.antilag = !self->v.antilag; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.antilag ? redtext(va("votes for antilag %s", OnOff(!(2 == cvar("sv_antilag"))))) : redtext(va("withdraws %s antilag vote", g_his(self)))), ((votes = get_votes_req(OV_ANTILAG, true)) ? va(" (%d)", votes) : "")); vote_check_antilag(); } // } // { private game functionality: players must login to ready up, simple vote to kick unauthed players void vote_check_privategame(void) { int veto; if (match_in_progress || intermission_running || match_over) { return; } if (!get_votes(OV_PRIVATE)) { return; } veto = is_admins_vote(OV_PRIVATE); if (veto || !get_votes_req(OV_PRIVATE, true)) { qbool enable = !is_private_game(); vote_clear(OV_PRIVATE); // toggle private game private_game_toggle(enable); if (veto) { G_bprint( 2, "%s\n", redtext(va("%s by admin veto", (is_private_game() ? "private game" : "public game")))); } else { G_bprint( 2, "%s\n", redtext(va("%s by majority vote", (is_private_game() ? "private game" : "public game")))); } } } void private_game_vote(void) { int votes; qbool enabled = is_private_game(); if (!private_game_voteable()) { G_sprint(self, 2, "%s not enabled on this server\n", redtext("Private game")); return; } if (match_in_progress) { G_sprint(self, 2, "%s mode %s\n", redtext("Private game"), OnOff(is_private_game())); return; } if (!enabled && !is_logged_in(self)) { G_sprint(self, 2, "You must log in to vote for private game\n"); return; } // admin may turn this status alone on server... if (!is_adm(self)) { // Dont need to bother if less than 2 players if (!enabled && CountPlayers() - CountBots() < 2) { G_sprint(self, 2, "You need at least 2 players to do this.\n"); return; } } self->v.privategame = !self->v.privategame; G_bprint( 2, "%s %s!%s\n", self->netname, (self->v.privategame ? redtext(va("votes for %s", enabled ? "public game" : "private game")) : redtext(va("withdraws %s %s game vote", g_his(self), enabled ? "public" : "private"))), ((votes = get_votes_req(OV_PRIVATE, true)) ? va(" (%d)", votes) : "")); vote_check_privategame(); } void private_game_toggle(qbool enable) { qbool allow_spectators = cvar("k_privategame_allow_specs"); qbool force_reconnect = cvar("k_privategame_force_reconnect"); int private_login = allow_spectators ? 1 : 2; // sv_login 1 => players only, sv_login 2 => everyone cvar_fset("k_privategame", enable ? 1 : 0); cvar_fset("sv_login", enable ? private_login : 0); // Assuming here that if server admin said they were voteable, server is public by default if (enable && match_in_progress < 2) { gedict_t *p; // Kick spectators if (!allow_spectators) { for (p = world; (p = find_spc(p));) { G_sprint(p, PRINT_HIGH, "Please reconnect & login\n"); stuffcmd(p, "disconnect\n"); // FIXME: stupid way } } // Only logged in players can play for (p = world; (p = find_plr(p));) { if (!p->isBot && p->ready && !is_logged_in(p)) { p->ready = 0; G_bprint(PRINT_HIGH, "%s is no longer ready\n", p->netname); } if (force_reconnect && !is_logged_in(p)) { if (allow_spectators) { // If this is disabled then they'll essentially get kicked when map changes anyway G_sprint(p, PRINT_HIGH, "You must login to play.\n"); do_force_spec(p, NULL, true); } else { G_sprint(p, PRINT_HIGH, "Please reconnect & login\n"); stuffcmd(p, "disconnect\n"); // FIXME: stupid way } } } } } qbool is_private_game(void) { return cvar("k_privategame") != 0; } qbool is_logged_in(gedict_t *p) { return ezinfokey(p, "login")[0]; } qbool private_game_voteable(void) { return cvar("k_privategame_voteable"); } qbool private_game_by_default(void) { return cvar("k_privategame_default"); } void vote_check_swapall(void) { int veto; gedict_t *p; if (match_in_progress || k_captains || k_coaches) { return; } if (!get_votes(OV_SWAPALL)) { return; } veto = is_admins_vote(OV_SWAPALL); if (veto || !get_votes_req(OV_SWAPALL, true)) { vote_clear(OV_SWAPALL); if (veto) { G_bprint(2, "Admin veto for %s\n", redtext("Swapall")); } else { G_bprint(2, "Majority vote for %s\n", redtext("Swapall")); } for (p = world; (p = find_plr(p));) { if (streq(getteam(p), "blue")) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "team \"red\"\ncolor 4\n"); } else if (streq(getteam(p), "red")) { stuffcmd_flags(p, STUFFCMD_IGNOREINDEMO, "team \"blue\"\ncolor 13\n"); } } } } void vote_check_all(void) { vote_check_map(); vote_check_break(); vote_check_elect(); vote_check_pickup(); vote_check_rpickup(MAX_RPICKUP_RECUSION); vote_check_nospecs(); vote_check_teamoverlay(); vote_check_coop(); vote_check_antilag(); vote_check_privategame(); vote_check_swapall(); } QW-Group-ktx-d05d6ca/src/weapons.c000066400000000000000000001651651475442401000170550ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" void ReportMe(void); void AdminImpBot(void); void CaptainPickPlayer(void); void ChasecamToggleButton(void); void ClanArenaTrackingToggleButton(void); // Bots support void BotsRocketSpawned(gedict_t *newmis); void BotsGrenadeSpawned(gedict_t *newmis); void AmmoUsed(gedict_t *player) { #ifdef BOT_SUPPORT if (player->fb.ammo_used) { player->fb.ammo_used(player); } #endif } // called by SP_worldspawn void W_Precache(void) { trap_precache_sound("weapons/r_exp3.wav"); // new rocket explosion trap_precache_sound("weapons/rocket1i.wav"); // spike gun trap_precache_sound("weapons/sgun1.wav"); trap_precache_sound("weapons/guncock.wav"); // player shotgun trap_precache_sound("weapons/ric1.wav"); // ricochet (used in c code) trap_precache_sound("weapons/ric2.wav"); // ricochet (used in c code) trap_precache_sound("weapons/ric3.wav"); // ricochet (used in c code) trap_precache_sound("weapons/spike2.wav"); // super spikes trap_precache_sound("weapons/tink1.wav"); // spikes tink (used in c code) trap_precache_sound("weapons/grenade.wav"); // grenade launcher trap_precache_sound("weapons/bounce.wav"); // grenade bounce trap_precache_sound("weapons/shotgn2.wav"); // super shotgun if (cvar("k_instagib_custom_models")) { trap_precache_sound("weapons/coilgun.wav"); // player railgun for instagib } } void W_FireSpikes(float ox); void W_FireLightning(void); /* ================ W_FireAxe ================ */ void W_FireAxe(void) { vec3_t source, dest; vec3_t org; WS_Mark(self, wpAXE); self->ps.wpn[wpAXE].attacks++; trap_makevectors(self->s.v.v_angle); VectorCopy(self->s.v.origin, source); source[2] += 16; VectorScale(g_globalvars.v_forward, 64, dest); VectorAdd(dest, source, dest) //source = self->s.v.origin + '0 0 16'; traceline(PASSVEC3(source), PASSVEC3(dest), false, self); if (g_globalvars.trace_fraction == 1.0) { return; } VectorScale(g_globalvars.v_forward, 4, org); VectorSubtract(g_globalvars.trace_endpos, org, org); // org = trace_endpos - v_forward*4; if ( PROG_TO_EDICT(g_globalvars.trace_ent)->s.v.takedamage) { int damage = 20; // default damage is 20 // can't touch/damage others in race if (isRACE() && (PROG_TO_EDICT(g_globalvars.trace_ent)->ct == ctPlayer) && (self != PROG_TO_EDICT(g_globalvars.trace_ent))) { return; } if (PROG_TO_EDICT(g_globalvars.trace_ent)->ct == ctPlayer) { WS_Mark(self, wpAXE); self->ps.wpn[wpAXE].hits++; } if (deathmatch > 3) { damage = 75; } else if (deathmatch == 3) { damage = k_yawnmode ? 50 : 20; // Yawnmode: 50 axe dmg in dmm3 } PROG_TO_EDICT(g_globalvars.trace_ent)->axhitme = 1; SpawnBlood(org, damage); PROG_TO_EDICT(g_globalvars.trace_ent)->deathtype = dtAXE; T_Damage(PROG_TO_EDICT(g_globalvars.trace_ent), self, self, damage); } else { // hit wall //crt - get rid of axe sound for spec if (!isRA() || (isWinner(self) || isLoser(self))) { sound(self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_GUNSHOT); WriteByte( MSG_MULTICAST, 3); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); trap_multicast(PASSVEC3(org), MULTICAST_PVS); } } //============================================================================ //============================================================================ void wall_velocity(vec3_t v) { vec3_t vel; normalize(self->s.v.velocity, vel); vel[0] += g_globalvars.v_up[0] * (g_random() - 0.5) + g_globalvars.v_right[0] * (g_random() - 0.5); vel[1] += g_globalvars.v_up[1] * (g_random() - 0.5) + g_globalvars.v_right[1] * (g_random() - 0.5); vel[2] += g_globalvars.v_up[2] * (g_random() - 0.5) + g_globalvars.v_right[2] * (g_random() - 0.5); VectorNormalize(vel); vel[0] += 2 * g_globalvars.trace_plane_normal[0]; vel[1] += 2 * g_globalvars.trace_plane_normal[1]; vel[2] += 2 * g_globalvars.trace_plane_normal[2]; VectorScale(vel, 200, v); //return vel; } /* ================ SpawnMeatSpray ================ */ void SpawnMeatSpray(vec3_t org, vec3_t vel) { gedict_t *missile; //vec3_t org; missile = spawn(); missile->s.v.owner = EDICT_TO_PROG(self); missile->s.v.movetype = MOVETYPE_BOUNCE; missile->isMissile = true; missile->s.v.solid = SOLID_NOT; trap_makevectors(self->s.v.angles); VectorCopy(vel, missile->s.v.velocity); // missile->s.v.velocity = vel; missile->s.v.velocity[2] = missile->s.v.velocity[2] + 250 + 50 * g_random(); SetVector(missile->s.v.avelocity, 3000, 1000, 2000); // missile.avelocity = '3000 1000 2000'; // set missile duration missile->s.v.nextthink = g_globalvars.time + 1; missile->think = (func_t) SUB_Remove; setmodel(missile, "progs/zom_gib.mdl"); setsize(missile, 0, 0, 0, 0, 0, 0); setorigin(missile, PASSVEC3(org)); } /* ================ SpawnBlood ================ */ void SpawnBlood(vec3_t org, float damage) { if (damage < 1) { return; } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_BLOOD); WriteByte( MSG_MULTICAST, damage); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); trap_multicast(PASSVEC3(org), MULTICAST_PVS); } /* ================ spawn_touchblood ================ */ void spawn_touchblood(float damage) { vec3_t vel; wall_velocity(vel); VectorScale(vel, 0.2 * 0.01, vel); VectorAdd(self->s.v.origin, vel, vel); SpawnBlood(vel, damage); } /* ============================================================================== MULTI-DAMAGE Collects multiple small damages into a single damage ============================================================================== */ gedict_t *multi_ent; float multi_damage; deathType_t multi_damage_type; vec3_t blood_org; float blood_count; vec3_t puff_org; float puff_count; void ClearMultiDamage(void) { multi_ent = world; multi_damage = 0; blood_count = 0; puff_count = 0; multi_damage_type = dtNONE; } void ApplyMultiDamage(void) { if (multi_ent == world) { return; } multi_ent->deathtype = multi_damage_type; T_Damage(multi_ent, self, self, multi_damage); } void AddMultiDamage(gedict_t *hit, float damage) { if (!hit) { return; } if (hit != multi_ent) { ApplyMultiDamage(); multi_damage = damage; multi_ent = hit; } else { multi_damage = multi_damage + damage; } } void Multi_Finish(void) { if (puff_count) { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_GUNSHOT); WriteByte( MSG_MULTICAST, puff_count); WriteCoord( MSG_MULTICAST, puff_org[0]); WriteCoord( MSG_MULTICAST, puff_org[1]); WriteCoord( MSG_MULTICAST, puff_org[2]); trap_multicast(PASSVEC3(puff_org), MULTICAST_PVS); } SpawnBlood(puff_org, blood_count); } void CoilgunTrail(vec3_t org, vec3_t endpos, int entnum, int color) { if ((color < 1) || (color > 7)) { color = 1; } if ((entnum < 0) || (entnum > MAX_CLIENTS)) { entnum = 0; } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_LIGHTNING1); WriteShort( MSG_MULTICAST, -264 + 8 * entnum + color); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); WriteCoord( MSG_MULTICAST, endpos[0]); WriteCoord( MSG_MULTICAST, endpos[1]); WriteCoord( MSG_MULTICAST, endpos[2]); trap_multicast(PASSVEC3(org), MULTICAST_PHS); } /* ============================================================================== BULLETS ============================================================================== */ /* ================ TraceAttack ================ */ void TraceAttack(float damage, vec3_t dir, qbool send_effects) { vec3_t org, tmp; VectorScale(dir, 4, tmp); VectorSubtract(g_globalvars.trace_endpos, tmp, org); // org = trace_endpos - dir*4; // can't touch/damage others in race if (isRACE() && (PROG_TO_EDICT(g_globalvars.trace_ent)->ct == ctPlayer) && (self != PROG_TO_EDICT(g_globalvars.trace_ent))) { return; } if (PROG_TO_EDICT(g_globalvars.trace_ent)->s.v.takedamage) { if (PROG_TO_EDICT(g_globalvars.trace_ent)->ct == ctPlayer) { if ((int)self->s.v.weapon == IT_SHOTGUN) { WS_Mark(self, wpSG); self->ps.wpn[wpSG].hits++; } else if ((int)self->s.v.weapon == IT_SUPER_SHOTGUN) { WS_Mark(self, wpSSG); self->ps.wpn[wpSSG].hits++; } else { ; // hmmm, make error? } } blood_count = blood_count + 1; VectorCopy(org, blood_org); // blood_org = org; AddMultiDamage(PROG_TO_EDICT(g_globalvars.trace_ent), damage); if (send_effects) { SpawnBlood(org, 1); } } else { puff_count = puff_count + 1; if (send_effects) { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_GUNSHOT); WriteByte( MSG_MULTICAST, 1); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); trap_multicast(PASSVEC3(puff_org), MULTICAST_PVS); } } } /* ================ FireInstaBullet Used by coilgun for Instagib mode, bullet doesn't stop at first player, it goes through till it hits wall ================ */ void T_InstaKickback(void); void FireInstaBullet(vec3_t dir, deathType_t deathtype) { vec3_t src, dst, tmp; int depth, solid; float fraction; gedict_t *ignore; if (cvar("k_cg_kb")) { newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->s.v.owner = EDICT_TO_PROG(self); newmis->s.v.movetype = MOVETYPE_FLYMISSILE; newmis->isMissile = true; newmis->s.v.solid = SOLID_BBOX; trap_makevectors(self->s.v.v_angle); aim(newmis->s.v.velocity); // = aim(self, 1000); VectorScale(newmis->s.v.velocity, 1000, newmis->s.v.velocity); vectoangles(newmis->s.v.velocity, newmis->s.v.angles); newmis->touch = (func_t) T_InstaKickback; newmis->voided = 0; newmis->s.v.nextthink = g_globalvars.time + 1; newmis->think = (func_t) SUB_Remove; newmis->classname = "kickback"; setmodel(newmis, ""); setsize(newmis, 0, 0, 0, 0, 0, 0); setorigin(newmis, self->s.v.origin[0] + g_globalvars.v_forward[0] * 8, self->s.v.origin[1] + g_globalvars.v_forward[1] * 8, self->s.v.origin[2] + g_globalvars.v_forward[2] * 8 + 16); } ClearMultiDamage(); multi_damage_type = deathtype; // init src trap_makevectors(self->s.v.v_angle); VectorScale(g_globalvars.v_forward, 10, tmp); VectorAdd(self->s.v.origin, tmp, src); src[2] = self->s.v.absmin[2] + self->s.v.size[2] * 0.7; for (ignore = self, depth = 0; depth < 32; depth++) { // G_sprint( self, 2, "depth %d\n", depth); // DEBUG!!!!! // init dst VectorScale(dir, 8192, tmp); VectorAdd(src, tmp, dst); traceline(PASSVEC3(src), PASSVEC3(dst), false, ignore); VectorScale(dir, 4, tmp); VectorSubtract(g_globalvars.trace_endpos, tmp, puff_org); // puff_org = trace_endpos - dir*4; // save trace info, since TraceAttack() may modifie it ignore = PROG_TO_EDICT(g_globalvars.trace_ent); fraction = g_globalvars.trace_fraction; solid = ignore->s.v.solid; // next interation we start traceline() from trace_endpos VectorCopy(g_globalvars.trace_endpos, src); // G_sprint( self, 2, "fraction %f\n", fraction); // DEBUG!!!!! // G_sprint( self, 2, "solid %d, %s\n", solid, ignore->netname); // DEBUG!!!!! TraceAttack(4, dir, false); // this is something like "fix" for one bullet hit more than one player? if (depth > 1) { WS_Mark(self, wpSG); self->ps.wpn[wpSG].hits--; if (depth > self->ps.i_maxmultigibs) { self->ps.i_maxmultigibs = depth; } } if (fraction == 1.0) { break; // no obstacle } if (solid != SOLID_SLIDEBOX) { break; // obstacle not a player/monster, probably something solid like wall or something } } if (depth > 1) { self->ps.i_multigibs++; } ApplyMultiDamage(); Multi_Finish(); VectorCopy(self->s.v.origin, tmp); //tmp = self->s.v.origin + '0 0 16'; tmp[2] += 16; CoilgunTrail(tmp, src, self - world, iKey(self, "railcolor")); } /* ================ FireBullets Used by shotgun, super shotgun, and enemy soldier firing Go to the trouble of combining multiple pellets into a single damage call. ================ */ void FireBullets(float shotcount, vec3_t dir, float spread_x, float spread_y, float spread_z, deathType_t deathtype) { vec3_t direction; vec3_t src, tmp, tmp2; qbool classic_shotgun = cvar("k_classic_shotgun"); qbool non_random_bullets = (k_yawnmode || (!match_in_progress && self && (self->ct == ctPlayer) && iKey(self, "nrb"))); trap_makevectors(self->s.v.v_angle); VectorScale(g_globalvars.v_forward, 10, tmp); VectorAdd(self->s.v.origin, tmp, src); //src = self->s.v.origin + v_forward*10; src[2] = self->s.v.absmin[2] + self->s.v.size[2] * 0.7; ClearMultiDamage(); multi_damage_type = deathtype; if (cvar("k_instagib")) { traceline(PASSVEC3(src), src[0] + dir[0] * 8192, src[1] + dir[1] * 8192, src[2] + dir[2] * 8192, false, self); } else { traceline(PASSVEC3(src), src[0] + dir[0] * 2048, src[1] + dir[1] * 2048, src[2] + dir[2] * 2048, false, self); } VectorScale(dir, 4, tmp); VectorSubtract(g_globalvars.trace_endpos, tmp, puff_org); // puff_org = trace_endpos - dir*4; while (shotcount > 0) { if (non_random_bullets) { if (shotcount == 1) { VectorClear(tmp); VectorClear(tmp2); } else if (shotcount == 2) { VectorClear(tmp); VectorClear(tmp2); } else if (shotcount == 3) { VectorClear(tmp); VectorScale(g_globalvars.v_up, 1.00 * spread_y, tmp2); } else if (shotcount == 4) { VectorClear(tmp); VectorScale(g_globalvars.v_up, -1.00 * spread_y, tmp2); } else if (shotcount == 5) { VectorScale(g_globalvars.v_right, 1.00 * spread_x, tmp); VectorClear(tmp2); } else if (shotcount == 6) { VectorScale(g_globalvars.v_right, -1.00 * spread_x, tmp); VectorClear(tmp2); } else if (shotcount == 7) { VectorClear(tmp); VectorScale(g_globalvars.v_up, 0.50 * spread_y, tmp2); } else if (shotcount == 8) { VectorClear(tmp); VectorScale(g_globalvars.v_up, -0.50 * spread_y, tmp2); } else if (shotcount == 9) { VectorScale(g_globalvars.v_right, 0.50 * spread_x, tmp); VectorClear(tmp2); } else if (shotcount == 10) { VectorScale(g_globalvars.v_right, -0.50 * spread_x, tmp); VectorClear(tmp2); } else if (shotcount == 11) { VectorScale(g_globalvars.v_right, 0.50 * spread_x, tmp); VectorScale(g_globalvars.v_up, 0.50 * spread_y, tmp2); } else if (shotcount == 12) { VectorScale(g_globalvars.v_right, 0.50 * spread_x, tmp); VectorScale(g_globalvars.v_up, -0.50 * spread_y, tmp2); } else if (shotcount == 13) { VectorScale(g_globalvars.v_right, -0.50 * spread_x, tmp); VectorScale(g_globalvars.v_up, -0.50 * spread_y, tmp2); } else if (shotcount == 14) { VectorScale(g_globalvars.v_right, -0.50 * spread_x, tmp); VectorScale(g_globalvars.v_up, 0.50 * spread_y, tmp2); } else if (shotcount == 15) { VectorScale(g_globalvars.v_right, 0.25 * spread_x, tmp); VectorScale(g_globalvars.v_up, 0.25 * spread_y, tmp2); } else if (shotcount == 16) { VectorScale(g_globalvars.v_right, 0.25 * spread_x, tmp); VectorScale(g_globalvars.v_up, -0.25 * spread_y, tmp2); } else if (shotcount == 17) { VectorScale(g_globalvars.v_right, -0.25 * spread_x, tmp); VectorScale(g_globalvars.v_up, -0.25 * spread_y, tmp2); } else if (shotcount == 18) { VectorScale(g_globalvars.v_right, -0.25 * spread_x, tmp); VectorScale(g_globalvars.v_up, 0.25 * spread_y, tmp2); } else if (shotcount == 19) { VectorScale(g_globalvars.v_right, -1.00 * spread_x, tmp); VectorClear(tmp2); } else if (shotcount == 20) { VectorClear(tmp); VectorClear(tmp2); } else if (shotcount == 21) { VectorScale(g_globalvars.v_right, 1.00 * spread_x, tmp); VectorClear(tmp2); } else { // No design for this bullet, place it in the middle VectorClear(tmp); VectorClear(tmp2); } VectorAdd(dir, tmp, direction); VectorAdd(direction, tmp2, direction); } else { VectorScale(g_globalvars.v_right, crandom() * spread_x, tmp); VectorAdd(dir, tmp, direction); VectorScale(g_globalvars.v_up, crandom() * spread_y, tmp); VectorAdd(direction, tmp, direction); } // direction = dir + crandom()*spread[0]*v_right + crandom()*spread[1]*v_up; if (cvar("k_instagib")) { VectorScale(direction, 8192, tmp); } else { VectorScale(direction, 2048, tmp); } VectorAdd(src, tmp, tmp); traceline(PASSVEC3(src), PASSVEC3(tmp), false, self); if (g_globalvars.trace_fraction != 1.0) { TraceAttack(4, direction, classic_shotgun); } shotcount = shotcount - 1; } ApplyMultiDamage(); if (!classic_shotgun) { Multi_Finish(); } } /* ================ W_FireShotgun ================ */ #ifdef HITBOXCHECK void W_FireShotgun(void) { qbool classic_shotgun = cvar("k_classic_shotgun"); vec3_t dir, s_dir, src, o_src, eorg, tmp; float offset; int bullets = bound(1, cvar("k_hitboxcheck_bullets"), 64), color = iKey(self, "railcolor"), b; WS_Mark(self, wpSG); self->ps.wpn[wpSG].attacks += bullets; sound(self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); trap_makevectors(self->s.v.v_angle); // make dir VectorCopy(g_globalvars.v_forward, dir); // make scaled dir VectorScale(dir, 8000, s_dir); // make source VectorScale(dir, 10, tmp); VectorAdd(self->s.v.origin, tmp, src); src[2] = self->s.v.absmin[2] + self->s.v.size[2] * 0.7; // prepare multi damage ClearMultiDamage(); multi_damage_type = dtSG; // make puff traceline(PASSVEC3(src), src[0] + s_dir[0], src[1] + s_dir[1], src[2] + s_dir[2], false, self); VectorScale(dir, 4, tmp); VectorSubtract(g_globalvars.trace_endpos, tmp, puff_org); // fire each bullet for (offset = -(float)(bullets - 1) / 2, b = bullets; b > 0; b--, offset++) { // calculate where trace start VectorMA(src, offset, g_globalvars.v_right, o_src); // calculate where trace should end VectorAdd(o_src, s_dir, eorg); traceline(PASSVEC3(o_src), PASSVEC3(eorg), false, self); if (g_globalvars.trace_fraction != 1.0) { TraceAttack(1, dir, classic_shotgun); } if ((b == bullets) || (b == 1)) { CoilgunTrail(o_src, g_globalvars.trace_endpos, self - world, color); } } // finish multi damage ApplyMultiDamage(); if (!classic_shotgun) { Multi_Finish(); } } #else void W_FireShotgun(void) { vec3_t dir; int bullets = 6; WS_Mark(self, wpSG); if (cvar("k_instagib")) { self->ps.wpn[wpSG].attacks++; } else { self->ps.wpn[wpSG].attacks += bullets; } if (cvar("k_instagib_custom_models") && cvar("k_instagib")) { sound(self, CHAN_WEAPON, "weapons/coilgun.wav", 1, ATTN_NORM); } else { sound(self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); } g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = --(self->s.v.ammo_shells); AmmoUsed(self); } } //dir = aim (self, 100000); aim(dir); if (cvar("k_instagib")) { FireInstaBullet(dir, dtSG); } else { FireBullets(bullets, dir, 0.04, 0.04, 0, dtSG); } } #endif /* ================ W_FireSuperShotgun ================ */ void W_FireSuperShotgun(void) { vec3_t dir; int bullets = (k_yawnmode ? 21 : 14); if (self->s.v.currentammo == 1) { W_FireShotgun(); return; } WS_Mark(self, wpSSG); self->ps.wpn[wpSSG].attacks += bullets; sound(self, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_BIGKICK); if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_shells = self->s.v.ammo_shells - 2; AmmoUsed(self); } } //dir = aim (self, 100000); aim(dir); if (k_yawnmode) { // Yawnmode: larger SSG spread, higher reload time, more damage // - Molgrum FireBullets(bullets, dir, 0.18, 0.12, 0, dtSSG); } else { FireBullets(bullets, dir, 0.14, 0.08, 0, dtSSG); } } /* ============================================================================== ROCKETS ============================================================================== */ void FixQuad(gedict_t *owner) { // well, quaded rocket is no more quaded after owner is dead, // at the same time that still allow apply full quad damage to nearby players in case of "quad bore" if ((owner->ct == ctPlayer) && ISDEAD(owner)) { owner->super_damage_finished = 0; } } void T_InstaKickback(void) { vec3_t tmp; if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } if (self->voided) { return; } self->voided = 1; if (trap_pointcontents(PASSVEC3(self->s.v.origin)) == CONTENT_SKY) { ent_remove(self); return; } T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 120, other, dtRL); normalize(self->s.v.velocity, tmp); VectorScale(tmp, -8, tmp); VectorAdd(self->s.v.origin, tmp, self->s.v.origin) ent_remove(self); } void T_MissileTouch(void) { float damg; vec3_t tmp; if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } // race rockets can only hit the world if (isRACE() && (other->s.v.solid != SOLID_BSP)) { return; } if (self->voided) { return; } self->voided = 1; if (trap_pointcontents(PASSVEC3(self->s.v.origin)) == CONTENT_SKY) { ent_remove(self); return; } FixQuad(PROG_TO_EDICT(self->s.v.owner)); // shamblers only take half damage from rockets if (streq(other->classname, "monster_shambler") && !cvar("k_bloodfest")) { damg = 55; } else { // 110 dmg on direct hits for all other cases damg = 110; } if (other->s.v.takedamage) { if (other->ct == ctPlayer) { WS_Mark(PROG_TO_EDICT(self->s.v.owner), wpRL); PROG_TO_EDICT(self->s.v.owner)->ps.wpn[wpRL].hits++; } } if (ISLIVE(other)) { other->deathtype = dtRL; T_Damage(other, self, PROG_TO_EDICT(self->s.v.owner), damg); } // don't do radius damage to the other, because all the damage // was done in the impact T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 120, other, dtRL); // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); normalize(self->s.v.velocity, tmp); VectorScale(tmp, -8, tmp); VectorAdd(self->s.v.origin, tmp, self->s.v.origin) // self->s.v.origin = self->s.v.origin - 8 * normalize(self->s.v.velocity); WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_EXPLOSION); WriteCoord( MSG_MULTICAST, self->s.v.origin[0]); WriteCoord( MSG_MULTICAST, self->s.v.origin[1]); WriteCoord( MSG_MULTICAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } /* ================ W_FireRocket ================ */ void W_FireRocket(void) { WS_Mark(self, wpRL); self->ps.wpn[wpRL].attacks++; if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_rockets = self->s.v.ammo_rockets - 1; AmmoUsed(self); } } sound(self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->s.v.owner = EDICT_TO_PROG(self); newmis->s.v.movetype = MOVETYPE_FLYMISSILE; newmis->isMissile = true; newmis->s.v.solid = (isRACE() ? SOLID_TRIGGER : SOLID_BBOX); // set newmis speed trap_makevectors(self->s.v.v_angle); aim(newmis->s.v.velocity); // = aim(self, 1000); if (cvar("k_midair") && (self->super_damage_finished > g_globalvars.time)) { VectorScale(newmis->s.v.velocity, 2000, newmis->s.v.velocity); newmis->s.v.effects = EF_BLUE; } else { VectorScale(newmis->s.v.velocity, 1000, newmis->s.v.velocity); } vectoangles(newmis->s.v.velocity, newmis->s.v.angles); newmis->touch = (func_t) T_MissileTouch; newmis->voided = 0; // set newmis duration newmis->s.v.nextthink = g_globalvars.time + 10; newmis->think = (func_t) SUB_Remove; newmis->classname = "rocket"; setmodel(newmis, "progs/missile.mdl"); setsize(newmis, 0, 0, 0, 0, 0, 0); // setorigin (newmis, self->s.v.origin + v_forward*8 + '0 0 16'); setorigin(newmis, self->s.v.origin[0] + g_globalvars.v_forward[0] * 8, self->s.v.origin[1] + g_globalvars.v_forward[1] * 8, self->s.v.origin[2] + g_globalvars.v_forward[2] * 8 + 16); // midair VectorCopy(self->s.v.origin, newmis->s.v.oldorigin); #ifdef BOT_SUPPORT BotsRocketSpawned(newmis); #endif } /* =============================================================================== LIGHTNING =============================================================================== */ void LightningHit(gedict_t *from, float damage) { if (PROG_TO_EDICT(g_globalvars.trace_ent)->ct == ctPlayer) { WS_Mark(from, wpLG); from->ps.wpn[wpLG].hits++; from->ps.wpn[wpLG].lastfraghits++; } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_LIGHTNINGBLOOD); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[0]); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[1]); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[2]); trap_multicast(PASSVEC3(g_globalvars.trace_endpos), MULTICAST_PVS); PROG_TO_EDICT(g_globalvars.trace_ent)->deathtype = dtLG_BEAM; T_Damage(PROG_TO_EDICT(g_globalvars.trace_ent), from, from, damage); } /* ================= LightningDamage ================= */ void LightningDamage(vec3_t p1, vec3_t p2, gedict_t *from, float damage) { traceline(PASSVEC3(p1), PASSVEC3(p2), false, from); if (PROG_TO_EDICT(g_globalvars.trace_ent)->s.v.takedamage) { if (lgc_enabled()) { lgc_register_hit(p1, from, PROG_TO_EDICT(g_globalvars.trace_ent)); } LightningHit(from, damage); // this code cause "dm6 secret door bug" if (from->ct == ctPlayer) { gedict_t *gre = PROG_TO_EDICT(from->s.v.groundentity); if (gre && (gre == PROG_TO_EDICT(g_globalvars.trace_ent)) && streq(gre->classname, "door")) { PROG_TO_EDICT(g_globalvars.trace_ent)->s.v.velocity[2] += 400; } } } else if (lgc_enabled()) { lgc_register_miss(p1, from); } } void W_FireLightning(void) { vec3_t org; float cells; vec3_t tmp; if ((self->s.v.ammo_cells < 1) || (match_in_progress == 1)) { self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); return; } trap_makevectors(self->s.v.v_angle); // explode if under water if ((self->s.v.waterlevel > 1) && (match_in_progress == 2)) { if (isRA() || isCA() || k_bloodfest) { self->s.v.ammo_cells = 0; W_SetCurrentAmmo(); AmmoUsed(self); return; } if (deathmatch > 3) { // Yawnmode: this always kills the player that discharges in dmm4 // - Molgrum if (k_yawnmode || (g_random() <= 0.5)) { self->deathtype = dtLG_DIS_SELF; T_Damage(self, self, self, 4000); return; } else { cells = self->s.v.ammo_cells; self->s.v.ammo_cells = 0; W_SetCurrentAmmo(); AmmoUsed(self); if (!cvar("k_dis")) { return; } T_RadiusDamage(self, self, 35 * cells, world, dtLG_DIS); return; } } else { cells = self->s.v.ammo_cells; self->s.v.ammo_cells = 0; W_SetCurrentAmmo(); AmmoUsed(self); if (!cvar("k_dis")) { return; } T_RadiusDamage(self, self, 35 * cells, world, dtLG_DIS); return; } } WS_Mark(self, wpLG); self->ps.wpn[wpLG].attacks++; self->ps.wpn[wpLG].lastfragattacks++; if (self->t_width < g_globalvars.time) { sound(self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM); self->t_width = g_globalvars.time + 0.6; } g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_cells = self->s.v.ammo_cells - 1; AmmoUsed(self); } } VectorCopy(self->s.v.origin, org); //org = self->s.v.origin + '0 0 16'; org[2] += 16; traceline(PASSVEC3(org), org[0] + g_globalvars.v_forward[0] * 600, org[1] + g_globalvars.v_forward[1] * 600, org[2] + g_globalvars.v_forward[2] * 600, true, self); WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_LIGHTNING2); WriteEntity( MSG_MULTICAST, self); WriteCoord( MSG_MULTICAST, org[0]); WriteCoord( MSG_MULTICAST, org[1]); WriteCoord( MSG_MULTICAST, org[2]); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[0]); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[1]); WriteCoord( MSG_MULTICAST, g_globalvars.trace_endpos[2]); trap_multicast(PASSVEC3(org), MULTICAST_PHS); VectorScale(g_globalvars.v_forward, 4, tmp); VectorAdd(g_globalvars.trace_endpos, tmp, tmp); // qqshka - not from 'self->s.v.origin' but from 'org' // LightningDamage( self->s.v.origin, tmp, self, 30 ); LightningDamage(org, tmp, self, 30); } //============================================================================= void GrenadeExplode(void) { if (self->voided) { return; } self->voided = 1; FixQuad(PROG_TO_EDICT(self->s.v.owner)); // shamblers only take half damage from grenades if (streq(self->classname, "monster_shambler") && !cvar("k_bloodfest")) { T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 60, world, dtGL); } else { T_RadiusDamage(self, PROG_TO_EDICT(self->s.v.owner), 120, world, dtGL); } WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_EXPLOSION); WriteCoord( MSG_MULTICAST, self->s.v.origin[0]); WriteCoord( MSG_MULTICAST, self->s.v.origin[1]); WriteCoord( MSG_MULTICAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); ent_remove(self); } void GrenadeTouch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; // don't explode on owner } // can't touch/damage others in race if (isRACE() && (other->ct == ctPlayer) && (other != PROG_TO_EDICT(self->s.v.owner))) { return; } if (other->s.v.takedamage) { if (other->ct == ctPlayer) { WS_Mark(PROG_TO_EDICT(self->s.v.owner), wpGL); PROG_TO_EDICT(self->s.v.owner)->ps.wpn[wpGL].hits++; } } if (other->s.v.takedamage == DAMAGE_AIM) { GrenadeExplode(); return; } sound(self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound if ((self->s.v.velocity[0] == 0) && (self->s.v.velocity[1] == 0) && (self->s.v.velocity[2] == 0)) { VectorClear(self->s.v.avelocity); } } /* ================ W_FireGrenade ================ */ void W_FireGrenade(void) { float r1 = crandom(), r2 = crandom(); vec3_t ang; WS_Mark(self, wpGL); self->ps.wpn[wpGL].attacks++; if (match_in_progress == 2) { if (isCA()) { self->s.v.currentammo = self->ca_ammo_grenades = self->ca_ammo_grenades - 1; if (!self->ca_ammo_grenades) { self->s.v.items -= IT_GRENADE_LAUNCHER; } AmmoUsed(self); } else if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_rockets = self->s.v.ammo_rockets - 1; AmmoUsed(self); } } sound(self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->voided = 0; newmis->s.v.owner = EDICT_TO_PROG(self); newmis->s.v.movetype = MOVETYPE_BOUNCE; newmis->isMissile = true; newmis->s.v.solid = SOLID_BBOX; newmis->classname = "grenade"; // set newmis speed VectorCopy(self->s.v.v_angle, ang); // limit pitch in case the server allows pitch angles < -70, // so that grenades still go straight up and not behind if (ang[PITCH] < -70) { ang[PITCH] = -70; } trap_makevectors(ang); // Yawnmode: disable randomness in grenade aim // - Molgrum if (k_yawnmode) { r1 = r2 = 0; } newmis->s.v.velocity[0] = g_globalvars.v_forward[0] * 600 + g_globalvars.v_up[0] * 200 + r1 * g_globalvars.v_right[0] * 10 + r2 * g_globalvars.v_up[0] * 10; newmis->s.v.velocity[1] = g_globalvars.v_forward[1] * 600 + g_globalvars.v_up[1] * 200 + r1 * g_globalvars.v_right[1] * 10 + r2 * g_globalvars.v_up[1] * 10; newmis->s.v.velocity[2] = g_globalvars.v_forward[2] * 600 + g_globalvars.v_up[2] * 200 + r1 * g_globalvars.v_right[2] * 10 + r2 * g_globalvars.v_up[0] * 10; SetVector(newmis->s.v.avelocity, 300, 300, 300); // newmis.avelocity = '300 300 300'; vectoangles(newmis->s.v.velocity, newmis->s.v.angles); newmis->touch = (func_t) GrenadeTouch; newmis->s.v.nextthink = g_globalvars.time + 2.5; newmis->think = (func_t) GrenadeExplode; if ((deathmatch == 4) && cvar("k_dmm4_gren_mode")) { newmis->think = (func_t) SUB_Remove; } setmodel(newmis, "progs/grenade.mdl"); setsize(newmis, 0, 0, 0, 0, 0, 0); setorigin(newmis, PASSVEC3(self->s.v.origin)); #ifdef BOT_SUPPORT BotsGrenadeSpawned(newmis); #endif } //============================================================================= void spike_touch(void); /* =============== launch_spike Used for both the player and the traps =============== */ void launch_spike(vec3_t org, vec3_t dir) { newmis = spawn(); g_globalvars.newmis = EDICT_TO_PROG(newmis); newmis->voided = 0; newmis->s.v.owner = EDICT_TO_PROG(self); newmis->s.v.movetype = MOVETYPE_FLYMISSILE; newmis->isMissile = true; newmis->s.v.solid = (isRACE() ? SOLID_TRIGGER : SOLID_BBOX); newmis->touch = (func_t) spike_touch; newmis->classname = "spike"; newmis->think = (func_t) SUB_Remove; newmis->s.v.nextthink = g_globalvars.time + 6; setmodel(newmis, "progs/spike.mdl"); setsize(newmis, 0, 0, 0, 0, 0, 0); setorigin(newmis, PASSVEC3(org)); // Yawnmode: spikes velocity is 1800 instead of 1000 // - Molgrum VectorScale(dir, (k_yawnmode ? 1800 : 1000), newmis->s.v.velocity); vectoangles(newmis->s.v.velocity, newmis->s.v.angles); } static qbool race_ignore_spike(gedict_t *self, gedict_t *other) { // we're not racing, treat as normal if (!isRACE()) { return false; } // everything collides with walls if (other == world) { return false; } // they only collide with players if (other->ct != ctPlayer) { return true; } // player fired it? ignore return PROG_TO_EDICT(self->s.v.owner)->ct == ctPlayer; } void spike_touch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; } if (race_ignore_spike(self, other)) { return; } if (self->voided) { return; } self->voided = 1; if (other->s.v.solid == SOLID_TRIGGER) { G_bprint(2, "Trigger field, do nothing (%s)\n", other->netname); return; // trigger field, do nothing } if (trap_pointcontents(PASSVEC3(self->s.v.origin)) == CONTENT_SKY) { ent_remove(self); return; } FixQuad(PROG_TO_EDICT(self->s.v.owner)); // hit something that bleeds if (other->s.v.takedamage) { if (other->ct == ctPlayer) { WS_Mark(PROG_TO_EDICT(self->s.v.owner), wpNG); PROG_TO_EDICT(self->s.v.owner)->ps.wpn[wpNG].hits++; } spawn_touchblood(1); other->deathtype = dtNG; T_Damage(other, self, PROG_TO_EDICT(self->s.v.owner), 9); } else { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); if (!strcmp(self->classname, "wizspike")) { WriteByte( MSG_MULTICAST, TE_WIZSPIKE); } else if (!strcmp(self->classname, "knightspike")) { WriteByte( MSG_MULTICAST, TE_KNIGHTSPIKE); } else { WriteByte( MSG_MULTICAST, TE_SPIKE); } WriteCoord( MSG_MULTICAST, self->s.v.origin[0]); WriteCoord( MSG_MULTICAST, self->s.v.origin[1]); WriteCoord( MSG_MULTICAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); } ent_remove(self); } void superspike_touch(void) { if (other == PROG_TO_EDICT(self->s.v.owner)) { return; } if (race_ignore_spike(self, other)) { return; } if (self->voided) { return; } self->voided = 1; if (other->s.v.solid == SOLID_TRIGGER) { return; // trigger field, do nothing } if (trap_pointcontents(PASSVEC3(self->s.v.origin)) == CONTENT_SKY) { ent_remove(self); return; } FixQuad(PROG_TO_EDICT(self->s.v.owner)); // hit something that bleeds if (other->s.v.takedamage) { if (other->ct == ctPlayer) { WS_Mark(PROG_TO_EDICT(self->s.v.owner), wpSNG); PROG_TO_EDICT(self->s.v.owner)->ps.wpn[wpSNG].hits++; } spawn_touchblood(2); other->deathtype = dtSNG; T_Damage(other, self, PROG_TO_EDICT(self->s.v.owner), (k_yawnmode ? 16 : 18)); } else { WriteByte( MSG_MULTICAST, SVC_TEMPENTITY); WriteByte( MSG_MULTICAST, TE_SUPERSPIKE); WriteCoord( MSG_MULTICAST, self->s.v.origin[0]); WriteCoord( MSG_MULTICAST, self->s.v.origin[1]); WriteCoord( MSG_MULTICAST, self->s.v.origin[2]); trap_multicast(PASSVEC3(self->s.v.origin), MULTICAST_PHS); } ent_remove(self); } void W_FireSuperSpikes(void) { vec3_t dir, tmp; WS_Mark(self, wpSNG); self->ps.wpn[wpSNG].attacks++; sound(self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM); self->attack_finished = g_globalvars.time + 0.2; if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_nails = self->s.v.ammo_nails - 2; AmmoUsed(self); } } aim(dir); //dir = aim (self, 1000); VectorCopy(self->s.v.origin, tmp); tmp[2] += 16; launch_spike(tmp, dir); newmis->touch = (func_t) superspike_touch; setmodel(newmis, "progs/s_spike.mdl"); setsize(newmis, 0, 0, 0, 0, 0, 0); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); } void W_FireSpikes(float ox) { vec3_t dir, tmp; // Yawnmode: ignores alternating nails effect in nailgun // - Molgrum if (k_yawnmode) { ox = 0; } trap_makevectors(self->s.v.v_angle); if (match_in_progress != 1) { if ((self->s.v.ammo_nails >= 2) && (self->s.v.weapon == IT_SUPER_NAILGUN)) { W_FireSuperSpikes(); return; } } if ((self->s.v.ammo_nails < 1) || (match_in_progress == 1)) { self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); return; } WS_Mark(self, wpNG); self->ps.wpn[wpNG].attacks++; sound(self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM); self->attack_finished = g_globalvars.time + 0.2; if (match_in_progress == 2) { if ((deathmatch != 4) && !k_bloodfest) { self->s.v.currentammo = self->s.v.ammo_nails = self->s.v.ammo_nails - 1; AmmoUsed(self); } } aim(dir); // dir = aim (self, 1000); VectorScale(g_globalvars.v_right, ox, tmp); VectorAdd(tmp, self->s.v.origin, tmp); tmp[2] += 16; launch_spike(tmp, dir); g_globalvars.msg_entity = EDICT_TO_PROG(self); WriteByte( MSG_ONE, SVC_SMALLKICK); } /* =============================================================================== PLAYER WEAPON USE =============================================================================== */ void W_SetCurrentAmmo(void) { qbool need_fix = false; int items; float old_currentammo = self->s.v.currentammo; // { get out of any weapon firing states if ((self->think == (func_t)player_stand1) || (self->think == (func_t)player_run)) { if ((self->s.v.weapon == IT_AXE) || (self->s.v.weapon == IT_HOOK)) { if (self->s.v.velocity[0] || self->s.v.velocity[1]) { // run if ((self->s.v.frame < 0) || (self->s.v.frame > 5)) { need_fix = true; // wrong axe run frame } } else { // stand if ((self->s.v.frame < 17) || (self->s.v.frame > 28)) { need_fix = true; // wrong axe stand frame } } } else { if (self->s.v.velocity[0] || self->s.v.velocity[1]) { // run if ((self->s.v.frame < 6) || (self->s.v.frame > 11)) { need_fix = true; // wrong non axe run frame } } else { // stand if ((self->s.v.frame < 12) || (self->s.v.frame > 16)) { need_fix = true; // wrong non axe stand frame } } } } else { need_fix = true; // hm, set proper ->think } if (need_fix) { // may change ->s.v.frame self->walkframe = 0; player_run(); } else { // does't change ->s.v.frame and ->walkframe, so we does't break current animation sequence on weapon change self->s.v.nextthink = g_globalvars.time + 0.1; self->s.v.weaponframe = 0; } // } items = self->s.v.items; items -= items & ( IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS); switch ((int)self->s.v.weapon) { case IT_AXE: self->s.v.currentammo = 0; self->weaponmodel = "progs/v_axe.mdl"; self->s.v.weaponframe = 0; if (vw_enabled) { self->vw_index = 1; } break; case IT_SHOTGUN: self->s.v.currentammo = self->s.v.ammo_shells; if (cvar("k_instagib_custom_models") && cvar("k_instagib")) { self->weaponmodel = "progs/v_coil.mdl"; } else { self->weaponmodel = "progs/v_shot.mdl"; } self->s.v.weaponframe = 0; items |= IT_SHELLS; if (vw_enabled) { self->vw_index = 2; } break; case IT_SUPER_SHOTGUN: self->s.v.currentammo = self->s.v.ammo_shells; self->weaponmodel = "progs/v_shot2.mdl"; self->s.v.weaponframe = 0; items |= IT_SHELLS; if (vw_enabled) { self->vw_index = 3; } break; case IT_NAILGUN: self->s.v.currentammo = self->s.v.ammo_nails; self->weaponmodel = "progs/v_nail.mdl"; self->s.v.weaponframe = 0; items |= IT_NAILS; if (vw_enabled) { self->vw_index = 4; } break; case IT_SUPER_NAILGUN: self->s.v.currentammo = self->s.v.ammo_nails; self->weaponmodel = "progs/v_nail2.mdl"; self->s.v.weaponframe = 0; items |= IT_NAILS; if (vw_enabled) { self->vw_index = 5; } break; case IT_GRENADE_LAUNCHER: if (isCA()) { self->s.v.currentammo = self->ca_ammo_grenades; } else { self->s.v.currentammo = self->s.v.ammo_rockets; } self->weaponmodel = "progs/v_rock.mdl"; self->s.v.weaponframe = 0; items |= IT_ROCKETS; if (vw_enabled) { self->vw_index = 6; } break; case IT_ROCKET_LAUNCHER: self->s.v.currentammo = self->s.v.ammo_rockets; self->weaponmodel = "progs/v_rock2.mdl"; self->s.v.weaponframe = 0; items |= IT_ROCKETS; if (vw_enabled) { self->vw_index = 7; } break; case IT_LIGHTNING: self->s.v.currentammo = self->s.v.ammo_cells; self->weaponmodel = "progs/v_light.mdl"; self->s.v.weaponframe = 0; items |= IT_CELLS; if (vw_enabled) { self->vw_index = 8; } break; case IT_HOOK: self->s.v.currentammo = 0; if (k_ctf_custom_models) { self->weaponmodel = "progs/v_star.mdl"; } else { self->weaponmodel = "progs/v_axe.mdl"; } self->s.v.weaponframe = 0; if (vw_enabled) { self->vw_index = 1; } break; default: self->s.v.currentammo = 0; self->weaponmodel = ""; self->s.v.weaponframe = 0; self->vw_index = 0; break; } if (!vw_enabled || self->invisible_finished) { self->vw_index = 0; } if (match_in_progress != 2) { if (old_currentammo) { self->s.v.currentammo = old_currentammo; } else { self->s.v.currentammo = 1000; } } self->s.v.items = items; } float W_BestWeapon(void) { int it = self->s.v.items; char *w_rank = ezinfokey(self, "w_rank"); if (!strnull(w_rank)) { while (*w_rank) { int weapon = (*w_rank - '0'); if ((weapon == 8) && (it & IT_LIGHTNING) && (self->s.v.ammo_cells >= 1)) { return IT_LIGHTNING; } if ((weapon == 7) && (it & IT_ROCKET_LAUNCHER) && (self->s.v.ammo_rockets >= 1)) { return IT_ROCKET_LAUNCHER; } if ((weapon == 6) && (it & IT_GRENADE_LAUNCHER) && (self->s.v.ammo_rockets >= 1)) { return IT_GRENADE_LAUNCHER; } if ((weapon == 5) && (it & IT_SUPER_NAILGUN) && (self->s.v.ammo_nails >= 2)) { return IT_SUPER_NAILGUN; } if ((weapon == 4) && (it & IT_NAILGUN) && (self->s.v.ammo_nails >= 1)) { return IT_NAILGUN; } if ((weapon == 3) && (it & IT_SUPER_SHOTGUN) && (self->s.v.ammo_shells >= 2)) { return IT_SUPER_SHOTGUN; } if ((weapon == 2) && (it & IT_SHOTGUN) && (self->s.v.ammo_shells >= 1)) { return IT_SHOTGUN; } if ((weapon == 1) && (it & IT_AXE)) { return IT_AXE; } ++w_rank; } if (it & IT_AXE) { return IT_AXE; } return 0; } // Standard behaviour if ((self->s.v.waterlevel <= 1) && (self->s.v.ammo_cells >= 1) && (it & IT_LIGHTNING)) { return IT_LIGHTNING; } else if ((self->s.v.ammo_nails >= 2) && (it & IT_SUPER_NAILGUN)) { return IT_SUPER_NAILGUN; } else if ((self->s.v.ammo_shells >= 2) && (it & IT_SUPER_SHOTGUN)) { return IT_SUPER_SHOTGUN; } else if ((self->s.v.ammo_nails >= 1) && (it & IT_NAILGUN)) { return IT_NAILGUN; } else if ((self->s.v.ammo_shells >= 1) && (it & IT_SHOTGUN)) { return IT_SHOTGUN; } /* if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) ) return IT_ROCKET_LAUNCHER; else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) ) return IT_GRENADE_LAUNCHER; */ return ((it & IT_AXE) ? IT_AXE : 0); } int W_CheckNoAmmo(void) { if (self->s.v.currentammo > 0) { return true; } if ((self->s.v.weapon == IT_AXE) || (self->s.v.weapon == IT_HOOK)) { return true; } self->s.v.weapon = W_BestWeapon(); W_SetCurrentAmmo(); // drop the weapon down return false; } /* ============ W_Attack An attack impulse can be triggered now ============ */ void W_Attack(void) { float r; if (!W_CheckNoAmmo()) { return; } self->lastwepfired = self->s.v.weapon; trap_makevectors(self->s.v.v_angle); // calculate forward angle for velocity self->show_hostile = g_globalvars.time + 1; // wake monsters up switch ((int)self->s.v.weapon) { case IT_AXE: if (self->ctf_flag & CTF_RUNE_HST) { self->attack_finished = g_globalvars.time + 0.5 - (cvar("k_ctf_rune_power_hst") / 10); HasteSound(self); } else { self->attack_finished = g_globalvars.time + 0.5; } // crt - no axe sound for spec if (!isRA() || (isWinner(self) || isLoser(self))) { sound(self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM); } r = g_random(); if (r < 0.25) { player_axe1(); } else if (r < 0.5) { player_axeb1(); } else if (r < 0.75) { player_axec1(); } else { player_axed1(); } break; case IT_SHOTGUN: player_shot1(); if (self->ctf_flag & CTF_RUNE_HST) { self->attack_finished = g_globalvars.time + 0.5 - (cvar("k_ctf_rune_power_hst") / 10); HasteSound(self); } else { if (cvar("k_instagib") == 1) { self->attack_finished = g_globalvars.time + 1.2; } else if (cvar("k_instagib") == 2) { self->attack_finished = g_globalvars.time + 0.7; } else { self->attack_finished = g_globalvars.time + 0.5; } } W_FireShotgun(); break; case IT_SUPER_SHOTGUN: player_shot1(); if (self->ctf_flag & CTF_RUNE_HST) { self->attack_finished = g_globalvars.time + 0.5 - (cvar("k_ctf_rune_power_hst") / 20); HasteSound(self); } else { self->attack_finished = g_globalvars.time + (k_yawnmode ? 0.8 : 0.7); } W_FireSuperShotgun(); break; case IT_NAILGUN: self->s.v.ltime = g_globalvars.time; player_nail1(); break; case IT_SUPER_NAILGUN: self->s.v.ltime = g_globalvars.time; player_nail1(); break; case IT_GRENADE_LAUNCHER: player_rocket1(); if (self->ctf_flag & CTF_RUNE_HST) { self->attack_finished = g_globalvars.time + 0.5 - (cvar("k_ctf_rune_power_hst") / 10); HasteSound(self); } else { self->attack_finished = g_globalvars.time + 0.6; } W_FireGrenade(); break; case IT_ROCKET_LAUNCHER: player_rocket1(); if (self->ctf_flag & CTF_RUNE_HST) { self->attack_finished = g_globalvars.time + 0.5 - (cvar("k_ctf_rune_power_hst") / 20); HasteSound(self); } else { self->attack_finished = g_globalvars.time + 0.8; } W_FireRocket(); break; case IT_LIGHTNING: self->attack_finished = g_globalvars.time + 0.1; sound(self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM); self->s.v.ltime = g_globalvars.time; player_light1(); break; case IT_HOOK: if (self->hook_out) { player_chain3(); } else { player_chain1(); } self->attack_finished = g_globalvars.time + 0.1; break; } } qbool W_CanSwitch(int wp, qbool warn) { int it, am, fl = 0; it = self->s.v.items; am = 0; switch (wp) { case 1: fl = IT_AXE; break; case 2: fl = IT_SHOTGUN; if (self->s.v.ammo_shells < 1) { am = 1; } break; case 3: fl = IT_SUPER_SHOTGUN; if (self->s.v.ammo_shells < 2) { am = 1; } break; case 4: fl = IT_NAILGUN; if (self->s.v.ammo_nails < 1) { am = 1; } break; case 5: fl = IT_SUPER_NAILGUN; if (self->s.v.ammo_nails < 2) { am = 1; } break; case 6: fl = IT_GRENADE_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case 7: fl = IT_ROCKET_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case 8: fl = IT_LIGHTNING; if (self->s.v.ammo_cells < 1) { am = 1; } break; case 22: fl = IT_HOOK; break; default: break; } if (!(it & fl) && !self->race_chasecam) { // don't have the weapon or the ammo if (warn) { G_sprint(self, PRINT_HIGH, "no weapon\n"); } return false; } if (am && !self->race_chasecam) { // don't have the ammo if (warn) { G_sprint(self, PRINT_HIGH, "not enough ammo\n"); } return false; } return true; } /* ============ W_ChangeWeapon ============ */ qbool W_ChangeWeapon(int wp) { int it, am, fl = 0; if ((g_globalvars.time < self->attack_finished) && wp != 22) { return false; } it = self->s.v.items; am = 0; switch (wp) { case 1: // ctf shortcut for newbs: selecting axe when you already have it switches to grapple if (isCTF() && (self->s.v.weapon == IT_AXE) && cvar("k_ctf_hook")) { fl = IT_HOOK; } else { fl = IT_AXE; } break; case 2: fl = IT_SHOTGUN; if (self->s.v.ammo_shells < 1) { am = 1; } break; case 3: fl = IT_SUPER_SHOTGUN; if (self->s.v.ammo_shells < 2) { am = 1; } break; case 4: fl = IT_NAILGUN; if (self->s.v.ammo_nails < 1) { am = 1; } break; case 5: fl = IT_SUPER_NAILGUN; if (self->s.v.ammo_nails < 2) { am = 1; } break; case 6: fl = IT_GRENADE_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case 7: fl = IT_ROCKET_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case 8: fl = IT_LIGHTNING; if (self->s.v.ammo_cells < 1) { am = 1; } break; case 22: fl = IT_HOOK; if (self->s.v.weapon != IT_HOOK) { if (self->hook_out) { GrappleReset(self->hook); } self->hook_out = false; self->on_hook = false; } break; default: break; } if (!(it & fl) && !self->race_chasecam) // don't have the weapon { G_sprint(self, PRINT_HIGH, "no weapon\n"); } else if (am && !self->race_chasecam) // don't have the ammo { G_sprint(self, PRINT_HIGH, "not enough ammo\n"); } else { // // set weapon, set ammo // self->s.v.weapon = fl; W_SetCurrentAmmo(); } return true; } /* ============ CycleWeaponCommand Go to the next weapon with ammo ============ */ qbool CycleWeaponCommand(void) { int i, it, am; if (g_globalvars.time < self->attack_finished) { return false; } it = self->s.v.items; for (i = 0; i < 20; i++) // qqshka, 20 is just from head, but prevent infinite loop { am = 0; switch ((int)self->s.v.weapon) { case IT_LIGHTNING: self->s.v.weapon = IT_AXE; break; case IT_AXE: self->s.v.weapon = IT_HOOK; break; case IT_HOOK: self->s.v.weapon = IT_SHOTGUN; if (self->s.v.ammo_shells < 1) { am = 1; } break; case IT_SHOTGUN: self->s.v.weapon = IT_SUPER_SHOTGUN; if (self->s.v.ammo_shells < 2) { am = 1; } break; case IT_SUPER_SHOTGUN: self->s.v.weapon = IT_NAILGUN; if (self->s.v.ammo_nails < 1) { am = 1; } break; case IT_NAILGUN: self->s.v.weapon = IT_SUPER_NAILGUN; if (self->s.v.ammo_nails < 2) { am = 1; } break; case IT_SUPER_NAILGUN: self->s.v.weapon = IT_GRENADE_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case IT_GRENADE_LAUNCHER: self->s.v.weapon = IT_ROCKET_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case IT_ROCKET_LAUNCHER: self->s.v.weapon = IT_LIGHTNING; if (self->s.v.ammo_cells < 1) { am = 1; } break; } if ((it & (int)self->s.v.weapon) && (am == 0)) { W_SetCurrentAmmo(); return true; } } return true; } /* ============ CycleWeaponReverseCommand Go to the prev weapon with ammo ============ */ qbool CycleWeaponReverseCommand(void) { int i, it, am; if (g_globalvars.time < self->attack_finished) { return false; } it = self->s.v.items; for (i = 0; i < 20; i++) // qqshka, 20 is just from head, but prevent infinite loop { am = 0; switch ((int)self->s.v.weapon) { case IT_LIGHTNING: self->s.v.weapon = IT_ROCKET_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case IT_ROCKET_LAUNCHER: self->s.v.weapon = IT_GRENADE_LAUNCHER; if (self->s.v.ammo_rockets < 1) { am = 1; } break; case IT_GRENADE_LAUNCHER: self->s.v.weapon = IT_SUPER_NAILGUN; if (self->s.v.ammo_nails < 2) { am = 1; } break; case IT_SUPER_NAILGUN: self->s.v.weapon = IT_NAILGUN; if (self->s.v.ammo_nails < 1) { am = 1; } break; case IT_NAILGUN: self->s.v.weapon = IT_SUPER_SHOTGUN; if (self->s.v.ammo_shells < 2) { am = 1; } break; case IT_SUPER_SHOTGUN: self->s.v.weapon = IT_SHOTGUN; if (self->s.v.ammo_shells < 1) { am = 1; } break; case IT_SHOTGUN: self->s.v.weapon = IT_HOOK; break; case IT_HOOK: self->s.v.weapon = IT_AXE; break; case IT_AXE: self->s.v.weapon = IT_LIGHTNING; if (self->s.v.ammo_cells < 1) { am = 1; } break; } if ((it & (int)self->s.v.weapon) && (am == 0)) { W_SetCurrentAmmo(); return true; } } return true; } void kfjump(void); void krjump(void); int CaptainImpulses(void) { if (k_captains != 2) { return 2; // s: return 2 if nothing interesting } // ok - below possible captain stuff if ((self->s.v.impulse > MAX_CLIENTS) || !capt_num(self)) { return 0; // s: return 0 if captain mode is set and no captain things were entered } return 1; // s: return 1 if it's a player picker impulse } /* ============ ImpulseCommands ============ */ void ImpulseCommands(void) { qbool clear = true; int capt, impulse = self->s.v.impulse; if (self->ct != ctPlayer) { self->s.v.impulse = impulse = 0; } if (!impulse) { return; } capt = CaptainImpulses(); if (!capt) { ; // empty } else if (capt == 1) { CaptainPickPlayer(); } else if (self->k_adminc && (impulse >= 1) && (impulse <= 9)) { AdminImpBot(); } else if (((impulse >= 1) && (impulse <= 8)) || (impulse == 22)) { clear = W_ChangeWeapon(impulse); } else if (impulse == 9) { ; // removed } else if (impulse == 10) { clear = CycleWeaponCommand(); } else if (impulse == 11) { ; // removed } else if (impulse == 12) { clear = CycleWeaponReverseCommand(); } else if (impulse == 156) { kfjump(); } else if (impulse == 164) { krjump(); } if (clear) { self->s.v.impulse = 0; } } void can_prewar_msg(char *msg) { if (g_globalvars.time > self->k_msgcount) { self->k_msgcount = g_globalvars.time + 1; stuffcmd(self, "bf\n"); G_sprint(self, 2, "%s\n", msg); } } // if fire == false then can_prewar is called for jump qbool can_prewar(qbool fire) { int k_prewar; if (match_in_progress == 2) { return true; // u can fire/jump } k_prewar = cvar("k_prewar"); switch (k_prewar) { case 1: goto captains; // probably u can fire/jump case 2: if (self->ready) { goto captains; } // probably u can jump/fire if ready if (fire) { can_prewar_msg(redtext("type ready to enable fire")); } else { can_prewar_msg(redtext("type ready to enable jumps")); } return false; // u can't fire/jump if _not_ ready case 0: default: if (fire) { // u can't fire can_prewar_msg(redtext("can't fire, prewar is disabled")); return false; } goto captains; // probably u can jump } captains: if (k_captains != 2) { return true; // u can fire/jump } if (fire) { // u can't fire can_prewar_msg(redtext("can't fire until in captains mode")); return false; } return true; // u can jump } /* ============ W_WeaponFrame Called every frame so impulse events can be handled as well as possible ============ */ void W_WeaponFrame(void) { if ((self->spawn_time + 0.05) > g_globalvars.time) { return; // discard +attack till 50 ms after respawn, like ktpro } if (self->wreg_attack) // client simulate +attack via "cmd wreg" feature { self->s.v.button0 = true; } if (isRACE()) { if ((self->ct == ctPlayer) && !self->racer && race.status) { if (self->s.v.button0) { ChasecamToggleButton(); } else { self->s.v.flags = ((int)(self->s.v.flags)) | FL_ATTACKRELEASED; } return; } } if (isCA()) { ClanArenaTrackingToggleButton(); } ImpulseCommands(); if (!race_weapon_allowed(self)) { return; } if (g_globalvars.time < self->attack_finished) { return; } // check for attack if (self->s.v.button0 && !intermission_running) { if (!readytostart()) { return; // RA restrictions } if (!CA_can_fire(self)) { return; // CA restrictions } if ((match_in_progress == 1) || !can_prewar(true)) { return; } SuperDamageSound(); W_Attack(); } } /* ======== SuperDamageSound Plays sound if needed ======== */ void SuperDamageSound(void) { if (self->super_damage_finished > g_globalvars.time) { if (self->super_sound < g_globalvars.time) { self->super_sound = g_globalvars.time + 1; // Play 8x sound if quad + strength rune if (self->ctf_flag & CTF_RUNE_STR) { sound(self, CHAN_AUTO, "rune/rune22.wav", 1, ATTN_NORM); } else { sound(self, CHAN_AUTO, "items/damage3.wav", 1, ATTN_NORM); } } } else if (self->ctf_flag & CTF_RUNE_STR) { if (self->super_sound < g_globalvars.time) { self->super_sound = g_globalvars.time + 1; sound(self, CHAN_AUTO, "rune/rune2.wav", 1, ATTN_NORM); } } return; } QW-Group-ktx-d05d6ca/src/world.c000066400000000000000000001442701475442401000165220ustar00rootroot00000000000000/* * QWProgs-DM * Copyright (C) 2004 [sd] angel * * This code is based on QuakeWorld DM mod code by 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 * * * $Id$ */ #include "g_local.h" #ifdef BOT_SUPPORT #endif void RegisterSkillVariables(void); void SUB_regen(void); void CheckAll(void); void FixSpecWizards(void); void FixSayFloodProtect(void); void FixRules(void); void ShowSpawnPoints(void); void r_route(void); void LoadMap(void); void SP_trigger_custom_push(void); #define MAX_BODYQUE 4 gedict_t *bodyque[MAX_BODYQUE]; int bodyque_head; void InitBodyQue(void) { int i; bodyque[0] = spawn(); bodyque[0]->classname = "bodyque"; for (i = 1; i < MAX_BODYQUE; i++) { bodyque[i] = spawn(); bodyque[i]->classname = "bodyque"; bodyque[i - 1]->s.v.owner = EDICT_TO_PROG(bodyque[i]); } bodyque[MAX_BODYQUE - 1]->s.v.owner = EDICT_TO_PROG(bodyque[0]); bodyque_head = 0; } // make a body que entry for the given ent so the ent can be // respawned elsewhere void CopyToBodyQue(gedict_t *ent) { if (ISLIVE(ent)) { return; // no corpse, since here may be frame where player live, so u got standing player model, will looks like bug } VectorCopy(ent->s.v.angles, bodyque[bodyque_head]->s.v.angles); VectorCopy(ent->s.v.velocity, bodyque[bodyque_head]->s.v.velocity); bodyque[bodyque_head]->model = ent->model; bodyque[bodyque_head]->s.v.modelindex = ent->s.v.modelindex; bodyque[bodyque_head]->s.v.frame = ent->s.v.frame; bodyque[bodyque_head]->s.v.colormap = ent->s.v.colormap; // once i got here MOVETYPE_WALK, so server crashed, probaly here must be always toss movement bodyque[bodyque_head]->s.v.movetype = /* ent->s.v.movetype */MOVETYPE_TOSS; bodyque[bodyque_head]->s.v.flags = 0; setorigin(bodyque[bodyque_head], PASSVEC3(ent->s.v.origin)); setsize(bodyque[bodyque_head], PASSVEC3(ent->s.v.mins), PASSVEC3(ent->s.v.maxs)); if (++bodyque_head >= MAX_BODYQUE) { bodyque_head = 0; } } void ClearBodyQue(void) { int i; for (i = 0; i < MAX_BODYQUE; i++) { bodyque[i]->model = ""; bodyque[i]->s.v.modelindex = 0; bodyque[i]->s.v.frame = 0; bodyque[i]->s.v.movetype = MOVETYPE_NONE; } bodyque_head = 0; } void CheckDefMap(void) { int player_count = CountPlayers(); int bot_count = CountBots(); if (((player_count == 0) || (player_count == bot_count)) && !cvar("k_lockmap")) { char *s1 = cvar_string("k_defmap"); // reload map to default one if we are not on it alredy, in case of intermission reload anyway if (!strnull(s1) && strneq(s1, mapname)) { changelevel(s1); } else if (intermission_running || (player_count == bot_count && bot_count)) { changelevel(mapname); } } ent_remove(self); } void Spawn_DefMapChecker(float timeout) { gedict_t *e; for (e = world; (e = find(e, FOFCLSN, "mapguard"));) { ent_remove(e); } if (k_matchLess && !isCTF()) // no defmap in matchLess mode, unless CTF { return; } e = spawn(); e->classname = "mapguard"; e->s.v.owner = EDICT_TO_PROG(world); e->think = (func_t) CheckDefMap; e->s.v.nextthink = g_globalvars.time + max(0.0001, timeout); } float max_map_uptime = 3600 * 12; // 12 hours void Check_LongMapUptime(void) { if (match_in_progress) { return; // no no no, not even bother with this during match } if (max_map_uptime > g_globalvars.time) { return; // seems all ok } max_map_uptime += (60 * 5); // so if map reloading fail, we repeat it after some time if (CountPlayers() && (CountPlayers() != CountBots())) { // oh, here players, warn but not reload G_bprint(2, "\x87%s Long map uptime detected, reload map please!\n", redtext("WARNING:")); return; } G_bprint(2, "Long map uptime, reloading\n"); changelevel(mapname); } void SP_item_artifact_super_damage(void); void SP_worldspawn(void) { char *s; G_SpawnString("classname", "", &s); if (Q_stricmp(s, "worldspawn")) { G_Error("SP_worldspawn: The first entity isn't 'worldspawn'"); } world->classname = "worldspawn"; InitBodyQue(); if (!Q_stricmp(self->model, "maps/e1m8.bsp")) { trap_cvar_set("sv_gravity", "100"); } else if (!Q_stricmp(self->model, "maps/bunmoo3.bsp")) { trap_cvar_set("sv_gravity", "150"); } else if (!Q_stricmp(self->model, "maps/lowgrav.bsp")) { trap_cvar_set("sv_gravity", "150"); } else { trap_cvar_set("sv_gravity", "800"); } // the area based ambient sounds MUST be the first precache_sounds // player precaches W_Precache(); // get weapon precaches // sounds used from C physics code trap_precache_sound("demon/dland2.wav"); // landing thud trap_precache_sound("misc/h2ohit1.wav"); // landing splash // setup precaches allways needed trap_precache_sound("items/itembk2.wav"); // item respawn sound trap_precache_sound("player/plyrjmp8.wav"); // player jump trap_precache_sound("player/land.wav"); // player landing trap_precache_sound("player/land2.wav"); // player hurt landing trap_precache_sound("player/drown1.wav"); // drowning pain trap_precache_sound("player/drown2.wav"); // drowning pain trap_precache_sound("player/gasp1.wav"); // gasping for air trap_precache_sound("player/gasp2.wav"); // taking breath trap_precache_sound("player/h2odeath.wav"); // drowning death trap_precache_sound("misc/talk.wav"); // talk trap_precache_sound("player/teledth1.wav"); // telefrag trap_precache_sound("misc/r_tele1.wav"); // teleport sounds trap_precache_sound("misc/r_tele2.wav"); trap_precache_sound("misc/r_tele3.wav"); trap_precache_sound("misc/r_tele4.wav"); trap_precache_sound("misc/r_tele5.wav"); trap_precache_sound("weapons/lock4.wav"); // ammo pick up trap_precache_sound("weapons/pkup.wav"); // weapon up trap_precache_sound("items/armor1.wav"); // armor up trap_precache_sound("weapons/lhit.wav"); //lightning trap_precache_sound("weapons/lstart.wav"); //lightning start trap_precache_sound("items/damage3.wav"); trap_precache_sound("misc/power.wav"); //lightning for boss // player gib sounds trap_precache_sound("player/gib.wav"); // player gib sound trap_precache_sound("player/udeath.wav"); // player gib sound trap_precache_sound("player/tornoff2.wav"); // gib sound // player pain sounds trap_precache_sound("player/pain1.wav"); trap_precache_sound("player/pain2.wav"); trap_precache_sound("player/pain3.wav"); trap_precache_sound("player/pain4.wav"); trap_precache_sound("player/pain5.wav"); trap_precache_sound("player/pain6.wav"); // player death sounds trap_precache_sound("player/death1.wav"); trap_precache_sound("player/death2.wav"); trap_precache_sound("player/death3.wav"); trap_precache_sound("player/death4.wav"); trap_precache_sound("player/death5.wav"); trap_precache_sound("boss1/sight1.wav"); // ax sounds trap_precache_sound("weapons/ax1.wav"); // ax swoosh trap_precache_sound("player/axhit1.wav"); // ax hit meat trap_precache_sound("player/axhit2.wav"); // ax hit world trap_precache_sound("player/h2ojump.wav"); // player jumping into water trap_precache_sound("player/slimbrn2.wav"); // player enter slime trap_precache_sound("player/inh2o.wav"); // player enter water trap_precache_sound("player/inlava.wav"); // player enter lava trap_precache_sound("misc/outwater.wav"); // leaving water sound trap_precache_sound("player/lburn1.wav"); // lava burn trap_precache_sound("player/lburn2.wav"); // lava burn trap_precache_sound("misc/water1.wav"); // swimming trap_precache_sound("misc/water2.wav"); // swimming // Invulnerability sounds trap_precache_sound("items/protect.wav"); trap_precache_sound("items/protect2.wav"); trap_precache_sound("items/protect3.wav"); // Invisibility sounds trap_precache_sound("items/inv1.wav"); trap_precache_sound("items/inv2.wav"); trap_precache_sound("items/inv3.wav"); // quad sounds - need this due to aerowalk customize trap_precache_sound("items/damage.wav"); trap_precache_sound("items/damage2.wav"); trap_precache_sound("items/damage3.wav"); // ctf #ifdef CTF_RELOADMAP if (isCTF()) // precache only if CTF is really on #else if (k_allowed_free_modes & UM_CTF) // precache if CTF even only possible, doesn't matter if it is on or off currently #endif { trap_precache_sound("weapons/chain1.wav"); trap_precache_sound("weapons/chain2.wav"); trap_precache_sound("weapons/chain3.wav"); trap_precache_sound("weapons/bounce2.wav"); trap_precache_sound("misc/flagtk.wav"); trap_precache_sound("misc/flagcap.wav"); trap_precache_sound("doors/runetry.wav"); trap_precache_sound("blob/land1.wav"); trap_precache_sound("rune/rune1.wav"); trap_precache_sound("rune/rune2.wav"); trap_precache_sound("rune/rune22.wav"); trap_precache_sound("rune/rune3.wav"); trap_precache_sound("rune/rune4.wav"); } if (cvar("k_instagib_custom_models")) // precache if custom models actived in config, even if instagib not yet activated { trap_precache_model("progs/v_coil.mdl"); trap_precache_sound("weapons/coilgun.wav"); } trap_precache_sound("ambience/windfly.wav"); trap_precache_model(Spawn_GetModel()); trap_precache_model("progs/player.mdl"); trap_precache_model("progs/eyes.mdl"); trap_precache_model("progs/h_player.mdl"); trap_precache_model("progs/gib1.mdl"); trap_precache_model("progs/gib2.mdl"); trap_precache_model("progs/gib3.mdl"); trap_precache_model("progs/s_bubble.spr"); // drowning bubbles trap_precache_model("progs/s_explod.spr"); // sprite explosion trap_precache_model("progs/v_axe.mdl"); trap_precache_model("progs/v_shot.mdl"); trap_precache_model("progs/v_nail.mdl"); trap_precache_model("progs/v_rock.mdl"); trap_precache_model("progs/v_shot2.mdl"); trap_precache_model("progs/v_nail2.mdl"); trap_precache_model("progs/v_rock2.mdl"); // FIXME: checkextension in mvdsv? // vw_available = checkextension("ZQ_VWEP"); vw_available = 1; if (cvar("k_allow_vwep") && vw_available) { // precache our vwep models trap_precache_vwep_model("progs/vwplayer.mdl"); // vwep-enabled player model to use trap_precache_vwep_model("progs/w_axe.mdl"); // index 2 trap_precache_vwep_model("progs/w_shot.mdl"); // index 3 trap_precache_vwep_model("progs/w_shot2.mdl"); trap_precache_vwep_model("progs/w_nail.mdl"); trap_precache_vwep_model("progs/w_nail2.mdl"); trap_precache_vwep_model("progs/w_rock.mdl"); trap_precache_vwep_model("progs/w_rock2.mdl"); trap_precache_vwep_model("progs/w_light.mdl"); if (cvar("k_instagib_custom_models")) { trap_precache_vwep_model("progs/w_coil.mdl"); //index 10 } trap_precache_vwep_model("-"); // null vwep model } vw_enabled = vw_available && cvar("k_allow_vwep") && cvar("k_vwep"); trap_precache_model("progs/bolt.mdl"); // for lightning gun trap_precache_model("progs/bolt2.mdl"); // for lightning gun trap_precache_model("progs/bolt3.mdl"); // for boss shock trap_precache_model("progs/lavaball.mdl");// for testing (also for race, if ctf models disabled) trap_precache_model("progs/missile.mdl"); trap_precache_model("progs/grenade.mdl"); trap_precache_model("progs/spike.mdl"); trap_precache_model("progs/s_spike.mdl"); trap_precache_model("progs/backpack.mdl"); trap_precache_model("progs/zom_gib.mdl"); trap_precache_model("progs/v_light.mdl"); trap_precache_model("progs/wizard.mdl"); // ctf if (k_ctf_custom_models) { trap_precache_model("progs/v_star.mdl"); trap_precache_model("progs/bit.mdl"); trap_precache_model("progs/star.mdl"); trap_precache_model("progs/flag.mdl"); } else { trap_precache_model("progs/v_spike.mdl"); } // this used in alot of places, so precache it anyway trap_precache_model("progs/w_g_key.mdl"); trap_precache_model("progs/w_s_key.mdl"); // ctf runes, actually may be precached anyway, since come with full quake distro if (k_allowed_free_modes & UM_CTF) { trap_precache_model("progs/end1.mdl"); trap_precache_model("progs/end2.mdl"); trap_precache_model("progs/end3.mdl"); trap_precache_model("progs/end4.mdl"); } // quad mdl - need this due to aerowalk customize trap_precache_model("progs/quaddama.mdl"); // pent mdl - need this for race and coop trap_precache_model("progs/invulner.mdl"); if (cvar("k_race_custom_models")) { // precache if custom models actived in config trap_precache_model("progs/start.mdl"); trap_precache_model("progs/check.mdl"); trap_precache_model("progs/finish.mdl"); } // pent sounds - need for coop trap_precache_sound("items/protect.wav"); trap_precache_sound("items/protect2.wav"); trap_precache_sound("items/protect3.wav"); // suit wav - need this for race trap_precache_sound("items/suit.wav"); trap_precache_model("progs/suit.mdl"); trap_precache_sound("items/suit2.wav"); // for race trap_precache_sound("knight/sword2.wav"); trap_precache_sound("boss2/idle.wav"); trap_precache_sound("boss2/sight.wav"); trap_precache_sound("ambience/thunder1.wav"); trap_precache_sound("enforcer/enfire.wav"); trap_precache_sound("zombie/z_miss.wav"); // g_models required for yawnmode weapondrops trap_precache_model("progs/g_shot.mdl"); trap_precache_model("progs/g_nail.mdl"); trap_precache_model("progs/g_nail2.mdl"); trap_precache_model("progs/g_rock.mdl"); trap_precache_model("progs/g_rock2.mdl"); trap_precache_model("progs/g_light.mdl"); // for instagib bonus trap_precache_model("progs/invisibl.mdl"); // various items. // health 15 trap_precache_model("maps/b_bh10.bsp"); trap_precache_sound("items/r_item1.wav"); // health 25 trap_precache_model("maps/b_bh25.bsp"); trap_precache_sound("items/health1.wav"); // megahealth trap_precache_model("maps/b_bh100.bsp"); trap_precache_sound("items/r_item2.wav"); // armor trap_precache_model("progs/armor.mdl"); // shells 20 trap_precache_model("maps/b_shell0.bsp"); // shells 40 trap_precache_model("maps/b_shell1.bsp"); // nails 20/25 trap_precache_model("maps/b_nail0.bsp"); // nails 40/50 trap_precache_model("maps/b_nail1.bsp"); // rockets 5 trap_precache_model("maps/b_rock0.bsp"); // rockets 10 trap_precache_model("maps/b_rock1.bsp"); // cells 6 trap_precache_model("maps/b_batt0.bsp"); // cells 12 trap_precache_model("maps/b_batt1.bsp"); // // Setup light animation tables. 'a' is total darkness, 'z' is maxbright. // // 0 normal trap_lightstyle(0, "m"); // 1 FLICKER (first variety) trap_lightstyle(1, "mmnmmommommnonmmonqnmmo"); // 2 SLOW STRONG PULSE trap_lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); // 3 CANDLE (first variety) trap_lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); // 4 FAST STROBE trap_lightstyle(4, "mamamamamama"); // 5 GENTLE PULSE 1 trap_lightstyle(5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj"); // 6 FLICKER (second variety) trap_lightstyle(6, "nmonqnmomnmomomno"); // 7 CANDLE (second variety) trap_lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm"); // 8 CANDLE (third variety) trap_lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); // 9 SLOW STROBE (fourth variety) trap_lightstyle(9, "aaaaaaaazzzzzzzz"); // 10 FLUORESCENT FLICKER trap_lightstyle(10, "mmamammmmammamamaaamammma"); // 11 SLOW PULSE NOT FADE TO BLACK trap_lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); // styles 32-62 are assigned by the light program for switchable lights // 63 testing trap_lightstyle(63, "a"); match_over = 0; k_standby = 0; localcmd("serverinfo status Standby\n"); Spawn_DefMapChecker(cvar("_k_worldspawns") == 1 ? 0.5 : 60 + g_random() * 30); if (!k_matchLess) // skip practice in matchLess mode { if (cvar("srv_practice_mode")) // #practice mode# { SetPractice(cvar("srv_practice_mode"), NULL); // may not reload map } } // Set hoonymode by default if flags set if (world->hoony_timelimit || !strnull(world->hoony_defaultwinner)) { UserMode(-8); HM_initialise_rounds(); } } void ShowSpawnPoints(void); void Customize_Maps(void) { gedict_t *p; jumpf_flag = -650; if (streq("q1dm17", mapname)) { jumpf_flag = -1000; } // spawn quad if map is aerowalk in this case if (cvar("add_q_aerowalk") && streq("aerowalk", mapname)) { gedict_t *swp = self; self = spawn(); setorigin(self, -912.6f, -898.9f, 248.0f); // oh, ktpro like self->s.v.owner = EDICT_TO_PROG(world); SP_item_artifact_super_damage(); self = swp; // restore self } if (!cvar("k_end_tele_spawn") && streq("end", mapname) #ifdef BOT_SUPPORT && !bots_enabled() #endif ) { vec3_t TS_ORIGIN = { -392, 608, 40 }; // tele spawn for (p = world; (p = find(p, FOFCLSN, "info_player_deathmatch"));) { if (VectorCompare(p->s.v.origin, TS_ORIGIN)) { ent_remove(p); break; } } } // correcting some teleport destintions on death32c (c) ktpro if (streq("death32c", mapname)) { for (p = world; (p = find(p, FOFCLSN, "trigger_teleport"));) { if (streq("dm220", p->target)) { p->target = "dm6t1"; } } } // Modify some ctf maps if (k_allowed_free_modes & UM_CTF) { if (!cvar("k_ctf_based_spawn") && (find_cnt(FOFCLSN, "info_player_deathmatch") <= 1)) { G_sprint(self, 2, "Spawn on base enforced due to map limitation\n"); cvar_fset("k_ctf_based_spawn", 1); } if (streq("ctf8", mapname)) { // fix/remove some bad spawns from ctf8 vec3_t spawn1 = { 1704, -540, 208 }; // blue spawn in red base vec3_t spawn2 = { -1132, -72, 208 }; // red spawn in blue base vec3_t spawn3 = { 660, 256, 40 }; // red spawn at quad for (p = world; (p = find(p, FOFCLSN, "info_player_team2"));) { if (VectorCompare(p->s.v.origin, spawn1)) { p->classname = "info_player_team1"; break; } } for (p = world; (p = find(p, FOFCLSN, "info_player_team1"));) { if (VectorCompare(p->s.v.origin, spawn2)) { p->classname = "info_player_team2"; break; } } for (p = world; (p = find(p, FOFCLSN, "info_player_team1"));) { if (VectorCompare(p->s.v.origin, spawn3)) { ent_remove(p); break; } } } } // modify slide8 to make it possible to complete in race mode if (streq(mapname, "slide8")) { gedict_t *push, *oldself, *ent; // create extra push before lava pit push = spawn(); if (!push) { return; } // Create push over the lava pit VectorSet(push->s.v.origin, -2110, 2550, -850); VectorSet(push->s.v.size, 250, 250, 50); VectorSet(push->s.v.movedir, -0.5, 0, 0.5); push->speed = 120; oldself = self; self = push; SP_trigger_custom_push(); self = oldself; // Remove hurt indicators around lava pit for (ent = world; (ent = findradius_ignore_solid(ent, push->s.v.origin, 300)); /**/) { if (streq(ent->classname, "trigger_hurt")) { ent_remove(ent); } } } if (cvar("k_spm_show")) { ShowSpawnPoints(); } if (isRACE()) { r_route(); } } // create cvar via 'set' command // FIXME: unfortunately with current API I can't check if cvar already exist qbool RegisterCvarEx(const char *var, const char *defaultstr) { if (!strnull(cvar_string(var))) { // G_cprint("RegisterCvar: \"%s\" already exist, value is \"%s\"\n", var, cvar_string( var )); return false; } else { // FIXME: some hack to check if cvar already exist, this check may give wrong results // thats all i can do with current api char *save = cvar_string(var); cvar_set(var, "~SomEHacK~~SomEHacK~"); if (!strnull(cvar_string(var))) { // ok, cvar exist but was empty cvar_set(var, save); // restore empty string %) // G_cprint("RegisterCvar: \"%s\" already exist\n", var); return false; } // but cvar_set may fail, if cvar is ROM for example // so, if cvar is empty and ROM we can't guess is this cvar exist } // G_cprint("RegisterCvar: \"%s\" registered\n", var); localcmd("set \"%s\" \"%s\"\n", var, defaultstr); trap_executecmd(); return true; } // like RegisterCvarEx, but uses "" for default value qbool RegisterCvar(const char *var) { return RegisterCvarEx(var, ""); } // in the first frame - even world is not spawned yet void FirstFrame(void) { int i, um_idx; qbool matchless_was_forced = false; if (framecount != 1) { return; } // clear buffer trap_executecmd(); // register mod cvars RegisterCvarEx("maxfps", "77"); // well, got tired from serverinfo, let it be cvar (mvdsv have it now too so it should just set it) #ifdef HITBOXCHECK RegisterCvarEx("k_hitboxcheck_bullets", "32"); // DEBUG: help me test hitbox of the player with modified shot gun #endif RegisterCvar("_k_last_xonx"); // internal usage, save last XonX command RegisterCvar("_k_lastmap"); // internal usage, name of last map RegisterCvar("_k_last_cycle_map"); // internal usage, name of last map in map cycle, // so we can back to map cycle if someone voted for map not in map cycle RegisterCvar("_k_worldspawns"); // internal usage, count of maps server spawned RegisterCvar("_k_pow_last"); // internal usage, k_pow from last map RegisterCvar("_k_nospecs"); // internal usage, will reject spectators connection RegisterCvar("k_noitems"); RegisterCvar("k_random_maplist"); // select random map from k_ml_XXX variables. RegisterCvar("k_mode"); RegisterCvar("k_defmode"); RegisterCvar("k_auto_xonx"); // switch XonX mode dependant on players + specs count RegisterCvar("k_matchless"); RegisterCvar("k_matchless_countdown"); RegisterCvar("k_matchless_max_idle_time"); // maximum time user can be idle in matchless mode RegisterCvar("k_use_matchless_dir"); // use configs/usermodes/matchless instead of configs/usermodes/ffa in matchless mode RegisterCvar("k_disallow_kfjump"); RegisterCvar("k_disallow_krjump"); RegisterCvar("k_lock_hdp"); RegisterCvar("k_disallow_weapons"); RegisterCvar("k_force_mapcycle"); // will use mapcycle even when /deathmatch 0 RegisterCvarEx("k_on_start_f_modified", "1"); RegisterCvarEx("k_on_start_f_ruleset", "1"); RegisterCvarEx("k_on_start_f_version", "1"); RegisterCvarEx("k_on_end_f_modified", "1"); RegisterCvarEx("k_on_end_f_ruleset", "1"); RegisterCvarEx("k_on_end_f_version", "1"); RegisterCvar("k_pow"); RegisterCvarEx("k_pow_q", "1"); // quad RegisterCvarEx("k_pow_p", "1"); // pent RegisterCvarEx("k_pow_r", "1"); // ring RegisterCvarEx("k_pow_s", "1"); // suit RegisterCvar("k_pow_min_players"); RegisterCvar("k_pow_check_time"); RegisterCvarEx("k_pow_pickup", "0");// allow multiple pickup of same powerup - off by default RegisterCvar("allow_spec_wizard"); RegisterCvar("k_no_wizard_animation"); // disallow wizard animation RegisterCvar("k_vp_break"); // votes percentage for stopping the match voting RegisterCvar("k_vp_admin"); // votes percentage for admin election RegisterCvar("k_vp_captain"); // votes percentage for captain election RegisterCvar("k_vp_coach"); // votes percentage for coachs election RegisterCvar("k_vp_map"); // votes percentage for map change voting RegisterCvar("k_vp_pickup"); // votes percentage for pickup voting RegisterCvar("k_vp_rpickup"); // votes percentage for rpickup voting RegisterCvar("k_vp_nospecs"); // votes percentage for nospecs voting RegisterCvar("k_vp_teamoverlay"); // votes percentage for teamoverlay voting RegisterCvar("k_vp_coop"); // votes percentage for coop voting RegisterCvar("k_vp_hookstyle"); // votes percentage for hookstyle voting RegisterCvar("k_vp_antilag"); // votes percentage for antilag voting RegisterCvar("k_no_vote_map"); // dis allow map voting in matcless mode, also disallow /next_map RegisterCvar("k_vp_privategame"); // temporarily force logins on the server RegisterCvar("k_end_tele_spawn"); // don't remove end tele spawn RegisterCvar("k_motd_time"); // motd time in seconds RegisterCvar("k_admincode"); RegisterCvarEx("k_prewar", "1"); RegisterCvar("k_lockmap"); RegisterCvar("k_fallbunny"); RegisterCvar("timing_players_time"); RegisterCvar("timing_players_action"); RegisterCvar("allow_timing"); RegisterCvarEx("demo_scoreslength", "10"); RegisterCvar("lock_practice"); RegisterCvar("k_defmap"); RegisterCvar("k_admins"); RegisterCvar("k_overtime"); RegisterCvar("k_exttime"); RegisterCvar("k_spw"); RegisterCvar("k_lockmin"); RegisterCvar("k_lockmax"); RegisterCvar("k_spectalk"); RegisterCvarEx("k_allowklist", "1"); RegisterCvarEx("k_allowtracklist", "1"); RegisterCvarEx("k_keepspectalkindemos", "0"); RegisterCvar("k_sayteam_to_spec"); RegisterCvar("k_dis"); RegisterCvar("dq"); RegisterCvar("dr"); RegisterCvar("dp"); RegisterCvar("k_frp"); RegisterCvar("k_highspeed"); RegisterCvar("k_freeze"); RegisterCvar("k_free_mode"); RegisterCvar("k_allowed_free_modes"); RegisterCvarEx("k_allow_vwep", "0"); RegisterCvarEx("k_vwep", "1"); RegisterCvar("allow_toggle_practice"); RegisterCvar("k_remove_end_hurt"); RegisterCvar("k_allowvoteadmin"); // RegisterCvar("k_maxrate"); -> now using sv_maxrate instead RegisterCvar("k_minrate"); RegisterCvar("k_sready"); RegisterCvarEx("k_spm_show", "1"); RegisterCvarEx("k_spm_glow", "0"); RegisterCvarEx("k_spm_custom_model", "0"); RegisterCvarEx("k_spm_color_rgba", "1.0 1.0 1.0 1.0"); RegisterCvar("k_entityfile"); // { hoonymode RegisterCvarEx("k_hoonymode", "0"); RegisterCvarEx("k_hoonyrounds", "6"); RegisterCvarEx("k_hoonymode_prevmap", ""); RegisterCvarEx("k_hoonymode_prevspawns", ""); // } // { freshteams dmm1 RegisterCvarEx("k_freshteams", "0"); RegisterCvarEx("k_freshteams_weapon_time", "20"); RegisterCvarEx("k_freshteams_fast_ammo", "0"); // ammo spawn times match weapons RegisterCvarEx("k_freshteams_limit_packs", "1"); // limit ammo in packs RegisterCvarEx("k_freshteams_pack_shells", "20"); // max shells in droppacks RegisterCvarEx("k_freshteams_pack_nails", "30"); // max nails in droppacks RegisterCvarEx("k_freshteams_pack_rockets", "5"); // max rockets in droppacks RegisterCvarEx("k_freshteams_pack_cells", "10"); // max cells in droppacks RegisterCvarEx("k_freshteams_limit_sweep_ammo", "1"); // limit ammo gained when sweeping a weapon RegisterCvarEx("k_freshteams_sweep_ng_ammo", "6"); RegisterCvarEx("k_freshteams_sweep_ssg_ammo", "1"); RegisterCvarEx("k_freshteams_sweep_sng_ammo", "6"); RegisterCvarEx("k_freshteams_sweep_gl_ammo", "1"); RegisterCvarEx("k_freshteams_sweep_rl_ammo", "1"); RegisterCvarEx("k_freshteams_sweep_lg_ammo", "3"); RegisterCvarEx("k_nosweep", "0"); // can't pick up weapons you already have in dmm1 // } // { race RegisterCvarEx("k_race", "0"); RegisterCvarEx("k_race_countdown", "2"); RegisterCvarEx("k_race_custom_models", "0"); RegisterCvarEx("k_race_autorecord", "1"); RegisterCvarEx("k_race_times_per_port", "0"); RegisterCvarEx("k_race_pace_headstart", "0.5"); RegisterCvarEx("k_race_pace_jumps", "0"); RegisterCvarEx("k_race_pace_resolution", "2"); RegisterCvarEx("k_race_pace_legal", "0"); RegisterCvarEx("k_race_pace_enabled", "0"); RegisterCvarEx("k_race_simultaneous", "0"); RegisterCvarEx("k_race_match", "0"); RegisterCvarEx("k_race_match_rounds", "9"); RegisterCvarEx("k_race_scoring_system", "0"); RegisterCvarEx("k_race_route_number", "0"); RegisterCvarEx("k_race_route_mapname", ""); //RegisterCvarEx("k_race_topscores", "10"); // } RegisterCvar("k_bzk"); RegisterCvar("k_btime"); RegisterCvar("k_idletime"); RegisterCvar("k_timetop"); RegisterCvar("k_membercount"); RegisterCvarEx("demo_tmp_record", "0"); RegisterCvar("demo_skip_ktffa_record"); RegisterCvar("k_demoname_date"); // add date to demo name, value is argument for strftime() function RegisterCvarEx("k_count", "10"); RegisterCvar("k_exclusive"); // stores whether players can join when a game is already in progress RegisterCvar("k_lockmode"); RegisterCvar("k_short_gib"); RegisterCvar("k_ann"); RegisterCvar("srv_practice_mode"); RegisterCvar("add_q_aerowalk"); RegisterCvar("k_noframechecks"); RegisterCvar("dmm4_invinc_time"); RegisterCvarEx("k_classic_shotgun", "1"); RegisterCvar("k_no_fps_physics"); //{ ctf RegisterCvar("k_ctf_custom_models"); RegisterCvar("k_ctf_hook"); RegisterCvar("k_ctf_hookstyle"); // loop through hookstyle settings RegisterCvar("k_ctf_runes"); RegisterCvarEx("k_ctf_rune_bounce", "3"); RegisterCvarEx("k_ctf_rune_power_str", "2.0"); RegisterCvarEx("k_ctf_rune_power_res", "2.0"); RegisterCvarEx("k_ctf_rune_power_rgn", "2.0"); RegisterCvarEx("k_ctf_rune_power_hst", "2.0"); RegisterCvar("k_ctf_ga"); RegisterCvar("k_ctf_based_spawn"); // spawn players on the base (red/blue) RegisterCvar("k_ctf_hurt_items"); //} RegisterCvar("k_spec_info"); RegisterCvar("k_midair"); RegisterCvarEx("k_midair_minheight", "1"); RegisterCvarEx("k_killquad", "0"); RegisterCvarEx("k_bloodfest", "0"); RegisterCvarEx("k_nightmare_pu", "0"); RegisterCvarEx("k_nightmare_pu_droprate", "0.15"); RegisterCvarEx("k_instagib", "0"); RegisterCvarEx("k_instagib_custom_models", "0"); RegisterCvarEx("k_cg_kb", "1"); RegisterCvar("k_rocketarena"); // rocket arena RegisterCvar("k_dmgfrags"); RegisterCvar("k_tp_tele_death"); // { Clan Arena RegisterCvarEx("k_clan_arena", "0"); RegisterCvarEx("k_clan_arena_rounds", "9"); RegisterCvarEx("k_clan_arena_max_respawns", "0"); // } // { upplayers/upspecs RegisterCvar("k_allowcountchange"); RegisterCvar("k_maxclients"); RegisterCvar("k_maxspectators"); // } RegisterCvar("k_ip_list"); // { cmd flood protection RegisterCvar("k_cmd_fp_count"); RegisterCvar("k_cmd_fp_per"); RegisterCvar("k_cmd_fp_for"); RegisterCvar("k_cmd_fp_kick"); RegisterCvar("k_cmd_fp_dontkick"); RegisterCvar("k_cmd_fp_disabled"); // } RegisterCvarEx("k_extralog_xsd_uri", "http://mirror.quakeworld.eu/ktx/ktxlog_0.1.xsd"); RegisterCvar("k_extralog"); RegisterCvar("k_demo_mintime"); RegisterCvar("k_dmm4_gren_mode"); RegisterCvarEx("k_fp", "1"); // say floodprot for players RegisterCvarEx("k_fp_spec", "3"); // say floodprot for spectators // { yawnmode implementation by Molgrum RegisterCvar("k_yawnmode"); RegisterCvar("k_teleport_cap"); // } RegisterCvar("k_teamoverlay"); // q3 like team overlay // { SP RegisterCvarEx("k_monster_spawn_time", "20"); // } RegisterCvar("_k_captteam1"); // internal mod usage RegisterCvar("_k_captcolor1"); // internal mod usage RegisterCvar("_k_captteam2"); // internal mod usage RegisterCvar("_k_captcolor2"); // internal mod usage RegisterCvar("_k_coachteam1"); // internal mod usage RegisterCvar("_k_coachteam2"); // internal mod usage RegisterCvar("_k_team1"); // internal mod usage RegisterCvar("_k_team2"); // internal mod usage RegisterCvar("_k_team3"); // internal mod usage RegisterCvar("_k_host"); // internal mod usage // { lastscores support RegisterCvar("__k_ls"); // current lastscore, really internal mod usage for (i = 0; i < MAX_LASTSCORES; i++) { RegisterCvar(va("__k_ls_m_%d", i)); // mode, really internal mod usage RegisterCvar(va("__k_ls_e1_%d", i)); // entry team/nick, really internal mod usage RegisterCvar(va("__k_ls_e2_%d", i)); // entry team/nick, really internal mod usage RegisterCvar(va("__k_ls_t1_%d", i)); // nicks, really internal mod usage RegisterCvar(va("__k_ls_t2_%d", i)); // nicks, really internal mod usage RegisterCvar(va("__k_ls_s_%d", i)); // scores, really internal mod usage } // } RegisterCvarEx("k_demotxt_format", "xml"); // what format for .txt files #ifdef BOT_SUPPORT // { frogbots support RegisterCvarEx(FB_CVAR_ENABLED, "0"); RegisterCvarEx(FB_CVAR_OPTIONS, "0"); RegisterCvarEx(FB_CVAR_AUTOADD_LIMIT, "0"); RegisterCvarEx(FB_CVAR_AUTOREMOVE_AT, "0"); RegisterCvarEx(FB_CVAR_AUTO_DELAY, "1"); RegisterCvarEx(FB_CVAR_SKILL, "10"); RegisterCvarEx(FB_CVAR_DEBUG, "0"); RegisterCvarEx(FB_CVAR_ADMIN_ONLY, "0"); RegisterCvarEx(FB_CVAR_FREEZE_PREWAR, "0"); RegisterCvarEx(FB_CVAR_HEALTH, "100"); RegisterCvarEx(FB_CVAR_WEAPON, "2"); RegisterCvarEx(FB_CVAR_BREAK_ON_DEATH, "1"); RegisterCvarEx(FB_CVAR_QUAD_MULTIPLIER, "4"); for (i = 0; i < MAX_CLIENTS; i++) { RegisterCvarEx(va("k_fb_name_%d", i), ""); RegisterCvarEx(va("k_fb_name_enemy_%d", i), ""); RegisterCvarEx(va("k_fb_name_team_%d", i), ""); } RegisterSkillVariables(); // } #endif RegisterCvar("k_no_scoreboard_ghosts"); RegisterCvar("k_lgcmode"); RegisterCvar("k_tot_mode"); // private games RegisterCvarEx("k_privategame", "0"); // whether it is currently on or off RegisterCvarEx("k_privategame_default", "0"); // what to set it to when resetting map RegisterCvarEx("k_privategame_voteable", "0"); // if set, players can vote for private games (require logins) RegisterCvarEx("k_privategame_allow_specs", "1"); // set the server to allow unauthed spectators RegisterCvarEx("k_privategame_force_reconnect", "1"); // when voting for private game, kick unauthed players // below globals changed only here k_matchLess = cvar("k_matchless"); k_matchLess_idle_time = cvar("k_matchless_max_idle_time") ? cvar("k_matchless_max_idle_time") : 0; k_matchLess_idle_warn = k_matchLess_idle_time - (k_matchLess_idle_time > 30 ? 30 : (k_matchLess_idle_time / 2)); if (!cvar("deathmatch") || cvar("coop")) { k_matchLess = 1; // treat coop or singleplayer as matchLess matchless_was_forced = true; } k_allowed_free_modes = cvar("k_allowed_free_modes"); // must be setup before UserMode(...) call if (k_matchLess) { k_allowed_free_modes |= UM_FFA; } // do not precache models if CTF is not really allowed k_ctf_custom_models = cvar("k_ctf_custom_models") && (k_allowed_free_modes & UM_CTF); // use k_defmode or reuse last mode from _k_last_xonx cvar_fset("_k_worldspawns", (int)cvar("_k_worldspawns") + 1); if (cvar("_k_worldspawns") == 1) { // server spawn first map sv_minping = cvar("sv_minping"); // remember, so we can broadcast changes if ((um_idx = um_idx_byname(cvar_string("k_defmode"))) >= 0) { cvar_fset("_k_last_xonx", um_idx + 1); // force exec configs for default user mode } } // since we remove k_srvcfgmap, we need configure different maps in matchless mode. // doing this by execiting configs like we do for "ffa" command in _non_ matchless mode if (k_matchLess) { if ((um_idx = um_idx_byname("ffa")) >= 0) { cvar_fset("_k_last_xonx", um_idx + 1); // force server call "ffa" user mode } else { G_bprint(2, "FirstFrame: um_idx_byname fail\n"); // shout cvar_fset("_k_last_xonx", 0); } } if ((cvar("_k_last_xonx") > 0) && strneq(cvar_string("_k_lastmap"), mapname)) { UserMode(-cvar("_k_last_xonx")); // auto call XonX command if map switched to another } // fix game rules, if cfgs some how misconfigured #ifdef CTF_RELOADMAP k_ctf = (cvar("k_mode") == gtCTF); // emulate CTF is active so FixRules is silent #endif if (matchless_was_forced) { trap_cvar_set_float("deathmatch", (deathmatch = 0)); } FixRules(); #ifdef CTF_RELOADMAP k_ctf = (k_mode == gtCTF); // finaly decide is ctf active or not k_ctf_custom_models = k_ctf_custom_models && (isCTF() || isRACE()); // precache only if CTF is really on #endif } // items spawned, but probably not solid yet void SecondFrame(void) { if (framecount != 2) { return; } Customize_Maps(); LocationInitialise(); HM_restore_spawns(); } void CheckSvUnlock(void) { if (k_sv_locktime && (k_sv_locktime < g_globalvars.time)) { G_bprint(2, "%s\n", redtext("server unlocked")); k_sv_locktime = 0; } } // switch XonX mode dependant on players + specs count void CheckAutoXonX(qbool use_time) { static int old_count = -666; // static static float last_check_time = 0; gedict_t *p; int count, um_idx = -1; if (!cvar("k_auto_xonx") || match_in_progress || k_matchLess || (use_time && ((g_globalvars.time - last_check_time) < 7)) /* allow users reconnect */ ) { return; } last_check_time = g_globalvars.time; for (count = 0, p = world; (p = find_client(p));) { if ((p->ct == ctPlayer) || ((p->ct == ctSpec) && p->ready)) { count++; } } if (count == old_count) { return; } switch (count) { case 0: case 1: case 2: case 3: um_idx = um_idx_byname("1on1"); break; case 4: case 5: um_idx = um_idx_byname("2on2"); break; case 6: case 7: um_idx = um_idx_byname("3on3"); break; case 8: case 9: um_idx = um_idx_byname("4on4"); break; default: um_idx = um_idx_byname("10on10"); break; } if ((um_idx >= 0) && ((cvar("_k_last_xonx") - 1) != um_idx)) { G_bprint(2, "Server decides to switch user mode\n"); UserMode(-(um_idx + 1)); } old_count = count; } // called when switching to/from ctf mode. void FixCTFItems(void) { static gameType_t old_k_mode = 0; // static static int k_ctf_runes = 0; // static static int k_ctf_hook = 0; // static if (framecount == 1) { // just init vars at first frame, after this we can determine if such vars changed old_k_mode = k_mode; k_ctf_runes = cvar("k_ctf_runes"); k_ctf_hook = cvar("k_ctf_hook"); return; } #ifdef CTF_RELOADMAP if ((old_k_mode != k_mode) && ((old_k_mode == gtCTF) || (k_mode == gtCTF))) { changelevel(mapname); } #endif if (match_in_progress) { return; // some optimization, ok ? } if (old_k_mode != k_mode) { RegenFlags(isCTF()); } if ((old_k_mode != k_mode) || (k_ctf_runes != cvar("k_ctf_runes")) || (framecount == 2)) { SpawnRunes(isCTF() && cvar("k_ctf_runes")); } if ((old_k_mode != k_mode) || (k_ctf_hook != cvar("k_ctf_hook"))) { AddHook(isCTF() && cvar("k_ctf_hook")); } old_k_mode = k_mode; k_ctf_runes = cvar("k_ctf_runes"); k_ctf_hook = cvar("k_ctf_hook"); } void FixRA(void) { static qbool old_k_rocketarena = false; // static if (framecount == 1) { return; // can't guess here something yet } if (framecount == 2) { old_k_rocketarena = isRA(); // ok, save RA status after world spawn, and start check status changes on 3-t frame return; } // do that even match in progress... if (old_k_rocketarena != isRA()) { old_k_rocketarena = isRA(); G_bprint(2, "%s: RA settings changed, map will be reloaded\n", redtext("WARNING")); changelevel(mapname); } } void FixRace(void) { static qbool old_k_race = false; // static if (framecount == 1) { return; // can't guess here something yet } if (framecount == 2) { old_k_race = isRACE(); return; } // do that even match in progress... if (old_k_race != isRACE()) { old_k_race = isRACE(); G_bprint(2, "%s: Race settings changed, map will be reloaded\n", redtext("WARNING")); changelevel(mapname); } } // serve k_pow and k_pow_min_players void FixPowerups(void) { static int k_pow = -1; // static static int k_pow_q = -1; // static static int k_pow_p = -1; // static static int k_pow_r = -1; // static static int k_pow_s = -1; // static qbool changed = false; int k_pow_new = Get_Powerups(); int k_pow_q_new = cvar("k_pow_q"); int k_pow_p_new = cvar("k_pow_p"); int k_pow_r_new = cvar("k_pow_r"); int k_pow_s_new = cvar("k_pow_s"); if ((k_pow != k_pow_new) || (k_pow_q != k_pow_q_new) || (k_pow_r != k_pow_r_new) || (k_pow_p != k_pow_p_new) || (k_pow_s != k_pow_s_new) || (framecount == 1)) // force on first frame { changed = true; k_pow = k_pow_new; k_pow_q = k_pow_q_new; k_pow_r = k_pow_r_new; k_pow_p = k_pow_p_new; k_pow_s = k_pow_s_new; } if (changed) { extern void hide_powerups(char *classname); extern void show_powerups(char *classname); if (k_pow && k_pow_p) { show_powerups("item_artifact_invulnerability"); } else { hide_powerups("item_artifact_invulnerability"); } if (k_pow && k_pow_q) { show_powerups("item_artifact_super_damage"); } else { hide_powerups("item_artifact_super_damage"); } if (k_pow && k_pow_s) { show_powerups("item_artifact_envirosuit"); } else { hide_powerups("item_artifact_envirosuit"); } if (k_pow && k_pow_r) { show_powerups("item_artifact_invisibility"); } else { hide_powerups("item_artifact_invisibility"); } } } void FixCmdFloodProtect(void) { k_cmd_fp_count = bound(0, cvar("k_cmd_fp_count"), MAX_FP_CMDS); k_cmd_fp_count = (k_cmd_fp_count ? k_cmd_fp_count : min(10, MAX_FP_CMDS)); k_cmd_fp_per = bound(0, cvar("k_cmd_fp_per"), 30); k_cmd_fp_per = (k_cmd_fp_per ? k_cmd_fp_per : 4); k_cmd_fp_for = bound(0, cvar("k_cmd_fp_for"), 30); k_cmd_fp_for = (k_cmd_fp_for ? k_cmd_fp_for : 5); k_cmd_fp_kick = bound(0, cvar("k_cmd_fp_kick"), 10); k_cmd_fp_kick = (k_cmd_fp_kick ? k_cmd_fp_kick : 4); k_cmd_fp_dontkick = bound(0, cvar("k_cmd_fp_dontkick"), 1); k_cmd_fp_disabled = bound(0, cvar("k_cmd_fp_disabled"), 1); } void FixSayTeamToSpecs(void) { int k_sayteam_to_spec = bound(0, cvar("k_sayteam_to_spec"), 3); int current_value = cvar("sv_sayteam_to_spec"); int desired_value = 0; switch (k_sayteam_to_spec) { case 0: desired_value = 0; break; case 1: desired_value = (match_in_progress ? 1 : 0); break; case 2: desired_value = (match_in_progress ? 0 : 1); break; default: desired_value = 1; break; } if (current_value != desired_value) { cvar_fset("sv_sayteam_to_spec", desired_value); } } // This function determines the actual game mode, include game type, and sub-mode, // which is part of the serverinfo reply. // Format is: mode-submode[-submode] void SetMode4ServerInfo(void) { char mode[64] = ""; const char *strCurrentUmode; // The parameter is (current_umode-1), because the UserModes_t enum has `umUnknown` as first element, // but the um_list[] array doesn't have an 'empty' first row strCurrentUmode = um_name_byidx(current_umode-1); if (strCurrentUmode != NULL) { strlcat(mode, (char *)strCurrentUmode, sizeof(mode)); if (isRACE()) { strlcat(mode, "-race", sizeof(mode)); } if (cvar("k_midair")) { strlcat(mode, "-midair", sizeof(mode)); } if (cvar("k_instagib")) { strlcat(mode, "-instagib", sizeof(mode)); } if (lgc_enabled()) { strlcat(mode, "-lgc", sizeof(mode)); } if (cvar("k_clan_arena") == 1) { strlcat(mode, "-ca", sizeof(mode)); } if (cvar("k_clan_arena") == 2) { strlcat(mode, "-wo", sizeof(mode)); } if (isRA()) { strlcat(mode, "-ra", sizeof(mode)); } if (cvar("k_dmm4_gren_mode")) { strlcat(mode, "-gm", sizeof(mode)); } if (cvar("k_dmgfrags")) { strlcat(mode, "-df", sizeof(mode)); } if (cvar("k_yawnmode")) { strlcat(mode, "-yw", sizeof(mode)); } if (cvar("k_bloodfest")) { strlcat(mode, "-bf", sizeof(mode)); } localcmd("serverinfo mode %s\n", mode); } } int skip_fixrules = 0; // check if server is misconfigured somehow, made some minimum fixage void FixRules(void) { extern void FixYawnMode(void); gameType_t km = k_mode = cvar("k_mode"); int k_tt = bound(0, cvar("k_timetop"), 600); int tp = teamplay = cvar("teamplay"); int tl = timelimit = cvar("timelimit"); int fl = fraglimit = cvar("fraglimit"); int dm = deathmatch = cvar("deathmatch"); int k_minr = bound(0, cvar("k_minrate"), 100000); int k_maxr = bound(0, cvar("sv_maxrate"), 500000); k_bloodfest = cvar("k_bloodfest"); k_killquad = cvar("k_killquad"); skill = cvar("skill"); coop = cvar("coop"); FixYawnMode(); // yawn mode k_maxspeed = cvar("sv_maxspeed"); FixCmdFloodProtect(); // cmd flood protect FixSayFloodProtect(); // say flood protect FixSayTeamToSpecs(); // k_sayteam_to_spec current_maxfps = cvar("maxfps"); if (current_maxfps != bound(50, current_maxfps, 1981)) { // current_maxfps = 72; // 2.30 standard current_maxfps = 77; // year 2007 standard cvar_fset("maxfps", current_maxfps); } if (skip_fixrules > 0) { skip_fixrules--; return; } // turn CTF off if CTF usermode is not allowed, due to precache_sound or precache_model if (isCTF() && !(k_allowed_free_modes & UM_CTF)) { cvar_fset("k_mode", (float)(k_mode = gtTeam)); } if (coop) { // if we are in coop, then deathmatch should be 0 if (deathmatch) { trap_cvar_set_float("deathmatch", (deathmatch = 0)); } // set some teamplay in coop mode. if (!teamplay) { trap_cvar_set_float("teamplay", (teamplay = 2)); } } else { // qqshka: interesting, why I commented it out, since I do not recall case then we can have zero deathmatch // in non coop game. // if ( !deathmatch ) // trap_cvar_set_float("deathmatch", (deathmatch = 3)); } // if unknown teamplay - disable it at all if ((teamplay != 0) && (teamplay != 1) && (teamplay != 2) && (teamplay != 3) && (teamplay != 4)) { trap_cvar_set_float("teamplay", (teamplay = 0)); } // if unknown deathmatch - set some default value if ((deathmatch != 0) && (deathmatch != 1) && (deathmatch != 2) && (deathmatch != 3) && (deathmatch != 4) && (deathmatch != 5)) { trap_cvar_set_float("deathmatch", (deathmatch = 3)); } if (k_matchLess) { // matchless mode MUST be FFA or CTF if (!isFFA() && !isCTF()) { trap_cvar_set_float("k_mode", (float)(k_mode = gtFFA)); } else if (isCTF()) { trap_cvar_set_float("k_mode", (float)(k_mode = gtCTF)); } // matchless mode should have teamplay set to 0 unless coop or CTF. if (teamplay && !coop && !isCTF()) { trap_cvar_set_float("teamplay", (teamplay = 0)); } if (isCTF()) { // Below commands only needed if "k_matchless 1" and "k_mode 4" are forced via rcon if (!teamplay) { trap_cvar_set_float("teamplay", (teamplay = 2)); } tp = teamplay; // Need to set this so that we don't get the "teamplay changed to: X" warning from the logic below km = 4; // Need to set this so that we don't get the "k_mode changed to: 2" warning from the logic below } } // if unknown k_mode - set some appropriate value if (isUnknown()) { trap_cvar_set_float("k_mode", (float)(k_mode = (teamplay ? gtTeam : gtDuel))); } // teamplay set, but gametype is not team, disable teamplay in this case if (teamplay) { if (!isTeam() && !isCTF() && !coop) { trap_cvar_set_float("teamplay", (teamplay = 0)); } } // gametype is team, but teamplay has wrong value, set some default value // qqshka - CTF need some teamplay too? if (isTeam() || isCTF()) { if ((teamplay != 1) && (teamplay != 2) && (teamplay != 3) && (teamplay != 4)) { trap_cvar_set_float("teamplay", (teamplay = 2)); } } if (k_tt <= 0) { // this change does't broadcasted cvar_fset("k_timetop", k_tt = 30); // sensible default if no max set } // oldman --> don't allow unlimited timelimit + fraglimit // also do not allow some weird timelimit if (deathmatch) { if (((timelimit == 0) && (fraglimit == 0)) || (timelimit > k_tt) || (timelimit < 0)) { if (!isHoonyModeDuel() && !isRACE() && !isCA()) { cvar_fset("timelimit", timelimit = k_tt); // sensible default if no max set } // NOTE: hoonymode works with fraglimit = 0, and timelimit = 0, and manages the game by frags directly } } else { if (timelimit) { cvar_fset("timelimit", timelimit = 0); } if (fraglimit) { cvar_fset("fraglimit", fraglimit = 0); } } // <-- oldman // { rate bounds if (!k_minr) { k_minr = 500; // was wrong/zero setting } if (!k_maxr) { k_maxr = 30000; // was wrong/zero setting } if (k_minr > k_maxr) { k_minr = k_maxr; // hehe } if (k_minr != cvar("k_minrate")) { cvar_fset("k_minrate", k_minr); } if (k_maxr != cvar("sv_maxrate")) { cvar_fset("sv_maxrate", k_maxr); } // } if (deathmatch) { g_globalvars.serverflags = (int)g_globalvars.serverflags & ~15; // remove runes } if (cvar("k_midair") && deathmatch != 4) { cvar_fset("k_midair", 0); // midair only in dmm4 } if (cvar("k_instagib") && deathmatch != 4) { cvar_fset("k_instagib", 0); // instagib only in dmm4 } if (cvar("k_freshteams") && deathmatch != 1) { cvar_fset("k_freshteams", 0); // freshteams only in dmm1 } if (cvar("k_nosweep") && deathmatch != 1) { cvar_fset("k_nosweep", 0); // nosweep only in dmm1 } // ok, broadcast changes if any, a bit tech info, but this is misconfigured server // and must not happen on well configured servers, k? if (km != k_mode) { G_bprint(2, "%s: k_mode changed to: %d\n", redtext("WARNING"), (int)k_mode); } if (tp != teamplay) { G_bprint(2, "%s: teamplay changed to: %d\n", redtext("WARNING"), teamplay); } if (tl != timelimit) { G_bprint(2, "%s: timelimit changed to: %d\n", redtext("WARNING"), timelimit); } if (fl != fraglimit) { G_bprint(2, "%s: fraglimit changed to: %d\n", redtext("WARNING"), fraglimit); } if (dm != deathmatch) { G_bprint(2, "%s: deathmatch changed to: %d\n", redtext("WARNING"), deathmatch); } if (sv_minping != (int)cvar("sv_minping")) { sv_minping = cvar("sv_minping"); // remember, so we can broadcast changes G_bprint(2, "%s changed to %d\n", redtext("sv_minping"), sv_minping); } if (framecount == 1) { trap_executecmd(); } SetMode4ServerInfo(); } int timelimit, fraglimit, teamplay, deathmatch, framecount, coop, skill; extern float intermission_exittime; void CheckTiming(void); void check_fcheck(void); void CheckTeamStatus(void); void SendSpecInfo(void); void DoMVDAutoTrack(void); void FixNoSpecs(void); void StartFrame(int time) { framecount++; if (framecount == 1) { FirstFrame(); } FixRules(); if (framecount == 2) { SecondFrame(); FixRules(); } FixNoSpecs(); // if no players left turn off "no spectators" mode FixCTFItems(); // if modes have changed we may need to add/remove flags etc FixRA(); // we may need reload map FixRace(); // we may need reload map FixPowerups(); FixSpecWizards(); framechecks = bound(0, !cvar("k_noframechecks"), 1); CheckSvUnlock(); DoMVDAutoTrack(); // mvd autotrack stuff CheckTiming(); // check if client lagged or returned from lag if (intermission_running && (g_globalvars.time >= (intermission_exittime - 1)) && !strnull(cvar_string("serverdemo"))) { localcmd("stop\n"); // demo is recording, stop it and save } if (k_matchLess && !match_in_progress && !k_bloodfest) { StartTimer(); // trying start countdown in matchless mode } if (isRA()) { ra_Frame(); } if (isCA()) { CA_Frame(); } if (framecount > 10) { vote_check_all(); } CheckAll(); // just check some clients params if (isRACE()) { race_think(); } check_monsters_respawn(); CheckTeamStatus(); CheckAutoXonX(true); // switch XonX mode dependant on players + specs count Check_LongMapUptime(); // reload map after some long up time, so our float time variables are happy check_fcheck(); TeamplayGameTick(); WillPause(); } // Check the same spawnflags as items only visible in DM for monsters as well. // 1. Disabled for all SP modes // 2. Not disabled for DM qbool AllowMonster(gedict_t *e) { if (!deathmatch) { return true; } if (((int) e->s.v.spawnflags & SPAWNFLAG_NOT_SP) != SPAWNFLAG_NOT_SP) { return false; } if (((int) e->s.v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH) == SPAWNFLAG_NOT_DEATHMATCH) { return false; } return true; } QW-Group-ktx-d05d6ca/tools/000077500000000000000000000000001475442401000155705ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/tools/cross-cmake/000077500000000000000000000000001475442401000177775ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/tools/cross-cmake/linux-aarch64.cmake000066400000000000000000000010741475442401000233700ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm64) # which compilers to use for C and C++ set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) QW-Group-ktx-d05d6ca/tools/cross-cmake/linux-amd64.cmake000066400000000000000000000010161475442401000230470ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR amd64) # which compilers to use for C and C++ set(CMAKE_C_COMPILER x86_64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER x86_64-linux-gnu-g++) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) QW-Group-ktx-d05d6ca/tools/cross-cmake/linux-armhf.cmake000066400000000000000000000010771475442401000232400ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) # which compilers to use for C and C++ set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) #set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) QW-Group-ktx-d05d6ca/tools/cross-cmake/linux-i686.cmake000066400000000000000000000012211475442401000226260ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER i686-linux-gnu-gcc) # Turn off excess precision with -mfpmath=sse -msse2, otherwise KTX compiled with bots will hang. set(CMAKE_C_FLAGS "-mfpmath=sse -msse2") #set(CMAKE_CXX_COMPILER x86_64-linux-gnu-g++) #set(CMAKE_CXX_FLAGS -m32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) QW-Group-ktx-d05d6ca/tools/cross-cmake/windows-x64.cmake000066400000000000000000000010441475442401000231110ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) QW-Group-ktx-d05d6ca/tools/cross-cmake/windows-x86.cmake000066400000000000000000000012511475442401000231150ustar00rootroot00000000000000# the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) # Turn off excess precision with -mfpmath=sse -msse2, otherwise KTX compiled with bots will hang. set(CMAKE_C_FLAGS "-mfpmath=sse -msse2") set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) QW-Group-ktx-d05d6ca/tools/q3asm/000077500000000000000000000000001475442401000166145ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/tools/q3asm/CMakeLists.txt000066400000000000000000000001461475442401000213550ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.9.0) project(q3asm C) add_executable(q3asm q3asm.c q3vm.c cmdlib.c) QW-Group-ktx-d05d6ca/tools/q3asm/README.Id000066400000000000000000000006361475442401000200340ustar00rootroot000000000000002002-10-25 Timothee Besset If you are looking for a faster version of the q3asm tool, try: http://www.icculus.org/~phaethon/q3/q3asm-turbo/q3asm-turbo.html 2001-10-31 Timothee Besset updated from the $/source/q3asm code modified for portability and use with >= 1.31 mod source release the cmdlib.c cmdlib.h mathlib.h qfiles.h have been copied from $/source/common QW-Group-ktx-d05d6ca/tools/q3asm/cmdlib.c000066400000000000000000000160711475442401000202170ustar00rootroot00000000000000/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // cmdlib.c #include "cmdlib.h" #include #include #ifdef _WIN32 #include #include #elif defined(NeXT) #include #else #include #endif char com_token[1024]; qboolean com_eof; /* ================= Error For abnormal program terminations in console apps ================= */ void Error( const char *error, ...) { va_list argptr; printf( "\n************ ERROR ************\n" ); va_start( argptr, error ); vprintf( error, argptr ); va_end( argptr ); printf( "\n" ); exit( 1 ); } char *copystring( const char *s ) { int len; char *b; len = strlen( s ) + 1; b = malloc( len ); memcpy( b, s, len ); return b; } /* ================ I_FloatTime ================ */ double I_FloatTime (void) { #ifdef _WIN32 DWORD count; count = GetTickCount(); return (double)count*0.001; #else time_t t; time (&t); return t; #endif #if 0 // more precise, less portable struct timeval tp; struct timezone tzp; static int secbase; gettimeofday(&tp, &tzp); if (!secbase) { secbase = tp.tv_sec; return tp.tv_usec/1000000.0; } return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; #endif } void Q_mkdir (const char *path) { #ifdef _WIN32 if (_mkdir (path) != -1) return; #else if (mkdir (path, 0777) != -1) return; #endif if (errno != EEXIST) Error ("mkdir %s: %s",path, strerror(errno)); } /* ============== COM_Parse Parse a token out of a string ============== */ char *COM_Parse (char *data) { int c; int len; len = 0; com_token[0] = 0; if (!data) return NULL; // skip whitespace skipwhite: while ( (c = *data) <= ' ') { if (c == 0) { com_eof = qtrue; return NULL; // end of file; } data++; } // skip // comments if (c=='/' && data[1] == '/') { while (*data && *data != '\n') data++; goto skipwhite; } // handle quoted strings specially if (c == '\"') { data++; for ( ;; ) { //do //{ c = *data++; if (c=='\"') { com_token[len] = 0; return data; } com_token[len] = c; len++; //} while (1); } } // parse single characters switch ( c ) { case '{': case '}': case '(': case ')': case '\'': case ':': { com_token[len++] = c; com_token[len] = '\0'; return data+1; } } // parse a regular word do { com_token[len] = c; data++; len++; c = *data; switch ( c ) { case '{': case '}': case '(': case ')': case '\'': case ':': { com_token[len] = '\0'; return data; } } } while ( c > ' ' ); com_token[len] = '\0'; return data; } /* ============================================================================= MISC FUNCTIONS ============================================================================= */ /* ================ Q_filelength ================ */ int Q_filelength (FILE *f) { int pos; int end; pos = ftell (f); fseek (f, 0, SEEK_END); end = ftell (f); fseek (f, pos, SEEK_SET); return end; } #ifdef MAX_PATH #undef MAX_PATH #endif #define MAX_PATH 4096 static FILE* myfopen( const char* filename, const char* mode ) { char* p; char fn[MAX_PATH]; fn[0] = '\0'; strncat(fn, filename, sizeof(fn)-1); for(p=fn;*p;++p) if(*p == '\\') *p = '/'; return fopen(fn, mode); } FILE *SafeOpenWrite (const char *filename) { FILE *f; f = myfopen(filename, "wb"); if (!f) Error ("Error opening %s: %s",filename,strerror(errno)); return f; } FILE *SafeOpenRead (const char *filename) { FILE *f; f = myfopen(filename, "rb"); if (!f) Error ("Error opening %s: %s",filename,strerror(errno)); return f; } void SafeRead (FILE *f, void *buffer, int count) { if ( fread (buffer, 1, count, f) != (size_t)count) Error ("File read failure"); } void SafeWrite (FILE *f, const void *buffer, int count) { if (fwrite (buffer, 1, count, f) != (size_t)count) Error ("File write failure"); } /* ============== LoadFile ============== */ int LoadFile( const char *filename, void **bufferptr ) { FILE *f; int length; void *buffer; f = SafeOpenRead (filename); length = Q_filelength (f); buffer = malloc (length+1); ((char *)buffer)[length] = 0; SafeRead (f, buffer, length); fclose (f); *bufferptr = buffer; return length; } /* ============== SaveFile ============== */ void SaveFile ( const char *filename, const void *buffer, int count ) { FILE *f; f = SafeOpenWrite( filename ); SafeWrite( f, buffer, count ); fclose( f ); } void DefaultExtension ( char *path, const char *extension ) { char *src; // // if path doesnt have a .EXT, append extension // (extension should include the .) // src = path + strlen(path) - 1; while ( *src != '/' && *src != '\\' && src != path ) { if ( *src == '.' ) return; // it has an extension src--; } strcat( path, extension ); } void StripExtension ( char *path ) { int length; length = strlen(path)-1; while( length > 0 && path[length] != '.' ) { length--; if ( path[length] == '/' ) return; // no extension } if ( length ) path[length] = '\0'; } /* ============================================================================ BYTE ORDER FUNCTIONS ============================================================================ */ // detect endianess int BigEndian( void ) { union { int i; char s[4]; } u; strcpy( u.s, "123" ); if ( u.i == 0x00333231 ) return 0; else return 1; } 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; } //======================================================= /* ============ CreatePath ============ */ void CreatePath (const char *path) { const char *ofs; char c; char dir[1024]; #ifdef _WIN32 int olddrive = -1; if ( path[1] == ':' ) { olddrive = _getdrive(); _chdrive( toupper( path[0] ) - 'A' + 1 ); } #endif if (path[1] == ':') path += 2; for (ofs = path+1 ; *ofs ; ofs++) { c = *ofs; if (c == '/' || c == '\\') { // create the directory memcpy( dir, path, ofs - path ); dir[ ofs - path ] = 0; Q_mkdir( dir ); } } #ifdef _WIN32 if ( olddrive != -1 ) { _chdrive( olddrive ); } #endif } QW-Group-ktx-d05d6ca/tools/q3asm/cmdlib.h000066400000000000000000000047361475442401000202310ustar00rootroot00000000000000/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // cmdlib.h #ifndef __CMDLIB__ #define __CMDLIB__ #ifdef _MSC_VER #pragma warning(disable : 4244) // MIPS #pragma warning(disable : 4136) // X86 #pragma warning(disable : 4051) // ALPHA #pragma check_stack(off) #endif #include #include #include #include #include #include #include #ifdef _MSC_VER #pragma intrinsic( memset, memcpy ) #endif #ifndef __BYTEBOOL__ #define __BYTEBOOL__ typedef enum { qfalse, qtrue } qboolean; typedef unsigned char byte; #endif #ifdef _WIN32 #define MAX_OS_PATH MAX_PATH #ifndef PATH_SEP #define PATH_SEP '\\' #endif #else #define MAX_OS_PATH 1024 #ifndef PATH_SEP #define PATH_SEP '/' #endif #endif int Q_filelength( FILE *f ); void Q_mkdir( const char *path ); double I_FloatTime( void ); void Error( const char *error, ... ); FILE *SafeOpenWrite( const char *filename ); FILE *SafeOpenRead( const char *filename ); void SafeRead( FILE *f, void *buffer, int count ); void SafeWrite( FILE *f, const void *buffer, int count ); int LoadFile( const char *filename, void **bufferptr ); void SaveFile( const char *filename, const void *buffer, int count ); void DefaultExtension( char *path, const char *extension ); void StripExtension( char *path ); void CreatePath( const char *path ); void ExtractFileExtension( const char *path, char *dest ); char *COM_Parse ( char *data ); extern char com_token[1024]; char *copystring( const char *s ); int BigEndian( void ); int LongSwap( int l ); #endif QW-Group-ktx-d05d6ca/tools/q3asm/lib.txt000066400000000000000000000002321475442401000201200ustar00rootroot00000000000000 strlen strcasecmp tolower strcat strncpy strcmp strcpy strchr vsprintf memcpy memset rand atoi atof abs floor fabs tan atan sqrt log cos sin atan2 QW-Group-ktx-d05d6ca/tools/q3asm/notes.txt000066400000000000000000000002661475442401000205110ustar00rootroot00000000000000 don't do any paramter conversion (double to float, etc) Why? Security. Portability. It may be more aproachable. can still use regular dlls for development purposes lcc q3asm QW-Group-ktx-d05d6ca/tools/q3asm/ops.txt000066400000000000000000000012041475442401000201530ustar00rootroot00000000000000CNSTF, CNSTI, CNSTP, CNSTU, ARGB, ARGF, ARGI, ARGP, ARGU, ASGNB, ASGNF, ASGNI, ASGNP, ASGNU, INDIRB, INDIRF, INDIRI, INDIRP, INDIRU, CVFF, CVFI, CVIF, CVII, CVIU, CVPU, CVUI, CVUP, CVUU, NEGF, NEGI, CALLB, CALLF, CALLI, CALLP, CALLU, CALLV, RETF, RETI, RETP, RETU, RETV, ADDRGP, ADDRFP, ADDRLP, ADDF, ADDI, ADDP, ADDU, SUBF, SUBI, SUBP, SUBU, LSHI, LSHU, MODI, MODU, RSHI, RSHU, BANDI, BANDU, BCOMI, BCOMU, BORI, BORU, BXORI, BXORU, DIVF, DIVI, DIVU, MULF, MULI, MULU, EQF, EQI, EQU, GEF, GEI, GEU, GTF, GTI, GTU, LEF, LEI, LEU, LTF, LTI, LTU, NEF, NEI, NEU, JUMPV, LABELV, LOADB, LOADF, LOADI, LOADP, LOADU, QW-Group-ktx-d05d6ca/tools/q3asm/opstrings.h000066400000000000000000000111031475442401000210110ustar00rootroot00000000000000/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ { "BREAK", OP_BREAK }, { "CNSTF4", OP_CONST }, { "CNSTI4", OP_CONST }, { "CNSTP4", OP_CONST }, { "CNSTU4", OP_CONST }, { "CNSTI2", OP_CONST }, { "CNSTU2", OP_CONST }, { "CNSTI1", OP_CONST }, { "CNSTU1", OP_CONST }, { "ASGNB", OP_BLOCK_COPY }, { "ASGNF4", OP_STORE4 }, { "ASGNI4", OP_STORE4 }, { "ASGNP4", OP_STORE4 }, { "ASGNU4", OP_STORE4 }, { "ASGNI2", OP_STORE2 }, { "ASGNU2", OP_STORE2 }, { "ASGNI1", OP_STORE1 }, { "ASGNU1", OP_STORE1 }, { "INDIRB", OP_IGNORE }, // block copy deals with this { "INDIRF4", OP_LOAD4 }, { "INDIRI4", OP_LOAD4 }, { "INDIRP4", OP_LOAD4 }, { "INDIRU4", OP_LOAD4 }, { "INDIRI2", OP_LOAD2 }, { "INDIRU2", OP_LOAD2 }, { "INDIRI1", OP_LOAD1 }, { "INDIRU1", OP_LOAD1 }, { "CVFF4", OP_UNDEF }, { "CVFI4", OP_CVFI }, { "CVIF4", OP_CVIF }, { "CVII4", OP_SEX8 }, // will be either SEX8 or SEX16 { "CVII1", OP_IGNORE }, { "CVII2", OP_IGNORE }, { "CVIU4", OP_IGNORE }, { "CVPU4", OP_IGNORE }, { "CVUI4", OP_IGNORE }, { "CVUP4", OP_IGNORE }, { "CVUU4", OP_IGNORE }, { "CVUU1", OP_IGNORE }, { "NEGF4", OP_NEGF }, { "NEGI4", OP_NEGI }, { "ADDRGP4", OP_CONST }, //{ "ADDRFP", OP_PARM, ASMP(ADDR) }, //{ "ADDRLP", OP_LOCAL,ASMP(ADDR) }, { "ADDF4", OP_ADDF }, { "ADDI4", OP_ADD }, { "ADDP4", OP_ADD }, { "ADDP", OP_ADD }, { "ADDU4", OP_ADD }, { "SUBF4", OP_SUBF }, { "SUBI4", OP_SUB }, { "SUBP4", OP_SUB }, { "SUBU4", OP_SUB }, { "LSHI4", OP_LSH }, { "LSHU4", OP_LSH }, { "MODI4", OP_MODI }, { "MODU4", OP_MODU }, { "RSHI4", OP_RSHI }, { "RSHU4", OP_RSHU }, { "BANDI4", OP_BAND }, { "BANDU4", OP_BAND }, { "BCOMI4", OP_BCOM }, { "BCOMU4", OP_BCOM }, { "BORI4", OP_BOR }, { "BORU4", OP_BOR }, { "BXORI4", OP_BXOR }, { "BXORU4", OP_BXOR }, { "DIVF4", OP_DIVF }, { "DIVI4", OP_DIVI }, { "DIVU4", OP_DIVU }, { "MULF4", OP_MULF }, { "MULI4", OP_MULI }, { "MULU4", OP_MULU }, { "EQF4", OP_EQF }, { "EQI4", OP_EQ }, { "EQU4", OP_EQ }, { "GEF4", OP_GEF }, { "GEI4", OP_GEI }, { "GEU4", OP_GEU }, { "GTF4", OP_GTF }, { "GTI4", OP_GTI }, { "GTU4", OP_GTU }, { "LEF4", OP_LEF }, { "LEI4", OP_LEI }, { "LEU4", OP_LEU }, { "LTF4", OP_LTF }, { "LTI4", OP_LTI }, { "LTU4", OP_LTU }, { "NEF4", OP_NEF }, { "NEI4", OP_NE }, { "NEU4", OP_NE }, { "JUMPV", OP_JUMP }, //{ "LOADB4", OP_UNDEF }, //{ "LOADF4", OP_UNDEF }, //{ "LOADI4", OP_UNDEF }, //{ "LOADP4", OP_UNDEF }, //{ "LOADU4", OP_UNDEF }, { "proc", DIR_PROC, ASMP(PROC) }, { "endproc", DIR_ENDPROC, ASMP(ENDPROC) }, { "address", DIR_ADDRESS, ASMP(ADDRESS) }, { "export", DIR_EXPORT, ASMP(EXPORT) }, { "import", DIR_IMPORT, ASMP(IMPORT) }, { "code", DIR_CODE, ASMP(CODE) }, { "data", DIR_DATA, ASMP(DATA) }, { "lit", DIR_LIT, ASMP(LIT) }, { "bss", DIR_BSS, ASMP(BSS) }, { "line", DIR_LINE, ASMP(LINE) }, { "file", DIR_FILE, ASMP(FILE) }, { "equ", DIR_EQU, ASMP(EQU) }, { "align", DIR_ALIGN, ASMP(ALIGN) }, { "byte", DIR_BYTE, ASMP(BYTE) }, { "skip", DIR_SKIP, ASMP(SKIP) }, { "pop", OP_IGNORE, ASMP(POP) }, { "ARGB", OP_IGNORE, ASMP(ARG) }, { "ARGF4", OP_IGNORE, ASMP(ARG) }, { "ARGI4", OP_IGNORE, ASMP(ARG) }, { "ARGP4", OP_IGNORE, ASMP(ARG) }, { "ARGU4", OP_IGNORE, ASMP(ARG) }, //{ "CALLB", OP_IGNORE, ASMP(CALL) }, { "CALLF4", OP_IGNORE, ASMP(CALL) }, { "CALLI4", OP_IGNORE, ASMP(CALL) }, { "CALLP4", OP_IGNORE, ASMP(CALL) }, { "CALLU4", OP_IGNORE, ASMP(CALL) }, { "CALLV", OP_IGNORE, ASMP(CALL) }, { "RETF4", OP_IGNORE, ASMP(RET) }, { "RETI4", OP_IGNORE, ASMP(RET) }, { "RETP4", OP_IGNORE, ASMP(RET) }, { "RETU4", OP_IGNORE, ASMP(RET) }, //{ "RETV", OP_IGNORE, ASMP(RET) }, { "ADDRFP4", OP_IGNORE, ASMP(ADDRF) }, { "ADDRLP4", OP_IGNORE, ASMP(ADDRL) }, { "LABELV", OP_IGNORE, ASMP(LABEL) }, QW-Group-ktx-d05d6ca/tools/q3asm/q3asm.c000066400000000000000000001167641475442401000200230ustar00rootroot00000000000000/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #ifdef _WIN32 #include #include #endif #include "qvm.h" // <- that one should be synced with engine! #include "cmdlib.h" #define MYSORT #define EMITJTS // for symbols #define SYM_HASHTABLE_SIZE 2048 // for opcodes/directives - minimize collisions #define OP_HASHTABLE_SIZE 512 char outputFilename[MAX_OS_PATH]; typedef enum { OP_UNDEF, OP_IGNORE, OP_BREAK, OP_ENTER, OP_LEAVE, OP_CALL, OP_PUSH, OP_POP, OP_CONST, OP_LOCAL, OP_JUMP, //------------------- OP_EQ, OP_NE, OP_LTI, OP_LEI, OP_GTI, OP_GEI, OP_LTU, OP_LEU, OP_GTU, OP_GEU, OP_EQF, OP_NEF, OP_LTF, OP_LEF, OP_GTF, OP_GEF, //------------------- OP_LOAD1, OP_LOAD2, OP_LOAD4, OP_STORE1, OP_STORE2, OP_STORE4, // *(stack[top-1]) = stack[top] OP_ARG, OP_BLOCK_COPY, // ------------------- OP_SEX8, OP_SEX16, OP_NEGI, OP_ADD, OP_SUB, OP_DIVI, OP_DIVU, OP_MODI, OP_MODU, OP_MULI, OP_MULU, OP_BAND, OP_BOR, OP_BXOR, OP_BCOM, OP_LSH, OP_RSHI, OP_RSHU, OP_NEGF, OP_ADDF, OP_SUBF, OP_DIVF, OP_MULF, OP_CVIF, OP_CVFI, // additional directives DIR_PROC = 128, DIR_ENDPROC, DIR_ADDRESS, DIR_EXPORT, DIR_IMPORT, DIR_CODE, DIR_DATA, DIR_LIT, DIR_BSS, DIR_LINE, DIR_FILE, DIR_EQU, DIR_ALIGN, DIR_BYTE, DIR_SKIP } opcode_t; typedef enum { PASS_DEFINE, PASS_COMPILE, PASS_OPTIMIZE, PASS_COUNT } pass_t; typedef enum { ST_RESERVED, ST_FUNCTION, ST_LABEL } symtype_t; #define MAX_IMAGE 0x400000 typedef struct segment_s { byte image[MAX_IMAGE]; int imageUsed; int segmentBase; // only valid after PASS_DEFINE } segment_t; typedef struct symbol_s { struct symbol_s *next; struct segment_s *segment; char *name; int value; symtype_t type; int refcnt; int ignore; struct { char *name; int line; } file; } symbol_t; typedef struct hashchain_s { void *data; struct hashchain_s *next; } hashchain_t; typedef struct hashtable_s { int buckets; int chains; int mask; hashchain_t **table; } hashtable_t; int symtablelen = SYM_HASHTABLE_SIZE; hashtable_t symtable; hashtable_t optable; byte jbitmap[MAX_IMAGE]; segment_t segment[NUM_SEGMENTS]; segment_t *currentSegment; pass_t passNumber; int passCount = 0; int ignoreFunc = 0; int ignoreLabel = 0; int errorCount; const char *passName[ PASS_COUNT ] = { "define", "compile", "optimize" }; typedef struct options_s { qboolean verbose; qboolean writeMapFile; qboolean vanillaQ3Compatibility; qboolean optimize; } options_t; options_t options = { 0 }; symbol_t *entry = NULL; // QVM entry point symbol_t *symbols = NULL; symbol_t *lastSymbol = NULL; // Most recent symbol defined #define MAX_ASM_FILES 256 int numAsmFiles; char *asmFiles[MAX_ASM_FILES]; char *asmFileNames[MAX_ASM_FILES]; int currentFileIndex; char *currentFileName; int currentFileLine; int stackSize = PROGRAM_STACK_SIZE; // 65536 // we need to convert arg and ret instructions to // stores to the local stack frame, so we need to track the // characteristics of the current functions stack frame int currentLocals; // bytes of locals needed by this function int currentArgs; // bytes of largest argument list called from this function int currentArgOffset; // byte offset in currentArgs to store next arg, reset each call #define MAX_LINE_LENGTH 1024 char lineBuffer[MAX_LINE_LENGTH]; int lineParseOffset; char token[MAX_LINE_LENGTH]; int instructionCount; char symExport[MAX_LINE_LENGTH]; #define ASMP(O) TryAssemble_##O #define ASMF(O) int TryAssemble_##O( void ) typedef struct { char *name; int opcode; int (*func)(void); } sourceOps_t; // declare prototypes ASMF(PROC); ASMF(ENDPROC); ASMF(ADDRESS); ASMF(EXPORT); ASMF(IMPORT); ASMF(CODE); ASMF(DATA); ASMF(LIT); ASMF(BSS); ASMF(LINE); ASMF(FILE); ASMF(EQU); ASMF(ALIGN); ASMF(BYTE); ASMF(SKIP); ASMF(ARG); ASMF(POP); ASMF(RET); ASMF(CALL); ASMF(ADDRL); ASMF(ADDRF); ASMF(LABEL); sourceOps_t sourceOps[] = { #include "opstrings.h" }; #define NUM_SOURCE_OPS ( sizeof( sourceOps ) / sizeof( sourceOps[0] ) ) #define JUSED(v) jbitmap[(v)/8]|=1<<((v)&7) int vreport( const char* fmt, va_list vp ) { if ( options.verbose != qtrue ) return 0; return vprintf(fmt, vp); } int report( const char *fmt, ... ) { va_list va; int retval; va_start( va, fmt ); retval = vreport( fmt, va ); va_end( va ); return retval; } #ifdef EMITJTS unsigned int crc_table[256]; void _crc32_init( unsigned int *crc ) { unsigned int c; int i, j; for (i = 0; i < 256; i++) { c = i; for (j = 0; j < 8; j++) c = c & 1 ? (c >> 1) ^ 0xEDB88320UL : c >> 1; crc_table[i] = c; }; *crc = 0xFFFFFFFFUL; } void _crc32_update( unsigned int *crc, unsigned char *buf, unsigned int len ) { while (len--) *crc = crc_table[(*crc ^ *buf++) & 0xFF] ^ (*crc >> 8); } void _crc32_final( unsigned int *crc ) { *crc = *crc ^ 0xFFFFFFFFUL; } #endif int log2floor( int x ) { int r = 1; int v = x; while( v >>= 1 ) r <<= 1; if ( r < x ) r <<= 1; return r; } #define hashtable_get(H,hash) (H).table[(hash)&(H).mask] /* The chain-and-bucket hash table. -PH */ void hashtable_alloc( hashtable_t *H, int buckets ) { // round-up buckets so we can use mask correctly buckets = log2floor( buckets ); H->buckets = buckets; H->mask = buckets - 1; H->chains = 0; H->table = malloc( buckets * sizeof( *(H->table) ) ); memset( H->table, 0, buckets * sizeof( *(H->table) ) ); } // By Paul Larson unsigned int HashSymbol( const char *sym ) { unsigned int hash = 0; while( *sym ) hash = 101 * hash + *sym++; return hash ^ (hash >> 16); } // Modified version, perfect hash for our limited directive set unsigned int HashOpcode( const char *op ) { unsigned int hash = 0; while( *op ) hash = 2039545 * hash + *op++; return hash ^ (hash >> 14); // hash = 6720353 * hash + *op++; // return hash ^ (hash >> 18); } void hashtable_add( hashtable_t *H, int hashvalue, void *data ) { hashchain_t *hc, **hb; hb = &H->table[ hashvalue & H->mask ]; hc = malloc( sizeof( *hc ) ); hc->data = data; hc->next = *hb; *hb = hc; H->chains++; } /* There is no need in hashtable_remove routines or so since symbol/opcode tables is allocated once and used until program end */ /* ============== InitTables ============== */ void InitTables( void ) { int i, hash; sourceOps_t *op; hashtable_alloc( &symtable, symtablelen ); hashtable_alloc( &optable, OP_HASHTABLE_SIZE ); op = sourceOps; for ( i = 0 ; i < NUM_SOURCE_OPS ; i++, op++ ) { hash = HashOpcode( op->name ); hashtable_add( &optable, hash, op ); } } void hashtable_stats( hashtable_t *H ) { int len, empties, longest, nodes; int i; float meanlen; hashchain_t *hc; empties = 0; longest = 0; nodes = 0; for ( i = 0; i < H->buckets; i++ ) { if ( H->table[i] == NULL ) { empties++; continue; } for (hc = H->table[i], len = 0; hc; hc = hc->next, len++); if (len > longest) { longest = len; } nodes += len; } meanlen = (float)(nodes) / (H->buckets - empties); report( "Stats for %s hashtable:", (H==&symtable) ? "symbol" : "opcode" ); report( " %d buckets (%i empty), %d nodes\n", H->buckets, empties, nodes ); report( " longest chain: %d, mean non-empty: %f\n", longest, meanlen ); } /* Search for a symbol in corresponding hash table return NULL if not found */ symbol_t *hashtable_symbol_exists( int hash, const char *sym ) { hashchain_t *hc; symbol_t *s; hc = hashtable_get( symtable, hash ); while( hc != NULL ) { s = (symbol_t*)hc->data; if ( !strcmp( sym, s->name ) ) return s; hc = hc->next; } return NULL; /* no matches */ } #ifdef MYSORT /* Quick symbols by its values */ static void sym_sort_v( symbol_t **a, int n ) { symbol_t *temp; symbol_t *m; int i, j; i = 0; j = n; m = a[ n>>1 ]; do { // sort by values while ( a[i]->value < m->value ) i++; while ( a[j]->value > m->value ) j--; if ( i <= j ) { temp = a[i]; a[i] = a[j]; a[j] = temp; i++; j--; } } while ( i <= j ); if ( j > 0 ) sym_sort_v( a, j ); if ( n > i ) sym_sort_v( a+i, n-i ); } #else /* Comparator function for quicksorting. */ static int symlist_cmp( const void *e1, const void *e2 ) { const symbol_t *a, *b; a = *(const symbol_t **)e1; b = *(const symbol_t **)e2; return ( a->value - b->value ); } #endif void sort_symbols( void ) { int i, n; symbol_t *s; symbol_t **symlist; if ( symtable.chains <= 1 ) { return; // nothing to sort actually } // alloc max possible buffer for storing all symbol pointers symlist = malloc( symtable.chains * sizeof( symbol_t* ) ); // now count only used symbols n = 0; s = symbols; while ( s != NULL ) { if ( !s->ignore ) { symlist[n] = s; n++; } s = s->next; } // nothing to sort? if ( n <= 1 ) { free( symlist ); return; } #ifdef _DEBUG report( "Quick-sorting %d symbols\n", n ); #endif #ifdef MYSORT sym_sort_v( symlist, n-1 ); #else qsort( symlist, n, sizeof(symbol_t*), symlist_cmp ); #endif // re-link chains s = symbols = symlist[0]; for ( i = 1; i < n; i++ ) { s->next = symlist[i]; s = s->next; } lastSymbol = s; s->next = NULL; free( symlist ); } /* Problem: BYTE values are specified as signed decimal string. A properly functional atoip() will cap large signed values at 0x7FFFFFFF. Negative word values are often specified as very large decimal values by lcc. Therefore, values that should be between 0x7FFFFFFF and 0xFFFFFFFF come out as 0x7FFFFFFF when using atoi(). Bad. */ int atoiNoCap( const char *s ) { int sign; int c, v; if ( !s ) return 0; // skip spaces while ( ( c = (*s & 255) ) <= ' ' ) { if ( !c ) return 0; s++; } // check sign switch ( c ) { case '-': s++; sign = 1; break; case '+': s++; default: sign = 0; break; } v = 0; // resulting value for ( ;; ) { c = *s++ & 255; if ( c < '0' || c > '9' ) break; v = v * 10 + (c - '0'); } if ( sign ) v = -v; return v; } /* ============ CodeError ============ */ void CodeError( char *fmt, ... ) { va_list argptr; errorCount++; fprintf( stderr, "%s:%i ", currentFileName, currentFileLine ); va_start( argptr,fmt ); vfprintf( stderr, fmt, argptr ); va_end( argptr ); } /* ============ EmitByte ============ */ void EmitByte( segment_t *seg, int v ) { if ( seg->imageUsed >= MAX_IMAGE ) { Error( "MAX_IMAGE" ); } seg->image[ seg->imageUsed ] = v; seg->imageUsed++; } /* ============ EmitInt Emit integer to corresponding segment in little-endian representation ============ */ void EmitInt( segment_t *seg, int v ) { if ( seg->imageUsed >= MAX_IMAGE - 4) { Error( "MAX_IMAGE" ); } seg->image[ seg->imageUsed ] = v & 255; seg->image[ seg->imageUsed + 1 ] = ( v >> 8 ) & 255; seg->image[ seg->imageUsed + 2 ] = ( v >> 16 ) & 255; seg->image[ seg->imageUsed + 3 ] = ( v >> 24 ) & 255; seg->imageUsed += 4; } symbol_t* FindSymbol( const char *sym ) { symbol_t *s; hashchain_t *hc; hc = hashtable_get( symtable, HashSymbol( sym ) ); while ( hc ) { s = (symbol_t*)hc->data; if ( !strcmp( sym, s->name ) ) return s; hc = hc->next; } return NULL; } sourceOps_t *FindOpcode( const char *opcode ) { sourceOps_t *op; hashchain_t *hc; hc = hashtable_get( optable, HashOpcode( opcode ) ); while ( hc ) { op = (sourceOps_t*)hc->data; if ( !strcmp( opcode, op->name ) ) return op; hc = hc->next; } return NULL; } symbol_t* FindIgnoreSymbol( const char *sym ) { symbol_t *s; hashchain_t *hc; hc = hashtable_get( symtable, HashSymbol( sym ) ); while ( hc ) { s = (symbol_t*)hc->data; if ( s->ignore && !strcmp( sym, s->name ) // strict checks && s->file.name == currentFileName && s->file.line == currentFileLine ) return s; hc = hc->next; } return NULL; } /* ============ IsIgnoredSymbol returns non-NULL in case of ignored symbol ============ */ symbol_t *IsIgnoredSymbol( const char *sym ) { char buf[MAX_LINE_LENGTH]; symbol_t *s; if ( sym[0] == '$' ) { sprintf( buf, "%s_%i", sym, currentFileIndex ); s = FindIgnoreSymbol( buf ); // local if ( s ) return s; } else { sprintf( buf, "%s^%i", sym, currentFileIndex ); s = FindIgnoreSymbol( buf ); // static if ( s ) return s; s = FindIgnoreSymbol( sym ); // global if ( s ) return s; } return NULL; } /* ============ CheckIgnoredSymbols check and set ignore flags for non-referenced symbols ============ */ int CheckIgnoredSymbols( void ) { symbol_t *s; int count = 0; for ( s = symbols ; s ; s = s->next ) { if ( s->ignore || s->type == ST_RESERVED ) continue; if ( s->refcnt > 0 ) { s->refcnt = 0; // reset for further optimization passes continue; } s->ignore = 1; count++; } return count; } /* ============ DefineSymbol Symbols can only be defined on PASS_DEFINE ============ */ void DefineSymbol( const char *sym, int value, symtype_t type, qboolean allowStatic ) { char buf[MAX_LINE_LENGTH]; symbol_t *s; int hash; if ( passNumber != PASS_DEFINE || ignoreFunc ) return; // NULL // add the file suffix to local symbols to guarantee unique if ( sym[0] == '$' ) { sprintf( buf, "%s_%i", sym, currentFileIndex ); sym = buf; } else // special suffix for static symbols if ( allowStatic && ( *symExport == 0 || strcmp( sym, symExport ) != 0 ) ) { sprintf( buf, "%s^%i", sym, currentFileIndex ); sym = buf; } *symExport = '\0'; // reset export symbol hash = HashSymbol( sym ); // save as hash value can be used later s = hashtable_symbol_exists( hash, sym ); if ( s ) { // can happen on second PASS_DEFINE or PASS_OPTIMIZE if ( s->file.name != currentFileName || s->file.line != currentFileLine ) { // symbol exists but was defined elsewhere CodeError( "%s already defined (%s:%i)\n", sym, s->file.name, s->file.line ); } else { s->value = value; s->segment = currentSegment; lastSymbol = s; } return; } s = malloc( sizeof( *s ) ); s->next = NULL; s->name = copystring( sym ); s->value = value; s->segment = currentSegment; // extra information s->type = type; s->refcnt = 0; s->ignore = 0; s->file.name = currentFileName; s->file.line = currentFileLine; hashtable_add( &symtable, hash, s ); /* Hash table lookup already speeds up symbol lookup enormously. We postpone sorting until end of pass 0. Since we're not doing the insertion sort, lastSymbol should always wind up pointing to the end of list. This allows constant time for adding to the list. -PH */ if ( symbols == NULL ) { lastSymbol = symbols = s; } else { lastSymbol->next = s; lastSymbol = s; } return; //s } /* ============ LookupSymbol Perform lookup and return symbol value ============ */ int LookupSymbol( const char *sym ) { char buf[MAX_LINE_LENGTH]; symbol_t *s; // can't operate at this stage if ( passNumber == PASS_DEFINE ) return 0; // ignore all symbol lookups inside ignore scope if ( ignoreFunc ) return 0; // now perform lookup and set reference counters if ( sym[0] == '$' ) { sprintf( buf, "%s_%i", sym, currentFileIndex ); s = FindSymbol( buf ); // local if ( s ) { s->refcnt++; return (s->segment->segmentBase + s->value); } } else { // look for static first sprintf( buf, "%s^%i", sym, currentFileIndex ); s = FindSymbol( buf ); if ( s ) { s->refcnt++; return (s->segment->segmentBase + s->value); } // now search as global s = FindSymbol( sym ); if ( s ) { s->refcnt++; return (s->segment->segmentBase + s->value); } } CodeError( "error: symbol %s undefined\n", sym ); return 0; } /* ============== ExtractLine Extracts the next line from the given text block. If a full line isn't parsed, returns NULL Otherwise returns the updated parse pointer =============== */ char *ExtractLine( char *data ) { /* Goal: Given a string `data', extract one text line into buffer `lineBuffer' that is no longer than MAX_LINE_LENGTH characters long. Return value is remainder of `data' that isn't part of `lineBuffer'. -PH */ /* Hand-optimized by PhaethonH */ char *p, *q; currentFileLine++; lineParseOffset = 0; token[0] = 0; *lineBuffer = 0; p = q = data; if (!*q) { return NULL; } for ( ; !((*p == 0) || (*p == '\n')); p++) /* nop */ ; if ((p - q) >= MAX_LINE_LENGTH) { CodeError( "MAX_LINE_LENGTH" ); return data; } memcpy( lineBuffer, data, (p - data) ); lineBuffer[(p - data)] = 0; p += (*p == '\n') ? 1 : 0; /* Skip over final newline. */ return p; } /* ============== Parse Parse a token out of linebuffer ============== */ qboolean Parse( void ) { /* Hand-optimized by PhaethonH */ const char *p, *q; /* Because lineParseOffset is only updated just before exit, this makes this code version somewhat harder to debug under a symbolic debugger. */ *token = 0; /* Clear token. */ // skip whitespace for (p = lineBuffer + lineParseOffset; *p && (*p <= ' '); p++) /* nop */ ; // skip ; comments // die on end-of-string if ((*p == ';') || (*p == 0)) { lineParseOffset = p - lineBuffer; return qfalse; } q = p; /* Mark the start of token. */ /* Find separator first. */ for ( ; *p > 32; p++) /* nop */ ; /* XXX: unsafe assumptions. */ /* *p now sits on separator. Mangle other values accordingly. */ strncpy(token, q, p - q); token[p - q] = 0; lineParseOffset = p - lineBuffer; return qtrue; } /* ============== ParseValue ============== */ int ParseValue( void ) { Parse(); return atoiNoCap( token ); } /* ============== ParseExpression ============== */ int ParseExpression( void ) { /* Hand optimization, PhaethonH */ int i, j; char sym[MAX_LINE_LENGTH]; int v; /* Skip over a leading minus. */ for ( i = ((token[0] == '-') ? 1 : 0) ; i < MAX_LINE_LENGTH ; i++ ) { if ( token[i] == '+' || token[i] == '-' || token[i] == 0 ) { break; } } memcpy( sym, token, i ); sym[i] = 0; // resolve depending on first character switch (*sym) { /* Optimizing compilers can convert cases into "calculated jumps". I think these are faster. -PH */ case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': v = atoiNoCap( sym ); break; default: v = LookupSymbol( sym ); break; } // parse add / subtract offsets while ( token[i] != 0 ) { for ( j = i + 1 ; j < MAX_LINE_LENGTH ; j++ ) { if ( token[j] == '+' || token[j] == '-' || token[j] == 0 ) { break; } } memcpy( sym, token+i+1, j-i-1 ); sym[j-i-1] = 0; switch ( token[i] ) { case '+': v += atoiNoCap( sym ); break; case '-': v -= atoiNoCap( sym ); break; } i = j; } return v; } /* ============== SwitchToSegment BIG HACK: I want to put all 32 bit values in the data segment so they can be byte swapped, and all char data in the lit segment, but switch jump tables are emited in the lit segment and initialized strng variables are put in the data segment. I can change segments here, but I also need to fixup the label that was just defined Note that the lit segment is read-write in the VM, so strings aren't read only as in some architectures. ============== */ void SwitchToSegment( segmentName_t seg ) { if ( currentSegment == &segment[seg] ) { return; } report( "%s %i: SwitchToSerment %i\n", currentFileName, currentFileLine, seg ); currentSegment = &segment[seg]; if ( passNumber == PASS_DEFINE ) { lastSymbol->segment = currentSegment; lastSymbol->value = currentSegment->imageUsed; } } // call instructions reset currentArgOffset ASMF(CALL) { EmitByte( &segment[CODESEG], OP_CALL ); instructionCount++; currentArgOffset = 0; return 1; } // arg is converted to a reversed store ASMF(ARG) { EmitByte( &segment[CODESEG], OP_ARG ); instructionCount++; if ( 8 + currentArgOffset >= 256 ) { CodeError( "currentArgOffset >= 256" ); return 0; } EmitByte( &segment[CODESEG], 8 + currentArgOffset ); currentArgOffset += 4; return 1; } // ret just leaves something on the op stack ASMF(RET) { EmitByte( &segment[CODESEG], OP_LEAVE ); instructionCount++; EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); return 1; } // pop is needed to discard the return value of a function ASMF(POP) { EmitByte( &segment[CODESEG], OP_POP ); instructionCount++; return 1; } // address of a parameter is converted to OP_LOCAL ASMF(ADDRF) { int v; Parse(); v = ParseExpression(); instructionCount++; v = 16 + currentArgs + currentLocals + v; EmitByte( &segment[CODESEG], OP_LOCAL ); EmitInt( &segment[CODESEG], v ); return 1; } // address of a local is converted to OP_LOCAL ASMF(ADDRL) { int v; Parse(); v = ParseExpression(); instructionCount++; v = 8 + currentArgs + v; EmitByte( &segment[CODESEG], OP_LOCAL ); EmitInt( &segment[CODESEG], v ); return 1; } ASMF(PROC) { char name[1024]; Parse(); // function name strcpy( name, token ); // we are in optimizing stage(s) if ( ignoreFunc == 0 ) { if ( IsIgnoredSymbol( name ) ) { ignoreFunc++; } } else { // should never happen but anyway ignoreFunc++; } if ( ignoreFunc > 0 ) return 1; if ( !entry ) { if ( strcmp( token, "vmMain" ) ) printf( "Warning: entry point should be 'vmMain' instead of '%s'\n", token ); DefineSymbol( token, instructionCount, ST_RESERVED, qtrue ); entry = symbols; } else { DefineSymbol( token, instructionCount, ST_FUNCTION, qtrue ); } currentLocals = ParseValue(); // locals currentLocals = ( currentLocals + 3 ) & ~3; currentArgs = ParseValue(); // arg marshalling currentArgs = ( currentArgs + 3 ) & ~3; if ( 8 + currentLocals + currentArgs >= 32767 ) { CodeError( "Locals > 32k in %s\n", name ); } instructionCount++; EmitByte( &segment[CODESEG], OP_ENTER ); EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); return 1; } ASMF(ENDPROC) { //int v, v2; if ( ignoreFunc > 0 ) { ignoreFunc--; return 1; } //Parse(); // skip the function name //v = ParseValue(); // locals //v2 = ParseValue(); // arg marshalling // all functions must leave something on the opstack instructionCount++; EmitByte( &segment[CODESEG], OP_PUSH ); instructionCount++; EmitByte( &segment[CODESEG], OP_LEAVE ); EmitInt( &segment[CODESEG], 8 + currentLocals + currentArgs ); return 1; } ASMF(ADDRESS) { int v; Parse(); v = ParseExpression(); /* Addresses are 32 bits wide, and therefore go into data segment. */ SwitchToSegment( DATASEG ); EmitInt( currentSegment, v ); #if 0 if ( passNumber == PASS_COMPILE && token[ 0 ] == '$' ) // crude test for labels { EmitInt( &segment[ JTRGSEG ], v ); } #endif return 1; } ASMF(EXPORT) { Parse(); // symbol name strcpy( symExport, token ); return 1; } ASMF(IMPORT) { return 1; } ASMF(CODE) { currentSegment = &segment[CODESEG]; return 1; } ASMF(BSS) { currentSegment = &segment[BSSSEG]; return 1; } ASMF(DATA) { currentSegment = &segment[DATASEG]; return 1; } ASMF(LIT) { currentSegment = &segment[LITSEG]; return 1; } ASMF(LINE) { return 1; } ASMF(FILE) { return 1; } ASMF(EQU) { char name[1024]; Parse(); strcpy( name, token ); Parse(); DefineSymbol( name, atoiNoCap( token ), ST_LABEL, qfalse ); return 1; } ASMF(ALIGN) { int v; v = ParseValue(); currentSegment->imageUsed = (currentSegment->imageUsed + v - 1 ) & ~( v - 1 ); return 1; } ASMF(SKIP) { int v; v = ParseValue(); currentSegment->imageUsed += v; return 1; } ASMF(BYTE) { int i, v, v2; v = ParseValue(); // size v2 = ParseValue(); // value if ( v == 1 ) { // Character (1-byte) values go into lit(eral) segment SwitchToSegment( LITSEG ); } else if ( v == 4 ) { // 32-bit (4-byte) values go into data segment SwitchToSegment( DATASEG ); } else { // and 16-bit (2-byte) values will cause q3asm to barf CodeError( "%i bit initialized data not supported", v*8 ); return 0; } // emit little endian for ( i = 0 ; i < v ; i++ ) { EmitByte( currentSegment, (v2 & 255) ); /* paranoid ANDing -PH */ v2 >>= 8; } return 1; } // code labels are emited as instruction counts, not byte offsets, // because the physical size of the code will change with // different run time compilers and we want to minimize the // size of the required translation table ASMF(LABEL) { Parse(); // never ignore labels inside active code blocks if ( currentSegment != &segment[CODESEG] && IsIgnoredSymbol( token ) ) { ignoreLabel = 1; return 1; } else { ignoreLabel = 0; } if ( currentSegment == &segment[CODESEG] ) { if ( passNumber == PASS_COMPILE ) JUSED( instructionCount ); DefineSymbol( token, instructionCount, ST_LABEL, qtrue ); } else { DefineSymbol( token, currentSegment->imageUsed, ST_LABEL, qtrue ); } return 1; } /* ============== AssembleLine ============== */ void AssembleLine( void ) { int opcode; int expression; sourceOps_t *op; Parse(); if ( !token[0] ) { return; } op = FindOpcode( token ); #if 0 hc = hashtable_get( optable, HashOpcode( token ) ); while ( hc ) { op = (sourceOps_t*)(hc->data); if ( !strcmp( token, op->name ) ) break; hc = hc->next; } #endif if ( !op ) { CodeError( "Unknown token: %s\n", token ); return; } opcode = op->opcode; if ( ignoreFunc ) { if ( ignoreLabel ) { CodeError( "ignore label in ignoreFunc scope" ); ignoreLabel = 0; } switch( opcode ) { case DIR_PROC: case DIR_ENDPROC: //case DIR_ALIGN: case DIR_CODE: // NEVER ignore segment directives! case DIR_LIT: case DIR_BSS: case DIR_DATA: if ( op->func ) // execute only dedicated directives op->func(); default: break; } return; // unconditionally return from this scope } if ( ignoreLabel ) { switch( opcode ) { case DIR_ADDRESS: case DIR_SKIP: case DIR_BYTE: return; } ignoreLabel = 0; } // execute opcode(directive) function and exit if ( op->func ) { op->func(); return; } // we ignore most conversions if ( op->opcode == OP_IGNORE ) { return; } // sign extensions need to check next parm if ( opcode == OP_SEX8 ) { Parse(); if ( token[0] == '1' ) { opcode = OP_SEX8; } else if ( token[0] == '2' ) { opcode = OP_SEX16; } else { CodeError( "Bad sign extension: %s\n", token ); return; } } // check for expression Parse(); if ( token[0] && opcode != OP_CVIF && opcode != OP_CVFI ) { expression = ParseExpression(); // code like this can generate non-dword block copies: // auto char buf[2] = " "; // we are just going to round up. This might conceivably // be incorrect if other initialized chars follow. if ( opcode == OP_BLOCK_COPY ) { expression = ( expression + 3 ) & ~3; } EmitByte( &segment[CODESEG], opcode ); EmitInt( &segment[CODESEG], expression ); } else { EmitByte( &segment[CODESEG], opcode ); } instructionCount++; } /* ============== WriteMapFile ============== */ void WriteMapFile( void ) { FILE *f; symbol_t *s; char imageName[MAX_OS_PATH]; int seg; strcpy( imageName, outputFilename ); StripExtension( imageName ); strcat( imageName, ".map" ); // Symbols list may be shrinked after sort because of ignored symbols // so we probably can't perform normal define/compile passes after that. // However, as we already created qvm file before - we can do anything now sort_symbols(); report( "Writing %s...\n", imageName ); f = SafeOpenWrite( imageName ); for ( seg = CODESEG ; seg <= BSSSEG ; seg++ ) { for ( s = symbols ; s ; s = s->next ) { if ( s->name[0] == '$' ) { continue; // skip locals } if ( &segment[seg] != s->segment ) { continue; } fprintf( f, "%i %8x %s\n", seg, s->value, s->name ); } } fclose( f ); } /* =============== WriteVmFile =============== */ void WriteVmFile( void ) { char imageName[MAX_OS_PATH]; char jtsName[MAX_OS_PATH]; const char *errMsg; vmHeader_t header; FILE *f; unsigned int crc; int i, headerSize; instruction_t *inst; strcpy( imageName, outputFilename ); StripExtension( imageName ); strcpy( jtsName, imageName ); strcat( imageName, ".qvm" ); strcat( jtsName, ".jts" ); remove( imageName ); remove( jtsName ); if ( errorCount != 0 ) { report( "Not writing a file due to errors\n" ); return; } report( "code segment: %7i\n", segment[CODESEG].imageUsed ); report( "data segment: %7i\n", segment[DATASEG].imageUsed ); report( "lit segment: %7i\n", segment[LITSEG].imageUsed ); report( "bss segment: %7i\n", segment[BSSSEG].imageUsed ); report( "instruction count: %i\n", instructionCount ); if( !options.vanillaQ3Compatibility ) { header.vmMagic = VM_MAGIC_VER2; headerSize = sizeof( header ); } else { header.vmMagic = VM_MAGIC; // Don't write the VM_MAGIC_VER2 bits when maintaining 1.32b compatibility. // (I know this isn't strictly correct due to padding, but then platforms // that pad wouldn't be able to write a correct header anyway). Note: if // vmHeader_t changes, this needs to be adjusted too. headerSize = sizeof( header ) - sizeof( header.jtrgLength ); } // Build jump table targets segment segment[JTRGSEG].imageUsed = 0; inst = ( instruction_t* ) malloc ( (instructionCount + 8) * sizeof( inst[0] ) ); memset( inst, 0, (instructionCount + 8) * sizeof( inst[0] ) ); errMsg = VM_LoadInstructions( segment[CODESEG].image, segment[CODESEG].imageUsed, instructionCount, inst ); if ( errMsg ) { CodeError( "VM_LoadInstructions: %s\n", errMsg ); exit(1); } errMsg = VM_CheckInstructions( inst, instructionCount, 0x7FFFFFFF ); if ( errMsg ) { CodeError( "VM_CheckInstructions: %s\n", errMsg ); exit(1); } //segment[JTRGSEG].segmentBase = segment[BSSSEG].segmentBase + segment[BSSSEG].imageUsed; for ( i = 0; i < instructionCount; i++ ) { if ( inst[i].jused ) { continue; } if ( jbitmap[i/8]&(1<<(i&7)) ) { EmitInt( &segment[JTRGSEG], i ); } } segment[JTRGSEG].imageUsed = (segment[JTRGSEG].imageUsed + 3) & ~3; header.instructionCount = instructionCount; header.codeOffset = headerSize; header.codeLength = segment[CODESEG].imageUsed; header.dataOffset = header.codeOffset + segment[CODESEG].imageUsed; header.dataLength = segment[DATASEG].imageUsed; header.litLength = segment[LITSEG].imageUsed; header.bssLength = segment[BSSSEG].imageUsed; header.jtrgLength = segment[JTRGSEG].imageUsed; if ( BigEndian() ) { // byte swap the header for ( i = 0 ; i < sizeof( vmHeader_t ) / 4 ; i++ ) { ((int *)&header)[i] = LongSwap( ((int *)&header)[i] ); } } #ifdef EMITJTS // Prepare data for storing jump targets segment in external jts file. // With VM_MAGIC_VER2 we don't need that but at the same time // VM_MAGIC_VER2 terminates Q3 SDK EULA which may be not acceptable. // So we export jump targets into separate file while keeping main qvm // vq3-compatible. Host engine should be modified to accept jts files. // ----------------------------------------------------------------------- // Jump targets is required by recent 1.32e engine builds to safely turn on // bytecode optimizations which may provide significant performance boost _crc32_init( &crc ); _crc32_update( &crc, (void*)&header, sizeof( header ) - sizeof( header.jtrgLength ) ); _crc32_update( &crc, (void*)&segment[CODESEG].image, segment[CODESEG].imageUsed ); _crc32_update( &crc, (void*)&segment[DATASEG].image, segment[DATASEG].imageUsed ); _crc32_update( &crc, (void*)&segment[LITSEG].image, segment[LITSEG].imageUsed ); _crc32_final( &crc ); // byte swap the sum if ( BigEndian() ) { for ( i = 0 ; i < sizeof( crc ) / 4 ; i++ ) { ((int *)&crc)[i] = LongSwap( ((int *)&crc)[i] ); } } #endif report( "Writing to %s\n", imageName ); CreatePath( imageName ); f = SafeOpenWrite( imageName ); SafeWrite( f, &header, headerSize ); SafeWrite( f, &segment[CODESEG].image, segment[CODESEG].imageUsed ); SafeWrite( f, &segment[DATASEG].image, segment[DATASEG].imageUsed ); SafeWrite( f, &segment[LITSEG].image, segment[LITSEG].imageUsed ); if ( !options.vanillaQ3Compatibility ) { SafeWrite( f, &segment[JTRGSEG].image, segment[JTRGSEG].imageUsed ); } fclose( f ); #ifdef EMITJTS // write jump targets to separate file if ( options.vanillaQ3Compatibility ) { CreatePath( jtsName ); f = SafeOpenWrite( jtsName ); SafeWrite( f, &crc, sizeof( crc ) ); SafeWrite( f, &header.jtrgLength, sizeof( header.jtrgLength ) ); SafeWrite( f, &segment[JTRGSEG].image, segment[JTRGSEG].imageUsed ); fclose( f ); } #endif } void PassDefineCompile( void ) { char *ptr; int i; // clear potential garbage for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { memset( segment[i].image, 0, MAX_IMAGE ); } memset( jbitmap, 0, sizeof( jbitmap ) ); for ( passNumber = PASS_DEFINE ; passNumber <= PASS_COMPILE ; passNumber++ ) { segment[LITSEG].segmentBase = segment[DATASEG].imageUsed; segment[BSSSEG].segmentBase = segment[LITSEG].segmentBase + segment[LITSEG].imageUsed; segment[JTRGSEG].segmentBase = segment[BSSSEG].segmentBase + segment[BSSSEG].imageUsed; for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { segment[i].imageUsed = 0; } segment[DATASEG].imageUsed = 4; // skip the 0 byte, so NULL pointers are fixed up properly instructionCount = 0; report( "pass #%i: %s\n", ++passCount, passName[ passNumber ] ); for ( i = 0 ; i < numAsmFiles ; i++ ) { currentFileIndex = i; currentFileName = asmFileNames[ i ]; currentFileLine = 0; fflush( NULL ); ptr = asmFiles[i]; ignoreFunc = 0; ignoreLabel = 0; while ( ptr ) { ptr = ExtractLine( ptr ); AssembleLine(); } if ( ignoreFunc ) { CodeError( "ignore level %i\n", ignoreFunc ); return; } if ( errorCount ) { return; } } // align all segments for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { segment[i].imageUsed = (segment[i].imageUsed + 3) & ~3; } } } void PassOptimize( void ) { char *ptr; int i; passNumber = PASS_OPTIMIZE; if ( !CheckIgnoredSymbols() ) return; do { for ( i = 0 ; i < NUM_SEGMENTS ; i++ ) { segment[i].imageUsed = 0; segment[i].segmentBase = 0; } report( "pass #%i: %s\n", ++passCount, passName[ passNumber ] ); for ( i = 0 ; i < numAsmFiles ; i++ ) { currentFileIndex = i; currentFileName = asmFileNames[ i ]; currentFileLine = 0; fflush( NULL ); ptr = asmFiles[i]; ignoreFunc = 0; ignoreLabel = 0; while ( ptr ) { ptr = ExtractLine( ptr ); AssembleLine(); } if ( ignoreFunc ) { CodeError( "ignore level is not zero: %i\n", ignoreFunc ); return; } } } while ( CheckIgnoredSymbols() > 0 ); } /* =============== Assemble =============== */ void Assemble( void ) { int i; char filename[MAX_OS_PATH]; report( "Output filename: %s\n", outputFilename ); for ( i = 0 ; i < numAsmFiles ; i++ ) { strcpy( filename, asmFileNames[ i ] ); DefaultExtension( filename, ".asm" ); LoadFile( filename, (void **)&asmFiles[i] ); } PassDefineCompile(); if ( options.optimize ) { // errors is unacceptable if ( errorCount ) return; PassOptimize(); if ( errorCount ) return; lastSymbol = NULL; instructionCount = 0; currentSegment = NULL; for ( i = 0; i < NUM_SEGMENTS; i++ ) { segment[i].imageUsed = 0; segment[i].segmentBase = 0; } // perform final fixup PassDefineCompile(); } passNumber = PASS_DEFINE; // reserve the stack in bss DefineSymbol( "_stackStart", segment[BSSSEG].imageUsed, ST_RESERVED, qfalse ); segment[BSSSEG].imageUsed += stackSize; DefineSymbol( "_stackEnd", segment[BSSSEG].imageUsed, ST_RESERVED, qfalse ); // write the image WriteVmFile(); // write the map file even if there were errors if( options.writeMapFile ) { WriteMapFile(); } } /* ============= ParseOptionFile ============= */ void ParseOptionFile( const char *filename ) { char expanded[MAX_OS_PATH]; char *text, *text_p; strcpy( expanded, filename ); DefaultExtension( expanded, ".q3asm" ); LoadFile( expanded, (void **)&text ); if ( !text ) { return; } text_p = text; while( ( text_p = COM_Parse( text_p ) ) != 0 ) { if ( !strcmp( com_token, "-o" ) ) { // allow output override in option file text_p = COM_Parse( text_p ); if ( text_p ) { strcpy( outputFilename, com_token ); } continue; } asmFileNames[ numAsmFiles ] = copystring( com_token ); numAsmFiles++; } } static const char *banner = { "Usage: %s [OPTION]... [FILES]...\n" "Assemble LCC bytecode assembly to Q3VM bytecode.\n" "\n" " -o OUTPUT Write assembled output to file OUTPUT.qvm\n" " -f LISTFILE Read options and list of files to assemble from LISTFILE\n" " -b BUCKETS Set symbol hash table to BUCKETS buckets\n" " -r Remove unreferenced symbols/functions from image\n" " -m Write map file\n" " -v Verbose compilation report\n" " -vq3 Produce a qvm file compatible with Q3 1.32b\n" " -- Stop switches parsing\n" }; /* ============== main ============== */ int main( int argc, const char *argv[] ) { int i; double start, end; const char *bin; if ( argc < 2 ) { // strip binary name bin = strrchr( argv[0], PATH_SEP ); if ( !bin || !bin[1] ) bin = argv[0]; else bin++; printf( banner, bin ); return 0; } start = I_FloatTime (); // default filename is "q3asm" strcpy( outputFilename, "q3asm" ); numAsmFiles = 0; for ( i = 1 ; i < argc ; i++ ) { if ( argv[i][0] != '-' ) { break; } if ( !strcmp( argv[i], "-o" ) ) { if ( i == argc - 1 ) { Error( "-o must preceed a filename" ); } /* Timbo of Tremulous pointed out -o not working; stock ID q3asm folded in the change. Yay. */ strcpy( outputFilename, argv[ i+1 ] ); i++; continue; } if ( !strcmp( argv[i], "-f" ) ) { if ( i == argc - 1 ) { Error( "-f must preceed a filename" ); } ParseOptionFile( argv[ i+1 ] ); i++; continue; } if ( !strcmp( argv[i], "-b" ) ) { if ( i == argc - 1 ) { Error( "-b requires an argument" ); } i++; symtablelen = atoiNoCap( argv[ i ] ); continue; } if ( !strcmp( argv[ i ], "-r" ) ) { options.optimize = qtrue; continue; } /* Verbosity option added by Timbo, 2002.09.14. By default (no -v option), q3asm remains silent except for critical errors. Verbosity turns on all messages, error or not. Motivation: not wanting to scrollback for pages to find asm error. */ if( !strcmp( argv[ i ], "-v" ) ) { options.verbose = qtrue; continue; } if( !strcmp( argv[ i ], "-m" ) ) { options.writeMapFile = qtrue; continue; } if( !strcmp( argv[ i ], "-vq3" ) ) { options.vanillaQ3Compatibility = qtrue; continue; } if( !strcmp( argv[ i ], "--" ) ) { break; } Error( "Unknown option: %s", argv[ i ] ); } // the rest of the command line args are asm files for ( ; i < argc ; i++ ) { asmFileNames[ numAsmFiles ] = copystring( argv[ i ] ); numAsmFiles++; } InitTables(); Assemble(); // do not print stats/timings on error if ( errorCount ) { return errorCount; } if ( options.verbose ) { hashtable_stats( &symtable ); #ifdef _DEBUG hashtable_stats( &optable ); #endif } end = I_FloatTime(); report( "%5.3f seconds elapsed\n---------------------\n", end-start ); return 0; } QW-Group-ktx-d05d6ca/tools/q3asm/q3vm.c000066400000000000000000000264061475442401000176560ustar00rootroot00000000000000/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. This file is part of Quake III Arena source code. Quake III Arena source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Quake III Arena source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "qvm.h" #include "cmdlib.h" typedef enum { OP_UNDEF, OP_IGNORE, OP_BREAK, OP_ENTER, OP_LEAVE, OP_CALL, OP_PUSH, OP_POP, OP_CONST, OP_LOCAL, OP_JUMP, //------------------- OP_EQ, OP_NE, OP_LTI, OP_LEI, OP_GTI, OP_GEI, OP_LTU, OP_LEU, OP_GTU, OP_GEU, OP_EQF, OP_NEF, OP_LTF, OP_LEF, OP_GTF, OP_GEF, //------------------- OP_LOAD1, OP_LOAD2, OP_LOAD4, OP_STORE1, OP_STORE2, OP_STORE4, // *(stack[top-1]) = stack[top] OP_ARG, OP_BLOCK_COPY, //------------------- OP_SEX8, OP_SEX16, OP_NEGI, OP_ADD, OP_SUB, OP_DIVI, OP_DIVU, OP_MODI, OP_MODU, OP_MULI, OP_MULU, OP_BAND, OP_BOR, OP_BXOR, OP_BCOM, OP_LSH, OP_RSHI, OP_RSHU, OP_NEGF, OP_ADDF, OP_SUBF, OP_DIVF, OP_MULF, OP_CVIF, OP_CVFI, OP_MAX } opcode_t; typedef struct opcode_info_s { int size; int stack; int flags; } opcode_info_t; #define JUMP (1<<0) #define PROC_OPSTACK_SIZE 30 #define LittleLong static const opcode_info_t ops[ OP_MAX ] = { { 0, 0, 0 }, // undef { 0, 0, 0 }, // ignore { 0, 0, 0 }, // break { 4, 0, 0 }, // enter { 4,-4, 0 }, // leave { 0, 0, 0 }, // call { 0, 4, 0 }, // push { 0,-4, 0 }, // pop { 4, 4, 0 }, // const { 4, 4, 0 }, // local { 0,-4, 0 }, // jump { 4,-8, JUMP }, // eq { 4,-8, JUMP }, // ne { 4,-8, JUMP }, // lti { 4,-8, JUMP }, // lei { 4,-8, JUMP }, // gti { 4,-8, JUMP }, // gei { 4,-8, JUMP }, // ltu { 4,-8, JUMP }, // leu { 4,-8, JUMP }, // gtu { 4,-8, JUMP }, // geu { 4,-8, JUMP }, // eqf { 4,-8, JUMP }, // nef { 4,-8, JUMP }, // ltf { 4,-8, JUMP }, // lef { 4,-8, JUMP }, // gtf { 4,-8, JUMP }, // gef { 0, 0, 0 }, // load1 { 0, 0, 0 }, // load2 { 0, 0, 0 }, // load4 { 0,-8, 0 }, // store1 { 0,-8, 0 }, // store2 { 0,-8, 0 }, // store4 { 1,-4, 0 }, // arg { 4,-8, 0 }, // bcopy { 0, 0, 0 }, // sex8 { 0, 0, 0 }, // sex16 { 0, 0, 0 }, // negi { 0,-4, 0 }, // add { 0,-4, 0 }, // sub { 0,-4, 0 }, // divi { 0,-4, 0 }, // divu { 0,-4, 0 }, // modi { 0,-4, 0 }, // modu { 0,-4, 0 }, // muli { 0,-4, 0 }, // mulu { 0,-4, 0 }, // band { 0,-4, 0 }, // bor { 0,-4, 0 }, // bxor { 0, 0, 0 }, // bcom { 0,-4, 0 }, // lsh { 0,-4, 0 }, // rshi { 0,-4, 0 }, // rshu { 0, 0, 0 }, // negf { 0,-4, 0 }, // addf { 0,-4, 0 }, // subf { 0,-4, 0 }, // divf { 0,-4, 0 }, // mulf { 0, 0, 0 }, // cvif { 0, 0, 0 } // cvfi }; /* ================= VM_LoadInstructions loads instructions in structured format ================= */ const char *VM_LoadInstructions( const byte *code_pos, int codeLength, int instructionCount, instruction_t *buf ) { static char errBuf[ 128 ]; const byte *code_start, *code_end; int i, n, op0, op1, opStack; instruction_t *ci; code_start = code_pos; // for printing code_end = code_pos + codeLength; ci = buf; opStack = 0; op1 = OP_UNDEF; // load instructions and perform some initial calculations/checks //for ( i = 0; i < header->instructionCount; i++, ci++, op1 = op0 ) { for ( i = 0; i < instructionCount; i++, ci++, op1 = op0 ) { op0 = *code_pos; if ( op0 < 0 || op0 >= OP_MAX ) { sprintf( errBuf, "bad opcode %02X at offset %d", op0, (int)(code_pos - code_start) ); return errBuf; } n = ops[ op0 ].size; if ( code_pos + 1 + n > code_end ) { sprintf( errBuf, "code_pos > code_end" ); return errBuf; } code_pos++; ci->op = op0; if ( n == 4 ) { ci->value = LittleLong( *((int*)code_pos) ); code_pos += 4; } else if ( n == 1 ) { ci->value = *((unsigned char*)code_pos); code_pos += 1; } else { ci->value = 0; } // setup jump value from previous const if ( op0 == OP_JUMP && op1 == OP_CONST ) { ci->value = (ci-1)->value; } ci->opStack = opStack; opStack += ops[ op0 ].stack; } return NULL; } /* =============================== VM_CheckInstructions performs additional consistency and security checks =============================== */ const char *VM_CheckInstructions( instruction_t *buf, int instructionCount, int dataLength ) { static char errBuf[ 128 ]; int i, n, v, op0, op1, opStack, pstack; instruction_t *ci, *proc; int startp, endp; ci = buf; opStack = 0; // opstack checks for ( i = 0; i < instructionCount; i++, ci++ ) { opStack += ops[ ci->op ].stack; if ( opStack < 0 ) { sprintf( errBuf, "opStack underflow at %i", i ); return errBuf; } if ( opStack >= PROC_OPSTACK_SIZE * 4 ) { sprintf( errBuf, "opStack overflow at %i", i ); return errBuf; } } ci = buf; pstack = 0; op1 = OP_UNDEF; proc = NULL; startp = 0; endp = instructionCount - 1; // Additional security checks for ( i = 0; i < instructionCount; i++, ci++, op1 = op0 ) { op0 = ci->op; // function entry if ( op0 == OP_ENTER ) { // missing block end if ( proc || ( pstack && op1 != OP_LEAVE ) ) { sprintf( errBuf, "missing proc end before %i", i ); return errBuf; } if ( ci->opStack != 0 ) { v = ci->opStack; sprintf( errBuf, "bad entry opstack %i at %i", v, i ); return errBuf; } v = ci->value; if ( v < 0 || v >= PROGRAM_STACK_SIZE || (v & 3) ) { sprintf( errBuf, "bad entry programStack %i at %i", v, i ); return errBuf; } pstack = ci->value; // mark jump target ci->jused = 1; proc = ci; startp = i + 1; // locate endproc for ( endp = 0, n = i+1 ; n < instructionCount; n++ ) { if ( buf[n].op == OP_PUSH && buf[n+1].op == OP_LEAVE ) { endp = n; break; } } if ( endp == 0 ) { sprintf( errBuf, "missing end proc for %i", i ); return errBuf; } continue; } // proc opstack will carry max.possible opstack value if ( proc && ci->opStack > proc->opStack ) proc->opStack = ci->opStack; // function return if ( op0 == OP_LEAVE ) { // bad return programStack if ( pstack != ci->value ) { v = ci->value; sprintf( errBuf, "bad programStack %i at %i", v, i ); return errBuf; } // bad opStack before return if ( ci->opStack != 4 ) { v = ci->opStack; sprintf( errBuf, "bad opStack %i at %i", v, i ); return errBuf; } v = ci->value; if ( v < 0 || v >= PROGRAM_STACK_SIZE || (v & 3) ) { sprintf( errBuf, "bad return programStack %i at %i", v, i ); return errBuf; } if ( op1 == OP_PUSH ) { if ( proc == NULL ) { sprintf( errBuf, "unexpected proc end at %i", i ); return errBuf; } proc = NULL; startp = i + 1; // next instruction endp = instructionCount - 1; // end of the image } continue; } // conditional jumps if ( ops[ ci->op ].flags & JUMP ) { v = ci->value; // conditional jumps should have opStack == 8 if ( ci->opStack != 8 ) { sprintf( errBuf, "bad jump opStack %i at %i", ci->opStack, i ); return errBuf; } //if ( v >= header->instructionCount ) { // allow only local proc jumps if ( v < startp || v > endp ) { sprintf( errBuf, "jump target %i at %i is out of range (%i,%i)", v, i-1, startp, endp ); return errBuf; } if ( buf[v].opStack != 0 ) { n = buf[v].opStack; sprintf( errBuf, "jump target %i has bad opStack %i", v, n ); return errBuf; } // mark jump target buf[v].jused = 1; continue; } // unconditional jumps if ( op0 == OP_JUMP ) { // jumps should have opStack == 4 if ( ci->opStack != 4 ) { sprintf( errBuf, "bad jump opStack %i at %i", ci->opStack, i ); return errBuf; } if ( op1 == OP_CONST ) { v = buf[i-1].value; // allow only local jumps if ( v < startp || v > endp ) { sprintf( errBuf, "jump target %i at %i is out of range (%i,%i)", v, i-1, startp, endp ); return errBuf; } if ( buf[v].opStack != 0 ) { n = buf[v].opStack; sprintf( errBuf, "jump target %i has bad opStack %i", v, n ); return errBuf; } if ( buf[v].op == OP_ENTER ) { n = buf[v].op; sprintf( errBuf, "jump target %i has bad opcode %i", v, n ); return errBuf; } if ( v == (i-1) ) { sprintf( errBuf, "self loop at %i", v ); return errBuf; } // mark jump target buf[v].jused = 1; } continue; } if ( op0 == OP_CALL ) { if ( ci->opStack < 4 ) { sprintf( errBuf, "bad call opStack at %i", i ); return errBuf; } if ( op1 == OP_CONST ) { v = buf[i-1].value; // analyse only local function calls if ( v >= 0 ) { if ( v >= instructionCount ) { sprintf( errBuf, "call target %i is out of range", v ); return errBuf; } if ( buf[v].op != OP_ENTER ) { n = buf[v].op; sprintf( errBuf, "call target %i has bad opcode %i", v, n ); return errBuf; } if ( v == 0 ) { sprintf( errBuf, "explicit vmMain call inside VM" ); return errBuf; } // mark jump target buf[v].jused = 1; } } continue; } if ( ci->op == OP_ARG ) { v = ci->value & 255; // argument can't exceed programStack frame if ( v < 8 || v > pstack - 4 || (v & 3) ) { sprintf( errBuf, "bad argument address %i at %i", v, i ); return errBuf; } continue; } if ( ci->op == OP_LOCAL ) { v = ci->value; if ( proc == NULL ) { sprintf( errBuf, "missing proc frame for local %i at %i", v, i ); return errBuf; } if ( (ci+1)->op == OP_LOAD1 || (ci+1)->op == OP_LOAD2 || (ci+1)->op == OP_LOAD4 || (ci+1)->op == OP_ARG ) { // FIXME: alloc 256 bytes of programStack in VM_CallCompiled()? if ( v < 8 || v >= proc->value + 256 ) { sprintf( errBuf, "bad local address %i at %i", v, i ); return errBuf; } } } if ( ci->op == OP_LOAD4 && op1 == OP_CONST ) { v = (ci-1)->value; if ( v < 0 || v > dataLength - 4 ) { sprintf( errBuf, "bad load4 address %i at %i", v, i - 1 ); return errBuf; } } if ( ci->op == OP_LOAD2 && op1 == OP_CONST ) { v = (ci-1)->value; if ( v < 0 || v > dataLength - 2 ) { sprintf( errBuf, "bad load2 address %i at %i", v, i - 1 ); return errBuf; } } if ( ci->op == OP_LOAD1 && op1 == OP_CONST ) { v = (ci-1)->value; if ( v < 0 || v > dataLength - 1 ) { sprintf( errBuf, "bad load1 address %i at %i", v, i - 1 ); return errBuf; } } if ( ci->op == OP_BLOCK_COPY ) { v = ci->value; if ( v >= dataLength ) { sprintf( errBuf, "bad count %i for block copy at %i", v, i - 1 ); return errBuf; } } // op1 = op0; // ci++; } if ( op1 != OP_UNDEF && op1 != OP_LEAVE ) { sprintf( errBuf, "missing return instruction at the end of the image" ); return errBuf; } return NULL; } QW-Group-ktx-d05d6ca/tools/q3asm/qvm.h000066400000000000000000000021671475442401000175760ustar00rootroot00000000000000/* copied from qfiles.h, should be synced with host qvm format - made for standalone compilation */ #include "cmdlib.h" #define VM_MAGIC 0x12721444 #define VM_MAGIC_VER2 0x12721445 #define PROGRAM_STACK_SIZE 0x10000 typedef struct { int vmMagic; int instructionCount; int codeOffset; int codeLength; int dataOffset; int dataLength; int litLength; // ( dataLength - litLength ) should be byteswapped on load int bssLength; // zero filled memory appended to datalength //!!! below here is VM_MAGIC_VER2 !!! int jtrgLength; // number of jump table targets } vmHeader_t; typedef enum { CODESEG, DATASEG, // initialized 32 bit data, will be byte swapped LITSEG, // strings BSSSEG, // 0 filled JTRGSEG, // psuedo-segment that contains only jump table targets NUM_SEGMENTS } segmentName_t; typedef struct { int value; byte op; byte opStack; unsigned jused:1; } instruction_t; const char *VM_LoadInstructions( const byte *code_pos, int codeLength, int instructionCount, instruction_t *buf ); const char *VM_CheckInstructions( instruction_t *buf, int instructionCount, int dataLength ); QW-Group-ktx-d05d6ca/tools/q3asm/readme.md000066400000000000000000000005111475442401000203700ustar00rootroot00000000000000q3asm is a tool which compiles assembly files (created by q3lcc from game sources) to QVM bytecode Major features of this version: * fast processing (faster even than q3asm-turbo) * unreferenced code/data elimination * proper 'static' keyword support * external jump targets segment (*.jts) generation for quake3e engineQW-Group-ktx-d05d6ca/tools/vs/000077500000000000000000000000001475442401000162205ustar00rootroot00000000000000QW-Group-ktx-d05d6ca/tools/vs/ktx.sln000066400000000000000000000025631475442401000175520ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32901.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ktx", "ktx.vcxproj", "{1B27BA54-712D-4803-9D15-62928C01C2C1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1B27BA54-712D-4803-9D15-62928C01C2C1}.Debug|x64.ActiveCfg = Debug|x64 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Debug|x64.Build.0 = Debug|x64 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Debug|x86.ActiveCfg = Debug|Win32 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Debug|x86.Build.0 = Debug|Win32 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Release|x64.ActiveCfg = Release|x64 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Release|x64.Build.0 = Release|x64 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Release|x86.ActiveCfg = Release|Win32 {1B27BA54-712D-4803-9D15-62928C01C2C1}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {40F356E1-2B94-4A38-A30F-88FA1F5B787F} EndGlobalSection EndGlobal QW-Group-ktx-d05d6ca/tools/vs/ktx.vcxproj000066400000000000000000000335601475442401000204520ustar00rootroot00000000000000 Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {1b27ba54-712d-4803-9d15-62928c01c2c1} ktx 10.0 DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode qwprogs.dll qwprogs.dll qwprogs.dll qwprogs.dll Level3 true WIN32;_DEBUG;KTX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);BOT_SUPPORT=1 true NotUsing C:\Users\Toma\source\repos\ktx\include;%(AdditionalIncludeDirectories) Windows true false Level3 true true true WIN32;NDEBUG;KTX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);BOT_SUPPORT=1 true NotUsing C:\Users\Toma\source\repos\ktx\include;%(AdditionalIncludeDirectories) Windows true true true false Level3 true _DEBUG;KTX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);BOT_SUPPORT=1 true NotUsing C:\Users\Toma\source\repos\ktx\include;%(AdditionalIncludeDirectories) Windows true false Level3 true true true NDEBUG;KTX_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions);BOT_SUPPORT=1 true NotUsing C:\Users\Toma\source\repos\ktx\include;%(AdditionalIncludeDirectories) Windows true true true false