├── .github └── workflows │ └── CI.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── licenses ├── BXT_LICENSE ├── FUNCHOOK_LICENSE ├── HLSDK_LICENSE └── SPTLIB_LICENSE ├── runsven.sh ├── src ├── .clang-format ├── CMakeLists.txt ├── CTimer.h ├── SvenBXT.cpp ├── SvenBXT.h ├── Utils.cpp ├── Utils.h ├── cl_dll │ ├── cdll_int.cpp │ ├── cdll_int.h │ ├── hud.cpp │ ├── hud.h │ ├── hud_crosshair.cpp │ ├── hud_crosshair.h │ ├── hud_jumpspeed.cpp │ ├── hud_jumpspeed.h │ ├── hud_origin.cpp │ ├── hud_origin.h │ ├── hud_speedometer.cpp │ ├── hud_speedometer.h │ ├── hud_timer.cpp │ ├── hud_timer.h │ ├── hud_viewangles.cpp │ ├── hud_viewangles.h │ ├── opengl_utils.cpp │ ├── opengl_utils.hpp │ ├── parsemsg.cpp │ ├── parsemsg.h │ ├── tri.cpp │ ├── tri.h │ ├── view.cpp │ └── view.h ├── cmake │ ├── InputFilesList.cmake │ ├── Linux32CrossCompile.cmake │ ├── PlatformInfo.cmake │ └── ToolchainLinuxGCC.cmake ├── dlls │ ├── enginecallback.h │ ├── server.cpp │ └── server.h ├── engine │ ├── gl_screen.cpp │ ├── gl_screen.h │ ├── server.h │ └── sound.h ├── engine_patterns.hpp ├── external │ ├── CMakeLists.txt │ └── SPTLib │ │ ├── MemUtils.h │ │ ├── Utils.hpp │ │ ├── patterns.hpp │ │ └── patterns_macros.hpp ├── hlsdk_mini.hpp ├── iface.cpp ├── iface.hpp ├── metahook_emulation.cpp ├── metahook_emulation.hpp ├── svenmod_emulation.cpp └── svenmod_emulation.hpp └── svenbxt.cfg /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - .gitignore 7 | - README.md 8 | - svenbxt.cfg 9 | pull_request: 10 | paths-ignore: 11 | - .gitignore 12 | - README.md 13 | - svenbxt.cfg 14 | workflow_dispatch: 15 | schedule: 16 | - cron: '0 0 1 * *' # Monthly 17 | 18 | jobs: 19 | build: 20 | runs-on: ${{ matrix.os }} 21 | 22 | strategy: 23 | fail-fast: true 24 | matrix: 25 | os: [ubuntu-latest, windows-latest] 26 | build_type: [Release] 27 | c_compiler: [gcc, cl] 28 | include: 29 | - os: windows-latest 30 | c_compiler: cl 31 | cpp_compiler: cl 32 | artifact: "svenbxt_windows-cl" 33 | bin-path: "src/build/Release/SvenBXT.dll" 34 | toolchain-file: "" 35 | cmake-generator: "Visual Studio 17 2022" 36 | build-target: "-A Win32" # HACK 37 | - os: ubuntu-latest 38 | c_compiler: gcc 39 | cpp_compiler: g++ 40 | artifact: "svenbxt_ubuntu-gcc" 41 | bin-path: "src/build/libSvenBXT.so" 42 | toolchain-file: "cmake/ToolchainLinuxGCC.cmake" 43 | cmake-generator: "Unix Makefiles" 44 | build-target: "" 45 | exclude: 46 | - os: windows-latest 47 | c_compiler: gcc 48 | - os: ubuntu-latest 49 | c_compiler: cl 50 | 51 | steps: 52 | - name: Checkout repository 53 | uses: actions/checkout@v4 54 | 55 | - name: Checkout submodules 56 | shell: bash 57 | run: git submodule update --init --recursive 58 | 59 | - name: Set reusable strings 60 | id: strings 61 | shell: bash 62 | run: | 63 | echo "build-output-dir=${{ github.workspace }}/src/build" >> "$GITHUB_OUTPUT" 64 | echo "src-dir=${{ github.workspace }}/src" >> "$GITHUB_OUTPUT" 65 | 66 | - name: Add msbuild to PATH 67 | if: runner.os == 'Windows' 68 | uses: microsoft/setup-msbuild@v2 69 | 70 | - name: Install Ubuntu packages 71 | if: runner.os == 'Linux' 72 | run: | 73 | sudo dpkg --add-architecture i386 74 | sudo apt update || true 75 | sudo apt install -y build-essential libc6:i386 g++-multilib mesa-common-dev libgl-dev:i386 libgl1-mesa-dev 76 | 77 | - name: Configure CMake 78 | run: > 79 | cmake -G "${{ matrix.cmake-generator }}" 80 | ${{ matrix.build-target }} 81 | -B ${{ steps.strings.outputs.build-output-dir }} 82 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} 83 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} 84 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} 85 | -DCMAKE_TOOLCHAIN_FILE=${{ matrix.toolchain-file }} 86 | -DFUNCHOOK_BUILD_TESTS=OFF 87 | -S ${{ steps.strings.outputs.src-dir }} 88 | 89 | - name: Build Linux version 90 | if: runner.os == 'Linux' 91 | run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} 92 | 93 | - name: Build Windows version 94 | if: runner.os == 'Windows' 95 | run: msbuild /m /p:OutputPath=${{ steps.strings.outputs.build-output-dir }} /p:Configuration=${{ matrix.build_type }} ${{ steps.strings.outputs.build-output-dir }}/SvenBXT.sln 96 | 97 | - name: Prepare artifacts 98 | run: mkdir -p bin && mv ${{ matrix.bin-path }} bin/ 99 | 100 | - name: Upload artifacts 101 | uses: actions/upload-artifact@v4 102 | with: 103 | path: ./bin 104 | name: ${{ matrix.artifact }} 105 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vs/ 3 | _build/ 4 | _build_WIN32/ 5 | build/ 6 | src/.idea/ 7 | src/.vs/ 8 | src/_build/ 9 | src/_build_WIN32/ 10 | src/build/ 11 | 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/external/funchook"] 2 | path = src/external/funchook 3 | url = https://github.com/kubo/funchook.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 ScriptedSnark 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SvenBXT 2 | 3 | SvenBXT is a complete remake of [BunnymodXT](https://github.com/YaLTeR/BunnymodXT), designed specifically for Sven Co-op 5.25. 4 |
You can legally use this tool for [Sven Co-op runs](https://www.speedrun.com/sven_coop).
5 | 6 |
Download latest release: [CLICK](https://github.com/ScriptedSnark/SvenBXT/releases/latest)
7 | Download nightly build: [CLICK](https://nightly.link/ScriptedSnark/SvenBXT/workflows/CI/new) 8 | 9 | ## Installation / Usage 10 | 11 | ### Windows 12 | SvenBXT can be installed as a [MetaHook](https://github.com/hzqst/MetaHookSv)/[SvenMod](https://github.com/sw1ft747/svenmod) plugin. 13 | Also can be injected by any injector (even deprecated one from `rebased` branch). 14 | 15 | #### MetaHook 16 | 1. Move `SvenBXT.dll` to `svencoop/metahook/plugins` 17 | 2. Write `SvenBXT.dll` in `svencoop/metahook/configs/plugins.lst` 18 | 19 | #### SvenMod 20 | 1. Move `SvenBXT.dll` to `svenmod/plugins` 21 | 2. Open `svenmod/plugins.txt` and write `"SvenBXT" "1"` inside plugins tab 22 | 23 | ``` 24 | // SvenMod 25 | // List of plugins to load 26 | 27 | "Plugins" 28 | { 29 | "SvenBXT" "1" 30 | 31 | "Settings" 32 | { 33 | "LoadDelay" "0.5" // in seconds 34 | } 35 | } 36 | ``` 37 | 38 | You can find additional info about that [here](https://github.com/sw1ft747/svenmod#adding-plugins). 39 | 40 | ### Linux 41 | You can use the `runsven.sh` script. Correct the paths at the top of the script if necessary. 42 | 43 | ## Credits 44 | **Thanks to [YaLTeR](https://github.com/YaLTeR) for [BunnymodXT](https://github.com/YaLTeR/BunnymodXT)!** 45 | 46 | Thanks to [autisoid](https://github.com/autisoid) for SvenMod/MetaHook emulators. -------------------------------------------------------------------------------- /licenses/BXT_LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2020 Ivan Molodetskikh 4 | Copyright (c) 2015-2018 Chong Jiang Wei 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /licenses/FUNCHOOK_LICENSE: -------------------------------------------------------------------------------- 1 | Funchook is distributed under the terms of the GNU General Public 2 | License version 2 or later with the following clarification and 3 | special exception. 4 | 5 | Linking this library statically or dynamically with other modules is 6 | making a combined work based on this library. Thus, the terms and 7 | conditions of the GNU General Public License cover the whole 8 | combination. 9 | 10 | As a special exception, the copyright holders of this library give you 11 | permission to link this library with independent modules to produce an 12 | executable, regardless of the license terms of these independent 13 | modules, and to copy and distribute the resulting executable under 14 | terms of your choice, provided that you also meet, for each linked 15 | independent module, the terms and conditions of the license of that 16 | module. An independent module is a module which is not derived from or 17 | based on this library. If you modify this library, you must extend this 18 | exception to your version of the library. 19 | 20 | ===================================================================== 21 | 22 | GNU GENERAL PUBLIC LICENSE 23 | Version 2, June 1991 24 | 25 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 26 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27 | Everyone is permitted to copy and distribute verbatim copies 28 | of this license document, but changing it is not allowed. 29 | 30 | Preamble 31 | 32 | The licenses for most software are designed to take away your 33 | freedom to share and change it. By contrast, the GNU General Public 34 | License is intended to guarantee your freedom to share and change free 35 | software--to make sure the software is free for all its users. This 36 | General Public License applies to most of the Free Software 37 | Foundation's software and to any other program whose authors commit to 38 | using it. (Some other Free Software Foundation software is covered by 39 | the GNU Lesser General Public License instead.) You can apply it to 40 | your programs, too. 41 | 42 | When we speak of free software, we are referring to freedom, not 43 | price. Our General Public Licenses are designed to make sure that you 44 | have the freedom to distribute copies of free software (and charge for 45 | this service if you wish), that you receive source code or can get it 46 | if you want it, that you can change the software or use pieces of it 47 | in new free programs; and that you know you can do these things. 48 | 49 | To protect your rights, we need to make restrictions that forbid 50 | anyone to deny you these rights or to ask you to surrender the rights. 51 | These restrictions translate to certain responsibilities for you if you 52 | distribute copies of the software, or if you modify it. 53 | 54 | For example, if you distribute copies of such a program, whether 55 | gratis or for a fee, you must give the recipients all the rights that 56 | you have. You must make sure that they, too, receive or can get the 57 | source code. And you must show them these terms so they know their 58 | rights. 59 | 60 | We protect your rights with two steps: (1) copyright the software, and 61 | (2) offer you this license which gives you legal permission to copy, 62 | distribute and/or modify the software. 63 | 64 | Also, for each author's protection and ours, we want to make certain 65 | that everyone understands that there is no warranty for this free 66 | software. If the software is modified by someone else and passed on, we 67 | want its recipients to know that what they have is not the original, so 68 | that any problems introduced by others will not reflect on the original 69 | authors' reputations. 70 | 71 | Finally, any free program is threatened constantly by software 72 | patents. We wish to avoid the danger that redistributors of a free 73 | program will individually obtain patent licenses, in effect making the 74 | program proprietary. To prevent this, we have made it clear that any 75 | patent must be licensed for everyone's free use or not licensed at all. 76 | 77 | The precise terms and conditions for copying, distribution and 78 | modification follow. 79 | 80 | GNU GENERAL PUBLIC LICENSE 81 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 82 | 83 | 0. This License applies to any program or other work which contains 84 | a notice placed by the copyright holder saying it may be distributed 85 | under the terms of this General Public License. The "Program", below, 86 | refers to any such program or work, and a "work based on the Program" 87 | means either the Program or any derivative work under copyright law: 88 | that is to say, a work containing the Program or a portion of it, 89 | either verbatim or with modifications and/or translated into another 90 | language. (Hereinafter, translation is included without limitation in 91 | the term "modification".) Each licensee is addressed as "you". 92 | 93 | Activities other than copying, distribution and modification are not 94 | covered by this License; they are outside its scope. The act of 95 | running the Program is not restricted, and the output from the Program 96 | is covered only if its contents constitute a work based on the 97 | Program (independent of having been made by running the Program). 98 | Whether that is true depends on what the Program does. 99 | 100 | 1. You may copy and distribute verbatim copies of the Program's 101 | source code as you receive it, in any medium, provided that you 102 | conspicuously and appropriately publish on each copy an appropriate 103 | copyright notice and disclaimer of warranty; keep intact all the 104 | notices that refer to this License and to the absence of any warranty; 105 | and give any other recipients of the Program a copy of this License 106 | along with the Program. 107 | 108 | You may charge a fee for the physical act of transferring a copy, and 109 | you may at your option offer warranty protection in exchange for a fee. 110 | 111 | 2. You may modify your copy or copies of the Program or any portion 112 | of it, thus forming a work based on the Program, and copy and 113 | distribute such modifications or work under the terms of Section 1 114 | above, provided that you also meet all of these conditions: 115 | 116 | a) You must cause the modified files to carry prominent notices 117 | stating that you changed the files and the date of any change. 118 | 119 | b) You must cause any work that you distribute or publish, that in 120 | whole or in part contains or is derived from the Program or any 121 | part thereof, to be licensed as a whole at no charge to all third 122 | parties under the terms of this License. 123 | 124 | c) If the modified program normally reads commands interactively 125 | when run, you must cause it, when started running for such 126 | interactive use in the most ordinary way, to print or display an 127 | announcement including an appropriate copyright notice and a 128 | notice that there is no warranty (or else, saying that you provide 129 | a warranty) and that users may redistribute the program under 130 | these conditions, and telling the user how to view a copy of this 131 | License. (Exception: if the Program itself is interactive but 132 | does not normally print such an announcement, your work based on 133 | the Program is not required to print an announcement.) 134 | 135 | These requirements apply to the modified work as a whole. If 136 | identifiable sections of that work are not derived from the Program, 137 | and can be reasonably considered independent and separate works in 138 | themselves, then this License, and its terms, do not apply to those 139 | sections when you distribute them as separate works. But when you 140 | distribute the same sections as part of a whole which is a work based 141 | on the Program, the distribution of the whole must be on the terms of 142 | this License, whose permissions for other licensees extend to the 143 | entire whole, and thus to each and every part regardless of who wrote it. 144 | 145 | Thus, it is not the intent of this section to claim rights or contest 146 | your rights to work written entirely by you; rather, the intent is to 147 | exercise the right to control the distribution of derivative or 148 | collective works based on the Program. 149 | 150 | In addition, mere aggregation of another work not based on the Program 151 | with the Program (or with a work based on the Program) on a volume of 152 | a storage or distribution medium does not bring the other work under 153 | the scope of this License. 154 | 155 | 3. You may copy and distribute the Program (or a work based on it, 156 | under Section 2) in object code or executable form under the terms of 157 | Sections 1 and 2 above provided that you also do one of the following: 158 | 159 | a) Accompany it with the complete corresponding machine-readable 160 | source code, which must be distributed under the terms of Sections 161 | 1 and 2 above on a medium customarily used for software interchange; or, 162 | 163 | b) Accompany it with a written offer, valid for at least three 164 | years, to give any third party, for a charge no more than your 165 | cost of physically performing source distribution, a complete 166 | machine-readable copy of the corresponding source code, to be 167 | distributed under the terms of Sections 1 and 2 above on a medium 168 | customarily used for software interchange; or, 169 | 170 | c) Accompany it with the information you received as to the offer 171 | to distribute corresponding source code. (This alternative is 172 | allowed only for noncommercial distribution and only if you 173 | received the program in object code or executable form with such 174 | an offer, in accord with Subsection b above.) 175 | 176 | The source code for a work means the preferred form of the work for 177 | making modifications to it. For an executable work, complete source 178 | code means all the source code for all modules it contains, plus any 179 | associated interface definition files, plus the scripts used to 180 | control compilation and installation of the executable. However, as a 181 | special exception, the source code distributed need not include 182 | anything that is normally distributed (in either source or binary 183 | form) with the major components (compiler, kernel, and so on) of the 184 | operating system on which the executable runs, unless that component 185 | itself accompanies the executable. 186 | 187 | If distribution of executable or object code is made by offering 188 | access to copy from a designated place, then offering equivalent 189 | access to copy the source code from the same place counts as 190 | distribution of the source code, even though third parties are not 191 | compelled to copy the source along with the object code. 192 | 193 | 4. You may not copy, modify, sublicense, or distribute the Program 194 | except as expressly provided under this License. Any attempt 195 | otherwise to copy, modify, sublicense or distribute the Program is 196 | void, and will automatically terminate your rights under this License. 197 | However, parties who have received copies, or rights, from you under 198 | this License will not have their licenses terminated so long as such 199 | parties remain in full compliance. 200 | 201 | 5. You are not required to accept this License, since you have not 202 | signed it. However, nothing else grants you permission to modify or 203 | distribute the Program or its derivative works. These actions are 204 | prohibited by law if you do not accept this License. Therefore, by 205 | modifying or distributing the Program (or any work based on the 206 | Program), you indicate your acceptance of this License to do so, and 207 | all its terms and conditions for copying, distributing or modifying 208 | the Program or works based on it. 209 | 210 | 6. Each time you redistribute the Program (or any work based on the 211 | Program), the recipient automatically receives a license from the 212 | original licensor to copy, distribute or modify the Program subject to 213 | these terms and conditions. You may not impose any further 214 | restrictions on the recipients' exercise of the rights granted herein. 215 | You are not responsible for enforcing compliance by third parties to 216 | this License. 217 | 218 | 7. If, as a consequence of a court judgment or allegation of patent 219 | infringement or for any other reason (not limited to patent issues), 220 | conditions are imposed on you (whether by court order, agreement or 221 | otherwise) that contradict the conditions of this License, they do not 222 | excuse you from the conditions of this License. If you cannot 223 | distribute so as to satisfy simultaneously your obligations under this 224 | License and any other pertinent obligations, then as a consequence you 225 | may not distribute the Program at all. For example, if a patent 226 | license would not permit royalty-free redistribution of the Program by 227 | all those who receive copies directly or indirectly through you, then 228 | the only way you could satisfy both it and this License would be to 229 | refrain entirely from distribution of the Program. 230 | 231 | If any portion of this section is held invalid or unenforceable under 232 | any particular circumstance, the balance of the section is intended to 233 | apply and the section as a whole is intended to apply in other 234 | circumstances. 235 | 236 | It is not the purpose of this section to induce you to infringe any 237 | patents or other property right claims or to contest validity of any 238 | such claims; this section has the sole purpose of protecting the 239 | integrity of the free software distribution system, which is 240 | implemented by public license practices. Many people have made 241 | generous contributions to the wide range of software distributed 242 | through that system in reliance on consistent application of that 243 | system; it is up to the author/donor to decide if he or she is willing 244 | to distribute software through any other system and a licensee cannot 245 | impose that choice. 246 | 247 | This section is intended to make thoroughly clear what is believed to 248 | be a consequence of the rest of this License. 249 | 250 | 8. If the distribution and/or use of the Program is restricted in 251 | certain countries either by patents or by copyrighted interfaces, the 252 | original copyright holder who places the Program under this License 253 | may add an explicit geographical distribution limitation excluding 254 | those countries, so that distribution is permitted only in or among 255 | countries not thus excluded. In such case, this License incorporates 256 | the limitation as if written in the body of this License. 257 | 258 | 9. The Free Software Foundation may publish revised and/or new versions 259 | of the General Public License from time to time. Such new versions will 260 | be similar in spirit to the present version, but may differ in detail to 261 | address new problems or concerns. 262 | 263 | Each version is given a distinguishing version number. If the Program 264 | specifies a version number of this License which applies to it and "any 265 | later version", you have the option of following the terms and conditions 266 | either of that version or of any later version published by the Free 267 | Software Foundation. If the Program does not specify a version number of 268 | this License, you may choose any version ever published by the Free Software 269 | Foundation. 270 | 271 | 10. If you wish to incorporate parts of the Program into other free 272 | programs whose distribution conditions are different, write to the author 273 | to ask for permission. For software which is copyrighted by the Free 274 | Software Foundation, write to the Free Software Foundation; we sometimes 275 | make exceptions for this. Our decision will be guided by the two goals 276 | of preserving the free status of all derivatives of our free software and 277 | of promoting the sharing and reuse of software generally. 278 | 279 | NO WARRANTY 280 | 281 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 282 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 283 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 284 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 285 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 286 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 287 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 288 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 289 | REPAIR OR CORRECTION. 290 | 291 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 292 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 293 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 294 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 295 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 296 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 297 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 298 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 299 | POSSIBILITY OF SUCH DAMAGES. 300 | 301 | END OF TERMS AND CONDITIONS 302 | 303 | How to Apply These Terms to Your New Programs 304 | 305 | If you develop a new program, and you want it to be of the greatest 306 | possible use to the public, the best way to achieve this is to make it 307 | free software which everyone can redistribute and change under these terms. 308 | 309 | To do so, attach the following notices to the program. It is safest 310 | to attach them to the start of each source file to most effectively 311 | convey the exclusion of warranty; and each file should have at least 312 | the "copyright" line and a pointer to where the full notice is found. 313 | 314 | 315 | Copyright (C) 316 | 317 | This program is free software; you can redistribute it and/or modify 318 | it under the terms of the GNU General Public License as published by 319 | the Free Software Foundation; either version 2 of the License, or 320 | (at your option) any later version. 321 | 322 | This program is distributed in the hope that it will be useful, 323 | but WITHOUT ANY WARRANTY; without even the implied warranty of 324 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 325 | GNU General Public License for more details. 326 | 327 | You should have received a copy of the GNU General Public License along 328 | with this program; if not, write to the Free Software Foundation, Inc., 329 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 330 | 331 | Also add information on how to contact you by electronic and paper mail. 332 | 333 | If the program is interactive, make it output a short notice like this 334 | when it starts in an interactive mode: 335 | 336 | Gnomovision version 69, Copyright (C) year name of author 337 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 338 | This is free software, and you are welcome to redistribute it 339 | under certain conditions; type `show c' for details. 340 | 341 | The hypothetical commands `show w' and `show c' should show the appropriate 342 | parts of the General Public License. Of course, the commands you use may 343 | be called something other than `show w' and `show c'; they could even be 344 | mouse-clicks or menu items--whatever suits your program. 345 | 346 | You should also get your employer (if you work as a programmer) or your 347 | school, if any, to sign a "copyright disclaimer" for the program, if 348 | necessary. Here is a sample; alter the names: 349 | 350 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 351 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 352 | 353 | , 1 April 1989 354 | Ty Coon, President of Vice 355 | 356 | This General Public License does not permit incorporating your program into 357 | proprietary programs. If your program is a subroutine library, you may 358 | consider it more useful to permit linking proprietary applications with the 359 | library. If this is what you want to do, use the GNU Lesser General 360 | Public License instead of this License. 361 | -------------------------------------------------------------------------------- /licenses/HLSDK_LICENSE: -------------------------------------------------------------------------------- 1 | Half Life 1 SDK LICENSE 2 | ====================== 3 | 4 | Half Life 1 SDK Copyright(c) Valve Corp. 5 | 6 | THIS DOCUMENT DESCRIBES A CONTRACT BETWEEN YOU AND VALVE CORPORATION ("Valve"). 7 | PLEASE READ IT BEFORE DOWNLOADING OR USING THE HALF LIFE 1 SDK ("SDK"). BY 8 | DOWNLOADING AND/OR USING THE HALF LIFE 1 SDK YOU ACCEPT THIS LICENSE. IF YOU DO 9 | NOT AGREE TO THE TERMS OF THIS LICENSE PLEASE DON'T DOWNLOAD OR USE THE SDK. 10 | 11 | You may, free of charge, download and use the SDK to develop a modified Valve 12 | game running on the Half-Life 1 engine. You may distribute your modified Valve 13 | game in source and object code form, but only for free. Terms of use for Valve 14 | games are found in the Steam Subscriber Agreement located here: 15 | http://store.steampowered.com/subscriber_agreement/ 16 | 17 | You may copy, modify, and distribute the SDK and any modifications you make to 18 | the SDK in source and object code form, but only for free. Any distribution of 19 | this SDK must include this LICENSE file. 20 | 21 | Any distribution of the SDK or a substantial portion of the SDK must include 22 | the above copyright notice and the following: 23 | 24 | DISCLAIMER OF WARRANTIES. THE HALF LIFE 1 SDK AND ANY OTHER MATERIAL 25 | DOWNLOADED BY LICENSEE IS PROVIDED "AS IS". VALVE AND ITS SUPPLIERS 26 | DISCLAIM ALL WARRANTIES WITH RESPECT TO THE SDK, EITHER EXPRESS OR IMPLIED, 27 | INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, 28 | NON-INFRINGEMENT, TITLE AND FITNESS FOR A PARTICULAR PURPOSE. 29 | 30 | LIMITATION OF LIABILITY. IN NO EVENT SHALL VALVE OR ITS SUPPLIERS BE LIABLE 31 | FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER 32 | (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 33 | BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY 34 | LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE ENGINE AND/OR THE 35 | SDK, EVEN IF VALVE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 36 | 37 | 38 | If you would like to use the SDK for a commercial purpose, please contact Valve 39 | at sourceengine@valvesoftware.com. 40 | -------------------------------------------------------------------------------- /licenses/SPTLIB_LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Ivan Molodetskikh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /runsven.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" 3 | 4 | # If your Steam library is somewhere else, correct this path. 5 | export SVEN_ROOT="." 6 | 7 | # SvenBXT path (you can correct this path too) 8 | export SVENBXT="$SVEN_ROOT/libSvenBXT.so" 9 | 10 | # Check that the Sven Co-op folder exists. 11 | if [ ! -d "$SVEN_ROOT" ]; then 12 | echo "Sven Co-op folder does not exist at $SVEN_ROOT" 13 | exit 1 14 | fi 15 | 16 | # Check that SvenBXT exists. 17 | if [ ! -f "$SVENBXT" ]; then 18 | echo "SvenBXT does not exist at $SVENBXT" 19 | exit 1 20 | fi 21 | 22 | export LD_PRELOAD="$LD_PRELOAD:$SVENBXT" 23 | 24 | # Run Sven Co-op. 25 | export LD_LIBRARY_PATH="$SVEN_ROOT:$LD_LIBRARY_PATH" 26 | export SteamEnv=1 27 | 28 | cd "$SVEN_ROOT" || exit 1 29 | exec ./svencoop_linux -steam "$@" -------------------------------------------------------------------------------- /src/.clang-format: -------------------------------------------------------------------------------- 1 | # Visual Studio generated .clang-format file 2 | 3 | # The style options in this file are a best effort attempt to replicate the 4 | # current IDE formatting configuration from Tools > Options. 5 | 6 | AccessModifierOffset: -4 7 | AlignAfterOpenBracket: DontAlign 8 | AllowShortBlocksOnASingleLine: true 9 | AllowShortCaseLabelsOnASingleLine: true 10 | AllowShortFunctionsOnASingleLine: All 11 | BasedOnStyle: LLVM 12 | BraceWrapping: 13 | BeforeLambdaBody: true 14 | AfterCaseLabel: true 15 | AfterClass: true 16 | AfterControlStatement: true 17 | AfterEnum: true 18 | AfterFunction: true 19 | AfterNamespace: true 20 | AfterStruct: true 21 | AfterUnion: true 22 | BeforeCatch: true 23 | BeforeElse: true 24 | IndentBraces: false 25 | SplitEmptyFunction: true 26 | SplitEmptyRecord: true 27 | BreakBeforeBraces: Custom 28 | ColumnLimit: 0 29 | Cpp11BracedListStyle: true 30 | FixNamespaceComments: false 31 | IndentCaseLabels: false 32 | IndentPPDirectives: None 33 | IndentWidth: 4 34 | MaxEmptyLinesToKeep: 10 35 | NamespaceIndentation: None 36 | PointerAlignment: Left 37 | SortIncludes: false 38 | SortUsingDeclarations: false 39 | SpaceAfterCStyleCast: false 40 | SpaceBeforeAssignmentOperators: true 41 | SpaceBeforeCaseColon: false 42 | SpaceBeforeCtorInitializerColon: false 43 | SpaceBeforeInheritanceColon: false 44 | SpaceBeforeParens: ControlStatements 45 | SpaceBeforeSquareBrackets: false 46 | SpaceInEmptyParentheses: false 47 | SpacesInCStyleCastParentheses: false 48 | SpacesInParentheses: false 49 | SpacesInSquareBrackets: false 50 | TabWidth: 4 51 | UseTab: true -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | 3 | # CMake modules 4 | list( APPEND CMAKE_MODULE_PATH 5 | "${CMAKE_CURRENT_LIST_DIR}/cmake" 6 | ) 7 | 8 | project(SvenBXT LANGUAGES C CXX ASM) 9 | 10 | include(PlatformInfo) 11 | include(InputFilesList) 12 | 13 | include_directories(${CMAKE_SOURCE_DIR}) 14 | 15 | if (COMPILER_MSVC) 16 | set(WINDOWS_FILES 17 | iface.cpp 18 | metahook_emulation.cpp 19 | svenmod_emulation.cpp) 20 | endif() 21 | 22 | set(CLIENT_FILES 23 | cl_dll/cdll_int.cpp 24 | cl_dll/cdll_int.h 25 | cl_dll/hud.cpp 26 | cl_dll/hud.h 27 | cl_dll/hud_crosshair.cpp 28 | cl_dll/hud_crosshair.h 29 | cl_dll/hud_jumpspeed.cpp 30 | cl_dll/hud_jumpspeed.h 31 | cl_dll/hud_origin.cpp 32 | cl_dll/hud_origin.h 33 | cl_dll/hud_speedometer.cpp 34 | cl_dll/hud_speedometer.h 35 | cl_dll/hud_timer.cpp 36 | cl_dll/hud_timer.h 37 | cl_dll/hud_viewangles.cpp 38 | cl_dll/hud_viewangles.h 39 | cl_dll/opengl_utils.cpp 40 | cl_dll/opengl_utils.hpp 41 | cl_dll/parsemsg.cpp 42 | cl_dll/parsemsg.h 43 | cl_dll/tri.cpp 44 | cl_dll/tri.h 45 | cl_dll/view.cpp 46 | cl_dll/view.h) 47 | 48 | set(SERVER_FILES 49 | dlls/server.cpp 50 | dlls/server.h) 51 | 52 | set(ENGINE_FILES 53 | engine/gl_screen.cpp 54 | engine/gl_screen.h) 55 | 56 | set(MAIN_FILES 57 | SvenBXT.cpp 58 | SvenBXT.h 59 | Utils.cpp 60 | Utils.h 61 | hlsdk_mini.hpp) 62 | 63 | source_group("cl_dll" FILES ${CLIENT_FILES}) 64 | source_group("dlls" FILES ${SERVER_FILES}) 65 | source_group("engine" FILES ${ENGINE_FILES}) 66 | source_group("" FILES ${MAIN_FILES} ${WINDOWS_FILES}) 67 | 68 | add_library(SvenBXT SHARED 69 | ${WINDOWS_FILES} 70 | ${CLIENT_FILES} 71 | ${SERVER_FILES} 72 | ${ENGINE_FILES} 73 | ${MAIN_FILES}) 74 | 75 | add_subdirectory("external") 76 | 77 | # Preprocessor definitions 78 | set( COMMON_DEFINES "" ) # Preprocessor definitions for all targets 79 | 80 | # Add platform defines to common defines 81 | set( COMMON_DEFINES "${COMMON_DEFINES} ${PLATFORM_DEFINES}" ) 82 | 83 | if( COMPILER_GNU ) 84 | 85 | set( COMMON_DEFINES 86 | ${COMMON_DEFINES} 87 | _stricmp=strcasecmp 88 | _strnicmp=strncasecmp 89 | _snprintf=snprintf 90 | _alloca=alloca 91 | _vsnprintf=vsnprintf 92 | _snwprintf=swprintf 93 | ) 94 | 95 | set(OPENGL_LIBRARY GL) 96 | elseif( COMPILER_MSVC ) 97 | 98 | # Disable "unsafe" warnings 99 | set( COMMON_DEFINES 100 | ${COMMON_DEFINES} 101 | _CRT_SECURE_NO_WARNINGS 102 | _SCL_SECURE_NO_WARNINGS 103 | ) 104 | 105 | set(OPENGL_LIBRARY opengl32) 106 | endif() 107 | 108 | if (COMPILER_GNU) 109 | set_target_properties(SvenBXT PROPERTIES 110 | C_VISIBILITY_PRESET hidden 111 | CXX_VISIBILITY_PRESET hidden 112 | COMPILE_FLAGS "${COMPILE_FLAGS} -fvisibility=hidden" 113 | LINKER_FLAGS "${LINKER_FLAGS} -fvisibility=hidden" 114 | ) 115 | endif() 116 | 117 | target_compile_definitions( SvenBXT PUBLIC 118 | ${COMMON_DEFINES} 119 | ) 120 | 121 | # Threads setup 122 | set(CMAKE_THREAD_PREFER_PTHREAD TRUE) 123 | set(THREADS_PREFER_PTHREAD_FLAG TRUE) 124 | 125 | # Modules 126 | find_package(Threads REQUIRED) 127 | find_package(OpenGL REQUIRED) 128 | 129 | # Link with dependencies 130 | target_link_libraries(SvenBXT 131 | Threads::Threads 132 | funchook-static 133 | ${OPENGL_LIBRARY} 134 | ) -------------------------------------------------------------------------------- /src/CTimer.h: -------------------------------------------------------------------------------- 1 | #ifdef CTIMER_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in CTimer.h 3 | #else //CTIMER_H_RECURSE_GUARD 4 | 5 | #define CTIMER_H_RECURSE_GUARD 6 | 7 | #ifndef CTIMER_H_GUARD 8 | #define CTIMER_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class CTimer 14 | { 15 | public: 16 | CTimer() 17 | { 18 | Init(); 19 | } 20 | 21 | void Init() 22 | { 23 | ResetTimer(); 24 | } 25 | 26 | void StartTimer() 27 | { 28 | m_bStarted = true; 29 | if (!m_bRunning) 30 | { 31 | m_startTime = std::chrono::steady_clock::now(); 32 | m_bRunning = true; 33 | } 34 | } 35 | 36 | void StopTimer() 37 | { 38 | if (m_bRunning) 39 | { 40 | auto now = std::chrono::steady_clock::now(); 41 | m_elapsedTime += std::chrono::duration_cast(now - m_startTime).count(); 42 | m_bRunning = false; 43 | } 44 | } 45 | 46 | void ResetTimer() 47 | { 48 | m_bRunning = false; 49 | m_elapsedTime = 0; 50 | } 51 | 52 | void SetTime(long long time) 53 | { 54 | m_elapsedTime = time; 55 | } 56 | 57 | 58 | void SyncTimer(long long serverTime, bool stop) 59 | { 60 | if (stop) 61 | { 62 | StopTimer(); 63 | SetTime(serverTime); 64 | } 65 | else 66 | { 67 | if (m_bRunning) 68 | { 69 | auto now = std::chrono::steady_clock::now(); 70 | long long currentElapsedTime = std::chrono::duration_cast(now - m_startTime).count() + m_elapsedTime; 71 | long long adjustment = serverTime - currentElapsedTime; 72 | m_startTime += std::chrono::milliseconds(adjustment); 73 | } 74 | else 75 | { 76 | SetTime(serverTime); 77 | StartTimer(); 78 | } 79 | } 80 | } 81 | 82 | long long GetTime() const 83 | { 84 | if (m_bRunning) 85 | { 86 | auto now = std::chrono::steady_clock::now(); 87 | return m_elapsedTime + std::chrono::duration_cast(now - m_startTime).count(); 88 | } 89 | return m_elapsedTime; 90 | } 91 | 92 | int GetMilliseconds() const 93 | { 94 | return static_cast(fmod(GetTime(), 1000.0)); 95 | } 96 | 97 | int GetSeconds() const 98 | { 99 | double seconds = GetTime() / 1000.0; 100 | return static_cast(fmod(seconds, 60.0)); 101 | } 102 | 103 | int GetMinutes() const 104 | { 105 | double minutes = GetTime() / 60000.0; 106 | return static_cast(fmod(minutes, 60.0)); 107 | } 108 | 109 | int GetHours() const 110 | { 111 | double hours = GetTime() / 3600000.0; 112 | return static_cast(fmod(hours, 24.0)); 113 | } 114 | 115 | int GetDays() const 116 | { 117 | double days = GetTime() / 86400000.0; 118 | return static_cast(days); 119 | } 120 | 121 | bool IsStopped() const 122 | { 123 | return m_bRunning ? false : true; 124 | } 125 | 126 | private: 127 | std::chrono::time_point m_startTime; 128 | long long m_elapsedTime; // elapsed time in milliseconds 129 | bool m_bRunning, m_bStarted; 130 | }; 131 | 132 | #else //!__cplusplus 133 | #error C++ compiler required to compile CTimer.h 134 | #endif //__cplusplus 135 | 136 | #endif //CTIMER_H_GUARD 137 | 138 | #undef CTIMER_H_RECURSE_GUARD 139 | #endif //CTIMER_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/SvenBXT.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by scriptedsnark on 7/18/24. 3 | // 4 | 5 | #include "SvenBXT.h" 6 | 7 | #ifdef PLATFORM_WINDOWS 8 | Utils utils = Utils::Utils(NULL, NULL, NULL); 9 | Utils sv_utils = Utils::Utils(NULL, NULL, NULL); 10 | #endif 11 | 12 | funchook_t* g_lpFuncHook_Server; 13 | funchook_t* g_lpFuncHook_Engine; 14 | funchook_t* g_lpFuncHook_Client; 15 | 16 | dllhandle_t g_lpEngine; 17 | dllhandle_t g_lpServer; 18 | dllhandle_t g_lpClient; 19 | 20 | cl_enginefunc_t* g_lpEngfuncs; 21 | enginefuncs_t* g_engfuncs; 22 | globalvars_t* gpGlobals; 23 | server_t* sv; 24 | 25 | bool g_bHasLoaded = false; 26 | 27 | void SvenBXT_HookClient(); 28 | 29 | void SvenBXT_FindEngineStuff() 30 | { 31 | TRACE("Finding engine stuff...\n"); 32 | 33 | g_lpFuncHook_Engine = funchook_create(); 34 | 35 | int status; 36 | #ifdef PLATFORM_LINUX 37 | g_lpEngfuncs = (cl_enginefunc_t*)Sys_GetProcAddress(g_lpEngine, "cl_enginefuncs"); 38 | 39 | if (!g_lpEngfuncs) 40 | { 41 | Sys_Printf("[hw so] Failed to get \"cl_enginefuncs\".\n"); 42 | return; 43 | } 44 | else 45 | { 46 | Sys_Printf("[hw so] Found cl_enginefuncs at %p.\n", g_lpEngfuncs); 47 | SvenBXT_HookClient(); 48 | } 49 | 50 | // TODO: use GET_VARIABLE define 51 | enginefuncs_t** p_engfuncs = (enginefuncs_t**)Sys_GetProcAddress(g_lpEngine, "g_pengfuncsExportedToDlls"); 52 | g_engfuncs = (*p_engfuncs); 53 | gpGlobals = (globalvars_t*)Sys_GetProcAddress(g_lpEngine, "gGlobalVariables"); 54 | sv = (server_t*)Sys_GetProcAddress(g_lpEngine, "sv"); 55 | 56 | if (!gpGlobals) 57 | { 58 | Sys_Printf("[hw so] Failed to get \"gGlobalVariables\".\n"); 59 | } 60 | 61 | if (!g_engfuncs) 62 | { 63 | Sys_Printf("[hw so] Failed to get \"g_engfuncsExportedToDlls\".\n[Engine] Sharing time to clients is not available.\n"); 64 | } 65 | 66 | if (!sv) 67 | { 68 | Sys_Printf("[hw so] Failed to get \"sv\".\n"); 69 | } 70 | 71 | GET_VARIABLE(Engine, ORIG_GL_Begin2D, _Z10GL_Begin2Dv); 72 | GET_VARIABLE(Engine, ORIG_GL_Finish2D, _Z11GL_Finish2Dv); 73 | 74 | GET_VARIABLE(Engine, ORIG_LoadThisDll, _Z11LoadThisDllPc); 75 | GET_VARIABLE(Engine, ORIG_SCR_BeginLoadingPlaque, _Z22SCR_BeginLoadingPlaquei); 76 | GET_VARIABLE(Engine, ORIG_SCR_EndLoadingPlaque, _Z20SCR_EndLoadingPlaquev); 77 | GET_VARIABLE(Engine, ORIG_GL_EndRendering, _Z15GL_EndRenderingv); 78 | #else 79 | void* handle; 80 | static void* base; 81 | static size_t size; 82 | 83 | if (!MemUtils::GetModuleInfo(L"hw.dll", &handle, &base, &size)) 84 | { 85 | Sys_Printf("Failed to get module info from engine.\n"); 86 | return; 87 | } 88 | 89 | utils = Utils::Utils(handle, base, size); 90 | 91 | void* ClientDLL_Init; 92 | auto fClientDLL_Init = utils.FindAsync( 93 | ClientDLL_Init, 94 | patterns::engine::ClientDLL_Init, 95 | [&](auto pattern) 96 | { 97 | switch (pattern - patterns::engine::ClientDLL_Init.cbegin()) 98 | { 99 | default: 100 | case 0: // Sven-5.25 101 | Sys_Printf("Searching cl_enginefuncs in Sven-5.25 pattern...\n"); 102 | g_lpEngfuncs = *reinterpret_cast(reinterpret_cast(ClientDLL_Init) + 332); 103 | 104 | if (g_lpEngfuncs) 105 | { 106 | Sys_Printf("[Engine] Found cl_enginefuncs at 0x%p.\n", g_lpEngfuncs); 107 | SvenBXT_HookClient(); 108 | } 109 | break; 110 | case 1: // Sven-5.26-rc1 111 | Sys_Printf("Searching cl_enginefuncs in Sven-5.26-rc1 pattern...\n"); 112 | g_lpEngfuncs = *reinterpret_cast(reinterpret_cast(ClientDLL_Init) + 354); 113 | 114 | if (g_lpEngfuncs) 115 | { 116 | Sys_Printf("[Engine] Found cl_enginefuncs at 0x%p.\n", g_lpEngfuncs); 117 | SvenBXT_HookClient(); 118 | } 119 | break; 120 | } 121 | }); 122 | 123 | void* LoadThisDll; 124 | auto fLoadThisDll = utils.FindAsync( 125 | LoadThisDll, 126 | patterns::engine::LoadThisDll, 127 | [&](auto pattern) 128 | { 129 | switch (pattern - patterns::engine::LoadThisDll.cbegin()) 130 | { 131 | default: 132 | case 0: // Sven-5.25 133 | Sys_Printf("Searching g_engfuncs in Sven-5.25 pattern...\n"); 134 | enginefuncs_t** p_engfuncs = *reinterpret_cast(reinterpret_cast(LoadThisDll) + 109); 135 | g_engfuncs = (*p_engfuncs); 136 | gpGlobals = *reinterpret_cast(reinterpret_cast(LoadThisDll) + 67); 137 | 138 | if (g_engfuncs) 139 | Sys_Printf("[Engine] Found g_engfuncs at 0x%p.\n", g_engfuncs); 140 | 141 | if (gpGlobals) 142 | Sys_Printf("[Engine] Found gpGlobals at 0x%p.\n", gpGlobals); 143 | break; 144 | } 145 | }); 146 | 147 | void* Host_ClearMemory; 148 | auto fHost_ClearMemory = utils.FindAsync( 149 | Host_ClearMemory, 150 | patterns::engine::Host_ClearMemory, 151 | [&](auto pattern) 152 | { 153 | switch (pattern - patterns::engine::Host_ClearMemory.cbegin()) 154 | { 155 | default: 156 | case 0: // Sven-5.25 157 | Sys_Printf("Searching sv in Sven-5.25 pattern...\n"); 158 | sv = *reinterpret_cast(reinterpret_cast(Host_ClearMemory) + 0x98); 159 | if (sv) 160 | { 161 | Sys_Printf("[Engine] Found sv at 0x%p.\n", sv); 162 | } 163 | break; 164 | } 165 | }); 166 | 167 | SPTEngineFind(GL_Begin2D); 168 | SPTEngineFind(GL_Finish2D); 169 | 170 | SPTEngineFind(LoadThisDll); 171 | SPTEngineFind(SCR_BeginLoadingPlaque); 172 | SPTEngineFind(SCR_EndLoadingPlaque); 173 | SPTEngineFind(GL_EndRendering); 174 | #endif 175 | 176 | CreateHook(Engine, LoadThisDll); 177 | CreateHook(Engine, SCR_BeginLoadingPlaque); 178 | CreateHook(Engine, SCR_EndLoadingPlaque); 179 | CreateHook(Engine, GL_EndRendering); 180 | 181 | funchook_install(g_lpFuncHook_Engine, 0); 182 | } 183 | 184 | void SvenBXT_HookClient() 185 | { 186 | TRACE("Hooking client...\n"); 187 | #ifdef PLATFORM_WINDOWS 188 | g_lpClient = Sys_GetModuleHandle("client"); 189 | #else 190 | g_lpClient = Sys_GetModuleHandle("svencoop/cl_dlls/client.so"); 191 | #endif 192 | 193 | if (!g_lpClient) 194 | { 195 | Sys_Printf("Failed to get client module handle.\n"); 196 | return; 197 | } 198 | 199 | g_lpFuncHook_Client = funchook_create(); 200 | 201 | CL_Initialize(); 202 | 203 | funchook_install(g_lpFuncHook_Client, 0); 204 | } 205 | 206 | void SvenBXT_HookEngine() 207 | { 208 | g_lpEngine = Sys_GetModuleHandle("hw" DLL_FORMAT); 209 | 210 | if (!g_lpEngine) 211 | { 212 | Sys_Printf("Failed to get engine module handle.\n"); 213 | return; 214 | } 215 | 216 | SvenBXT_FindEngineStuff(); 217 | } 218 | 219 | void SvenBXT_UnhookClient() 220 | { 221 | if (g_lpFuncHook_Client) 222 | { 223 | funchook_uninstall(g_lpFuncHook_Client, 0); 224 | funchook_destroy(g_lpFuncHook_Client); 225 | } 226 | } 227 | 228 | void SvenBXT_UnhookEngine() 229 | { 230 | if (g_lpFuncHook_Engine) 231 | { 232 | funchook_uninstall(g_lpFuncHook_Engine, 0); 233 | funchook_destroy(g_lpFuncHook_Engine); 234 | } 235 | } 236 | 237 | //----------------------------------------------------------------------------- 238 | // Purpose: hook in right time a.k.a I don't wanna hook LoadLibraryA/dlopen 239 | //----------------------------------------------------------------------------- 240 | void WaitUntilClientLoads() 241 | { 242 | lbl_waitFor: 243 | #ifdef PLATFORM_WINDOWS 244 | g_lpClient = Sys_GetModuleHandle("client"); 245 | #else 246 | g_lpClient = Sys_GetModuleHandle("svencoop/cl_dlls/client" DLL_FORMAT); 247 | #endif 248 | 249 | if (g_lpClient) 250 | { 251 | SvenBXT_HookEngine(); 252 | g_bHasLoaded = true; 253 | } 254 | else 255 | goto lbl_waitFor; 256 | } 257 | 258 | void SvenBXT_Main() 259 | { 260 | if (g_bHasLoaded) 261 | { 262 | Sys_Printf("Loader/injector or whatever else tried to initialize SvenBXT again!"); 263 | return; 264 | } 265 | 266 | // too lazy to do this using fopen 267 | std::ofstream ofs; 268 | ofs.open("svenbxt.log", std::ofstream::out | std::ofstream::trunc); 269 | ofs.close(); 270 | 271 | TRACE("Initializing SvenBXT...\n"); 272 | 273 | std::thread t(WaitUntilClientLoads); 274 | t.detach(); 275 | } 276 | 277 | void SvenBXT_Shutdown() 278 | { 279 | TRACE("Shutting down...\n"); 280 | 281 | SvenBXT_UnhookEngine(); 282 | SvenBXT_UnhookClient(); 283 | 284 | g_bHasLoaded = false; 285 | } 286 | 287 | #ifdef WIN32 288 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 289 | { 290 | switch (fdwReason) 291 | { 292 | case DLL_PROCESS_ATTACH: 293 | #ifdef _DEBUG 294 | AllocConsole(); 295 | FILE *in, *out; 296 | freopen_s(&in, "conin$", "r", stdin); 297 | freopen_s(&out, "conout$", "w+", stdout); 298 | #endif 299 | CreateThread(NULL, NULL, reinterpret_cast(SvenBXT_Main), NULL, NULL, NULL); 300 | break; 301 | 302 | case DLL_PROCESS_DETACH: 303 | SvenBXT_Shutdown(); 304 | break; 305 | } 306 | 307 | return TRUE; 308 | } 309 | #else 310 | static __attribute__((constructor)) void Construct() 311 | { 312 | SvenBXT_Main(); 313 | } 314 | 315 | static __attribute__((destructor)) void Destruct() 316 | { 317 | SvenBXT_Shutdown(); 318 | } 319 | #endif 320 | -------------------------------------------------------------------------------- /src/SvenBXT.h: -------------------------------------------------------------------------------- 1 | #ifdef SVENBXT_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in SvenBXT.h 3 | #else // SVENBXT_H_RECURSE_GUARD 4 | 5 | #define SVENBXT_H_RECURSE_GUARD 6 | 7 | #ifndef SVENBXT_H_GUARD 8 | #define SVENBXT_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | // GLOBAL DEFINE 14 | #define SVENBXT_VERSION __DATE__ // maybe something else? :thinking: 15 | #define SVENBXT_GITHUB_URL "https://github.com/ScriptedSnark/SvenBXT" 16 | 17 | // WINDOWS 18 | #ifdef PLATFORM_WINDOWS 19 | #include 20 | #include 21 | #else 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | // STL 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | // GL 39 | #include 40 | 41 | #include "external/funchook/include/funchook.h" 42 | 43 | #ifdef PLATFORM_WINDOWS 44 | #include "iface.hpp" 45 | 46 | #include "external/SPTLib/Utils.hpp" 47 | #include "engine_patterns.hpp" 48 | extern Utils utils; 49 | extern Utils sv_utils; 50 | #endif 51 | 52 | #include 53 | #include "hlsdk_mini.hpp" 54 | #include "engine/sound.h" 55 | #include "engine/server.h" 56 | 57 | // OWN STUFF 58 | #include "Utils.h" 59 | #include "CTimer.h" 60 | 61 | extern funchook_t* g_lpFuncHook_Server; 62 | extern funchook_t* g_lpFuncHook_Client; 63 | extern dllhandle_t g_lpEngine; 64 | extern dllhandle_t g_lpServer; 65 | extern dllhandle_t g_lpClient; 66 | extern cl_enginefunc_t* g_lpEngfuncs; 67 | extern enginefuncs_t* g_engfuncs; 68 | extern globalvars_t* gpGlobals; 69 | extern server_t* sv; 70 | 71 | #include "cl_dll/cdll_int.h" 72 | #include "cl_dll/hud.h" 73 | #include "cl_dll/parsemsg.h" 74 | #include "cl_dll/view.h" 75 | #include "cl_dll/tri.h" 76 | #include "cl_dll/opengl_utils.hpp" 77 | 78 | #include "engine/gl_screen.h" 79 | 80 | #include "dlls/enginecallback.h" 81 | #include "dlls/server.h" 82 | 83 | // HUD 84 | #include "cl_dll/hud_speedometer.h" 85 | #include "cl_dll/hud_viewangles.h" 86 | #include "cl_dll/hud_origin.h" 87 | #include "cl_dll/hud_timer.h" 88 | #include "cl_dll/hud_jumpspeed.h" 89 | #include "cl_dll/hud_crosshair.h" 90 | 91 | #ifdef PLATFORM_WINDOWS 92 | #define FASTCALL __fastcall 93 | #elif defined(PLATFORM_LINUX) 94 | #define FASTCALL 95 | #else 96 | #error Unsupported platform 97 | #endif 98 | 99 | #define GET_VARIABLE(tag, resultVar, procName) \ 100 | resultVar = (decltype(resultVar))Sys_GetProcAddress(g_lp##tag, #procName); \ 101 | if (!resultVar) \ 102 | Sys_Printf("[" #tag "] Failed to get \"" #procName "\".\n"); \ 103 | else \ 104 | Sys_Printf("[" #tag "] Found " #procName " at %p.\n", resultVar) \ 105 | 106 | #define Find(lib, func_name) \ 107 | if ((ORIG_##func_name = reinterpret_cast<_##func_name>(Sys_GetProcAddress(g_lp##lib, "" #func_name "")))) \ 108 | Sys_Printf("[" #lib "] Found " #func_name " at %p.\n", ORIG_##func_name); \ 109 | else \ 110 | Sys_Printf("[" #lib "] Could not find " #func_name ".\n") 111 | 112 | 113 | #ifdef PLATFORM_WINDOWS 114 | #define SPTEngineFind(future_name) \ 115 | { \ 116 | auto f##future_name = utils.FindAsync(ORIG_##future_name, patterns::engine::future_name); \ 117 | auto pattern = f##future_name.get(); \ 118 | if (ORIG_##future_name) \ 119 | { \ 120 | Sys_Printf("[Engine] Found " #future_name " at %p (using the %s pattern).\n", ORIG_##future_name, pattern->name()); \ 121 | } \ 122 | else \ 123 | Sys_Printf("[Engine] Could not find " #future_name ".\n"); \ 124 | } 125 | 126 | #define SPTServerFind(future_name) \ 127 | { \ 128 | auto f##future_name = sv_utils.FindAsync(ORIG_##future_name, patterns::server::future_name); \ 129 | auto pattern = f##future_name.get(); \ 130 | if (ORIG_##future_name) \ 131 | { \ 132 | Sys_Printf("[Server] Found " #future_name " at %p (using the %s pattern).\n", ORIG_##future_name, pattern->name()); \ 133 | } \ 134 | } 135 | #endif 136 | 137 | #define CreateHook(lib, func_name) \ 138 | do \ 139 | { \ 140 | Sys_Printf("[" #lib "] Creating hook for " #func_name "...\n"); \ 141 | status = funchook_prepare(g_lpFuncHook_##lib, (void**)&ORIG_##func_name, (void*)HOOKED_##func_name); \ 142 | if (status == FUNCHOOK_ERROR_SUCCESS) \ 143 | Sys_Printf("[" #lib "] Hooked " #func_name "!\n"); \ 144 | else \ 145 | Sys_Printf("[" #lib "] Failed to hook " #func_name "! Code: %i\n", status); \ 146 | } while (0) 147 | 148 | #else //!__cplusplus 149 | #error C++ compiler required to compile SvenBXT.h 150 | #endif //__cplusplus 151 | 152 | #endif // SVENBXT_H_GUARD 153 | 154 | #undef SVENBXT_H_RECURSE_GUARD 155 | #endif // SVENBXT_H_RECURSE_GUARD 156 | -------------------------------------------------------------------------------- /src/Utils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by scriptedsnark on 7/18/24. 3 | // 4 | 5 | #include "SvenBXT.h" 6 | 7 | /* 8 | ================ 9 | UTIL_IsHost 10 | ================ 11 | */ 12 | bool UTIL_IsHost() 13 | { 14 | if (!sv) 15 | return false; 16 | 17 | return sv->active; 18 | } 19 | 20 | /* 21 | ================ 22 | Sys_Printf 23 | ================ 24 | */ 25 | void Sys_Printf(const char* fmt, ...) 26 | { 27 | va_list va; 28 | 29 | FILE* file = fopen("svenbxt.log", "a"); 30 | 31 | va_start(va, fmt); 32 | 33 | if (file) 34 | { 35 | vfprintf(file, fmt, va); 36 | fclose(file); 37 | } 38 | 39 | vprintf(fmt, va); 40 | va_end(va); 41 | } 42 | 43 | /* 44 | ================ 45 | Sys_GetModuleHandle 46 | ================ 47 | */ 48 | dllhandle_t Sys_GetModuleHandle(const char* pszModuleName) 49 | { 50 | #ifdef PLATFORM_WINDOWS 51 | return GetModuleHandleA(pszModuleName); 52 | #else 53 | void* handle = dlopen(pszModuleName, RTLD_LAZY | RTLD_NOLOAD); 54 | if (handle == NULL) 55 | { 56 | if (dlerror() && dlerror()[0]) 57 | Sys_Printf("dlopen error: %s\n", dlerror()); 58 | 59 | return NULL; 60 | } 61 | 62 | return reinterpret_cast(handle); 63 | #endif 64 | } 65 | 66 | /* 67 | ================ 68 | Sys_GetProcAddress 69 | ================ 70 | */ 71 | farproc_t Sys_GetProcAddress(dllhandle_t handle, const char* name) 72 | { 73 | #ifdef PLATFORM_WINDOWS 74 | return GetProcAddress(handle, name); 75 | #else 76 | return dlsym(handle, name); 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /src/Utils.h: -------------------------------------------------------------------------------- 1 | #ifdef UTILS_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in Utils.h 3 | #else // UTILS_H_RECURSE_GUARD 4 | 5 | #define UTILS_H_RECURSE_GUARD 6 | 7 | #ifndef UTILS_H_GUARD 8 | #define UTILS_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | #ifdef PLATFORM_WINDOWS 14 | using dllhandle_t = HMODULE; 15 | using farproc_t = FARPROC; 16 | #define DLL_FORMAT ".dll" 17 | #else 18 | using dllhandle_t = void*; 19 | using farproc_t = void*; 20 | #define DLL_FORMAT ".so" 21 | #endif 22 | 23 | #define TRACE(format, ...) Sys_Printf("%s::%s(%d): " format, __FILE__, __FUNCTION__, __LINE__) 24 | 25 | bool UTIL_IsHost(); 26 | 27 | void Sys_Printf(const char* fmt, ...); 28 | dllhandle_t Sys_GetModuleHandle(const char* pszModuleName); 29 | farproc_t Sys_GetProcAddress(dllhandle_t handle, const char* name); 30 | 31 | #else //!__cplusplus 32 | #error C++ compiler required to compile Utils.h 33 | #endif //__cplusplus 34 | 35 | #endif // UTILS_H_GUARD 36 | 37 | #undef UTILS_H_RECURSE_GUARD 38 | #endif // UTILS_H_RECURSE_GUARD 39 | -------------------------------------------------------------------------------- /src/cl_dll/cdll_int.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | cvar_t* hud_bordersize; 4 | 5 | // From hl_weapons 6 | _HUD_PostRunCmd ORIG_HUD_PostRunCmd = nullptr; 7 | 8 | // From cdll_int 9 | _Initialize ORIG_Initialize = nullptr; 10 | _HUD_VidInit ORIG_HUD_VidInit = nullptr; 11 | _HUD_Init ORIG_HUD_Init = nullptr; 12 | _HUD_Redraw ORIG_HUD_Redraw = nullptr; 13 | _HUD_UpdateClientData ORIG_HUD_UpdateClientData = nullptr; 14 | _HUD_Reset ORIG_HUD_Reset = nullptr; 15 | _HUD_PlayerMove ORIG_HUD_PlayerMove = nullptr; 16 | _HUD_PlayerMoveInit ORIG_HUD_PlayerMoveInit = nullptr; 17 | _HUD_PlayerMoveTexture ORIG_HUD_PlayerMoveTexture = nullptr; 18 | _HUD_ConnectionlessPacket ORIG_HUD_ConnectionlessPacket = nullptr; 19 | _HUD_GetHullBounds ORIG_HUD_GetHullBounds = nullptr; 20 | _HUD_Frame ORIG_HUD_Frame = nullptr; 21 | _HUD_VoiceStatus ORIG_HUD_VoiceStatus = nullptr; 22 | _HUD_DirectorMessage ORIG_HUD_DirectorMessage = nullptr; 23 | _HUD_ChatInputPosition ORIG_HUD_ChatInputPosition = nullptr; 24 | 25 | // From demo 26 | _Demo_ReadBuffer ORIG_Demo_ReadBuffer = nullptr; 27 | 28 | // From entity 29 | _HUD_AddEntity ORIG_HUD_AddEntity = nullptr; 30 | _HUD_CreateEntities ORIG_HUD_CreateEntities = nullptr; 31 | _HUD_StudioEvent ORIG_HUD_StudioEvent = nullptr; 32 | _HUD_TxferLocalOverrides ORIG_HUD_TxferLocalOverrides = nullptr; 33 | _HUD_ProcessPlayerState ORIG_HUD_ProcessPlayerState = nullptr; 34 | _HUD_TxferPredictionData ORIG_HUD_TxferPredictionData = nullptr; 35 | _HUD_TempEntUpdate ORIG_HUD_TempEntUpdate = nullptr; 36 | _HUD_GetUserEntity ORIG_HUD_GetUserEntity = nullptr; 37 | 38 | // From in_camera 39 | _CAM_Think ORIG_CAM_Think = nullptr; 40 | _CL_IsThirdPerson ORIG_CL_IsThirdPerson = nullptr; 41 | _CL_CameraOffset ORIG_CL_CameraOffset = nullptr; 42 | 43 | // From input 44 | _KB_Find ORIG_KB_Find = nullptr; 45 | _CL_CreateMove ORIG_CL_CreateMove = nullptr; 46 | _HUD_Shutdown ORIG_HUD_Shutdown = nullptr; 47 | _HUD_Key_Event ORIG_HUD_Key_Event = nullptr; 48 | 49 | // From inputw32 50 | _IN_ActivateMouse ORIG_IN_ActivateMouse = nullptr; 51 | _IN_DeactivateMouse ORIG_IN_DeactivateMouse = nullptr; 52 | _IN_MouseEvent ORIG_IN_MouseEvent = nullptr; 53 | _IN_Accumulate ORIG_IN_Accumulate = nullptr; 54 | _IN_ClearStates ORIG_IN_ClearStates = nullptr; 55 | 56 | // From tri 57 | _HUD_DrawNormalTriangles ORIG_HUD_DrawNormalTriangles = nullptr; 58 | _HUD_DrawTransparentTriangles ORIG_HUD_DrawTransparentTriangles = nullptr; 59 | 60 | // From view 61 | _V_CalcRefdef ORIG_V_CalcRefdef = nullptr; 62 | 63 | // From GameStudioModelRenderer 64 | _HUD_GetStudioModelInterface ORIG_HUD_GetStudioModelInterface = nullptr; 65 | 66 | int HOOKED_HUD_VidInit(void) 67 | { 68 | TRACE("Initializing visuals...\n"); 69 | gBXTHud.VidInit(); 70 | 71 | return ORIG_HUD_VidInit(); 72 | } 73 | 74 | int HOOKED_HUD_Redraw(float time, int intermission) 75 | { 76 | gBXTHud.Redraw(time, intermission); 77 | 78 | return ORIG_HUD_Redraw(time, intermission); 79 | } 80 | 81 | void CL_Initialize() 82 | { 83 | int status; 84 | 85 | hud_bordersize = g_lpEngfuncs->GetCvarPointer("hud_bordersize"); // TODO: use this for HUD padding 86 | 87 | Find(Client, V_CalcRefdef); 88 | Find(Client, HUD_VidInit); 89 | Find(Client, HUD_Redraw); 90 | Find(Client, HUD_DrawTransparentTriangles); 91 | CreateHook(Client, V_CalcRefdef); 92 | CreateHook(Client, HUD_VidInit); 93 | CreateHook(Client, HUD_Redraw); 94 | CreateHook(Client, HUD_DrawTransparentTriangles); 95 | 96 | TRACE("Initializing HUD...\n"); 97 | gBXTHud.Init(); 98 | } 99 | -------------------------------------------------------------------------------- /src/cl_dll/cdll_int.h: -------------------------------------------------------------------------------- 1 | #ifdef CDLL_INT_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in cdll_int.h 3 | #else // CDLL_INT_H_RECURSE_GUARD 4 | 5 | #define CDLL_INT_H_RECURSE_GUARD 6 | 7 | #ifndef CDLL_INT_H_GUARD 8 | #define CDLL_INT_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | extern cvar_t* hud_bordersize; 14 | 15 | void CL_Initialize(); 16 | 17 | // From hl_weapons 18 | typedef void (*_HUD_PostRunCmd)(struct local_state_s* from, struct local_state_s* to, struct usercmd_s* cmd, int runfuncs, double time, unsigned int random_seed); 19 | 20 | // From cdll_int 21 | typedef int (*_Initialize)(cl_enginefunc_t* pEnginefuncs, int iVersion); 22 | typedef int (*_HUD_VidInit)(void); 23 | typedef void (*_HUD_Init)(void); 24 | typedef int (*_HUD_Redraw)(float flTime, int intermission); 25 | typedef int (*_HUD_UpdateClientData)(client_data_t* cdata, float flTime); 26 | typedef void (*_HUD_Reset)(void); 27 | typedef void (*_HUD_PlayerMove)(struct playermove_s* ppmove, int server); 28 | typedef void (*_HUD_PlayerMoveInit)(struct playermove_s* ppmove); 29 | typedef char (*_HUD_PlayerMoveTexture)(char* name); 30 | typedef int (*_HUD_ConnectionlessPacket)(const struct netadr_s* net_from, const char* args, char* response_buffer, int* response_buffer_size); 31 | typedef int (*_HUD_GetHullBounds)(int hullnumber, float* mins, float* maxs); 32 | typedef void (*_HUD_Frame)(double time); 33 | typedef void (*_HUD_VoiceStatus)(int entindex, qboolean bTalking); 34 | typedef void (*_HUD_DirectorMessage)(int iSize, void* pbuf); 35 | typedef void (*_HUD_ChatInputPosition)(int* x, int* y); 36 | 37 | // From demo 38 | typedef void (*_Demo_ReadBuffer)(int size, unsigned char* buffer); 39 | 40 | // From entity 41 | typedef int (*_HUD_AddEntity)(int type, struct cl_entity_s* ent, const char* modelname); 42 | typedef void (*_HUD_CreateEntities)(void); 43 | typedef void (*_HUD_StudioEvent)(const struct mstudioevent_s* event, const struct cl_entity_s* entity); 44 | typedef void (*_HUD_TxferLocalOverrides)(struct entity_state_s* state, const struct clientdata_s* client); 45 | typedef void (*_HUD_ProcessPlayerState)(struct entity_state_s* dst, const struct entity_state_s* src); 46 | typedef void (*_HUD_TxferPredictionData)(struct entity_state_s* ps, const struct entity_state_s* pps, struct clientdata_s* pcd, const struct clientdata_s* ppcd, struct weapon_data_s* wd, const struct weapon_data_s* pwd); 47 | typedef void (*_HUD_TempEntUpdate)(double frametime, double client_time, double cl_gravity, struct tempent_s** ppTempEntFree, struct tempent_s** ppTempEntActive, int (*Callback_AddVisibleEntity)(struct cl_entity_s* pEntity), void (*Callback_TempEntPlaySound)(struct tempent_s* pTemp, float damp)); 48 | typedef struct cl_entity_s* (*_HUD_GetUserEntity)(int index); 49 | 50 | // From in_camera 51 | typedef void (*_CAM_Think)(void); 52 | typedef int (*_CL_IsThirdPerson)(void); 53 | typedef void (*_CL_CameraOffset)(float* ofs); 54 | 55 | // From input 56 | typedef struct kbutton_s* (*_KB_Find)(const char* name); 57 | typedef void (*_CL_CreateMove)(float frametime, struct usercmd_s* cmd, int active); 58 | typedef void (*_HUD_Shutdown)(void); 59 | typedef int (*_HUD_Key_Event)(int eventcode, int keynum, const char* pszCurrentBinding); 60 | 61 | // From inputw32 62 | typedef void (*_IN_ActivateMouse)(void); 63 | typedef void (*_IN_DeactivateMouse)(void); 64 | typedef void (*_IN_MouseEvent)(int mstate); 65 | typedef void (*_IN_Accumulate)(void); 66 | typedef void (*_IN_ClearStates)(void); 67 | 68 | // From tri 69 | typedef void (*_HUD_DrawNormalTriangles)(void); 70 | typedef void (*_HUD_DrawTransparentTriangles)(void); 71 | 72 | // From view 73 | typedef void (*_V_CalcRefdef)(struct ref_params_s* pparams); 74 | 75 | // From GameStudioModelRenderer 76 | typedef int (*_HUD_GetStudioModelInterface)(int version, struct r_studio_interface_s** ppinterface, struct engine_studio_api_s* pstudio); 77 | 78 | extern _HUD_PostRunCmd ORIG_HUD_PostRunCmd; 79 | extern _Initialize ORIG_Initialize; 80 | extern _HUD_VidInit ORIG_HUD_VidInit; 81 | extern _HUD_Init ORIG_HUD_Init; 82 | extern _HUD_Redraw ORIG_HUD_Redraw; 83 | extern _HUD_UpdateClientData ORIG_HUD_UpdateClientData; 84 | extern _HUD_Reset ORIG_HUD_Reset; 85 | extern _HUD_PlayerMove ORIG_HUD_PlayerMove; 86 | extern _HUD_PlayerMoveInit ORIG_HUD_PlayerMoveInit; 87 | extern _HUD_PlayerMoveTexture ORIG_HUD_PlayerMoveTexture; 88 | extern _HUD_ConnectionlessPacket ORIG_HUD_ConnectionlessPacket; 89 | extern _HUD_GetHullBounds ORIG_HUD_GetHullBounds; 90 | extern _HUD_Frame ORIG_HUD_Frame; 91 | extern _HUD_VoiceStatus ORIG_HUD_VoiceStatus; 92 | extern _HUD_DirectorMessage ORIG_HUD_DirectorMessage; 93 | extern _HUD_ChatInputPosition ORIG_HUD_ChatInputPosition; 94 | extern _Demo_ReadBuffer ORIG_Demo_ReadBuffer; 95 | extern _HUD_AddEntity ORIG_HUD_AddEntity; 96 | extern _HUD_CreateEntities ORIG_HUD_CreateEntities; 97 | extern _HUD_StudioEvent ORIG_HUD_StudioEvent; 98 | extern _HUD_TxferLocalOverrides ORIG_HUD_TxferLocalOverrides; 99 | extern _HUD_ProcessPlayerState ORIG_HUD_ProcessPlayerState; 100 | extern _HUD_TxferPredictionData ORIG_HUD_TxferPredictionData; 101 | extern _HUD_TempEntUpdate ORIG_HUD_TempEntUpdate; 102 | extern _HUD_GetUserEntity ORIG_HUD_GetUserEntity; 103 | extern _CAM_Think ORIG_CAM_Think; 104 | extern _CL_IsThirdPerson ORIG_CL_IsThirdPerson; 105 | extern _CL_CameraOffset ORIG_CL_CameraOffset; 106 | extern _KB_Find ORIG_KB_Find; 107 | extern _CL_CreateMove ORIG_CL_CreateMove; 108 | extern _HUD_Shutdown ORIG_HUD_Shutdown; 109 | extern _HUD_Key_Event ORIG_HUD_Key_Event; 110 | extern _IN_ActivateMouse ORIG_IN_ActivateMouse; 111 | extern _IN_DeactivateMouse ORIG_IN_DeactivateMouse; 112 | extern _IN_MouseEvent ORIG_IN_MouseEvent; 113 | extern _IN_Accumulate ORIG_IN_Accumulate; 114 | extern _IN_ClearStates ORIG_IN_ClearStates; 115 | extern _HUD_DrawNormalTriangles ORIG_HUD_DrawNormalTriangles; 116 | extern _HUD_DrawTransparentTriangles ORIG_HUD_DrawTransparentTriangles; 117 | extern _V_CalcRefdef ORIG_V_CalcRefdef; 118 | extern _HUD_GetStudioModelInterface ORIG_HUD_GetStudioModelInterface; 119 | 120 | #else //!__cplusplus 121 | #error C++ compiler required to compile cdll_int.h 122 | #endif //__cplusplus 123 | 124 | #endif // CDLL_INT_H_GUARD 125 | 126 | #undef CDLL_INT_H_RECURSE_GUARD 127 | #endif // CDLL_INT_H_RECURSE_GUARD 128 | -------------------------------------------------------------------------------- /src/cl_dll/hud.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | #undef max 4 | #undef min 5 | 6 | CBXTHud gBXTHud; 7 | 8 | // some code is from HL SDK, OpenAG, BunnymodXT 9 | 10 | constexpr int ten_powers[] = { 11 | 1, 12 | 10, 13 | 100, 14 | 1000, 15 | 10000, 16 | 100000, 17 | 1000000, 18 | 10000000, 19 | 100000000, 20 | 1000000000}; 21 | 22 | // GetSpriteIndex() 23 | // searches through the sprite list loaded from hud.txt for a name matching SpriteName 24 | // returns an index into the gHUD.m_rghSprites[] array 25 | // returns 0 if sprite not found 26 | int CBXTHud::GetSpriteIndex(const char* SpriteName) 27 | { 28 | // look through the loaded sprite name list for SpriteName 29 | for (int i = 0; i < m_iSpriteCount; i++) 30 | { 31 | if (strncmp(SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH) == 0) 32 | return i; 33 | } 34 | 35 | return -1; // invalid sprite 36 | } 37 | 38 | void CBXTHud::GetPosition(cvar_t* offset, cvar_t* anchor, int* x, int* y, int rx = 0, int ry = 0) 39 | { 40 | std::istringstream iss; 41 | 42 | if (offset && offset->string[0]) 43 | { 44 | iss.str(offset->string); 45 | iss >> rx >> ry; 46 | iss.str(std::string()); 47 | iss.clear(); 48 | } 49 | 50 | iss.str(anchor->string); 51 | float w = 0, h = 0; 52 | iss >> w >> h; 53 | 54 | rx += static_cast(w * ScreenWidth); 55 | ry += static_cast(h * ScreenHeight); 56 | 57 | if (x) *x = rx; 58 | if (y) *y = ry; 59 | } 60 | 61 | void CBXTHud::Init(void) 62 | { 63 | hud_precision = CVAR_CREATE("sbxt_hud_precision", "6", 0); 64 | 65 | RegisterHUDElement(); 66 | RegisterHUDElement(); 67 | RegisterHUDElement(); 68 | RegisterHUDElement(); 69 | RegisterHUDElement(); 70 | RegisterHUDElement(); 71 | 72 | for (CBXTHudBase* i : m_vecHudList) 73 | { 74 | i->Init(); 75 | } 76 | } 77 | 78 | void CBXTHud::VidInit(void) 79 | { 80 | m_scrinfo.iSize = sizeof(m_scrinfo); 81 | g_lpEngfuncs->GetScreenInfo(&m_scrinfo); 82 | 83 | if (ScreenWidth < 640) 84 | m_iRes = 320; 85 | else 86 | m_iRes = 640; 87 | 88 | // Only load this once 89 | if (!m_pSpriteList) 90 | { 91 | // we need to load the hud.txt, and all sprites within 92 | m_pSpriteList = SPR_GetList("sprites/hud.txt", &m_iSpriteCountAllRes); 93 | 94 | if (m_pSpriteList) 95 | { 96 | // count the number of sprites of the appropriate res 97 | m_iSpriteCount = 0; 98 | client_sprite_t* p = m_pSpriteList; 99 | int j; 100 | for (j = 0; j < m_iSpriteCountAllRes; j++) 101 | { 102 | if (p->iRes == m_iRes) 103 | m_iSpriteCount++; 104 | p++; 105 | } 106 | 107 | // allocated memory for sprite handle arrays 108 | m_rghSprites = new HSPRITE_HL[m_iSpriteCount]; 109 | m_rgrcRects = new wrect_t[m_iSpriteCount]; 110 | m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH]; 111 | 112 | p = m_pSpriteList; 113 | int index = 0; 114 | for (j = 0; j < m_iSpriteCountAllRes; j++) 115 | { 116 | if (p->iRes == m_iRes) 117 | { 118 | char sz[256]; 119 | sprintf(sz, "sprites/%s.spr", p->szSprite); 120 | m_rghSprites[index] = SPR_Load(sz); 121 | m_rgrcRects[index] = p->rc; 122 | strncpy(&m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH); 123 | 124 | index++; 125 | } 126 | 127 | p++; 128 | } 129 | } 130 | } 131 | else 132 | { 133 | // we have already have loaded the sprite reference from hud.txt, but 134 | // we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game) 135 | client_sprite_t* p = m_pSpriteList; 136 | int index = 0; 137 | for (int j = 0; j < m_iSpriteCountAllRes; j++) 138 | { 139 | if (p->iRes == m_iRes) 140 | { 141 | char sz[256]; 142 | sprintf(sz, "sprites/%s.spr", p->szSprite); 143 | m_rghSprites[index] = SPR_Load(sz); 144 | index++; 145 | } 146 | 147 | p++; 148 | } 149 | } 150 | 151 | // assumption: number_1, number_2, etc, are all listed and loaded sequentially 152 | m_HUD_number_0 = GetSpriteIndex("number_0"); 153 | 154 | m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top; 155 | 156 | for (CBXTHudBase* i : m_vecHudList) 157 | { 158 | i->VidInit(); 159 | } 160 | 161 | m_bInitializedHUD = true; 162 | } 163 | 164 | int CBXTHud::RedrawAlwaysVisibleElements(float flTime) 165 | { 166 | if (!m_bInitializedHUD) 167 | return 1; 168 | 169 | for (CBXTHudBase* i : m_vecHudList) 170 | { 171 | if (i->m_iFlags & HUD_ALWAYSRENDER) 172 | i->Draw(flTime); 173 | } 174 | 175 | return 1; 176 | } 177 | 178 | int CBXTHud::Redraw(float flTime, int intermission) 179 | { 180 | if (!m_bInitializedHUD) 181 | return 1; 182 | 183 | for (CBXTHudBase* i : m_vecHudList) 184 | { 185 | if (i->m_iFlags & HUD_ALWAYSRENDER) 186 | continue; // see CBXTHud::RedrawAlwaysVisibleElements 187 | 188 | if (!intermission) 189 | { 190 | if (i->m_iFlags & HUD_ACTIVE) 191 | i->Draw(flTime); 192 | } 193 | else 194 | { // it's an intermission, so only draw hud elements that are set to draw during intermissions 195 | if (i->m_iFlags & HUD_INTERMISSION) 196 | i->Draw(flTime); 197 | } 198 | } 199 | 200 | return 1; 201 | } 202 | 203 | // should be in hud_redraw.cpp 204 | int CBXTHud::DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b) 205 | { 206 | int iWidth = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left; 207 | int k; 208 | 209 | if (iNumber > 0) 210 | { 211 | // SPR_Draw 100's 212 | if (iNumber >= 100) 213 | { 214 | k = iNumber / 100; 215 | SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b); 216 | SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k)); 217 | x += iWidth; 218 | } 219 | else if (iFlags & (DHN_3DIGITS)) 220 | { 221 | // SPR_DrawAdditive( 0, x, y, &rc ); 222 | x += iWidth; 223 | } 224 | 225 | // SPR_Draw 10's 226 | if (iNumber >= 10) 227 | { 228 | k = (iNumber % 100) / 10; 229 | SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b); 230 | SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k)); 231 | x += iWidth; 232 | } 233 | else if (iFlags & (DHN_3DIGITS | DHN_2DIGITS)) 234 | { 235 | // SPR_DrawAdditive( 0, x, y, &rc ); 236 | x += iWidth; 237 | } 238 | 239 | // SPR_Draw ones 240 | k = iNumber % 10; 241 | SPR_Set(GetSprite(m_HUD_number_0 + k), r, g, b); 242 | SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + k)); 243 | x += iWidth; 244 | } 245 | else if (iFlags & DHN_DRAWZERO) 246 | { 247 | SPR_Set(GetSprite(m_HUD_number_0), r, g, b); 248 | 249 | // SPR_Draw 100's 250 | if (iFlags & (DHN_3DIGITS)) 251 | { 252 | // SPR_DrawAdditive( 0, x, y, &rc ); 253 | x += iWidth; 254 | } 255 | 256 | if (iFlags & (DHN_3DIGITS | DHN_2DIGITS)) 257 | { 258 | // SPR_DrawAdditive( 0, x, y, &rc ); 259 | x += iWidth; 260 | } 261 | 262 | // SPR_Draw ones 263 | 264 | SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0)); 265 | x += iWidth; 266 | } 267 | 268 | return x; 269 | } 270 | 271 | int CBXTHud::DrawHudNumber(int x, int y, int number, int r, int g, int b) 272 | { 273 | size_t digit_width = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left; 274 | size_t digit_count = count_digits(number); 275 | 276 | for (int i = digit_count; i > 0; --i) 277 | { 278 | int digit = number / ten_powers[i - 1]; 279 | 280 | SPR_Set(GetSprite(m_HUD_number_0 + digit), r, g, b); 281 | SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + digit)); 282 | x += digit_width; 283 | 284 | number -= digit * ten_powers[i - 1]; 285 | } 286 | 287 | return x; 288 | } 289 | 290 | int CBXTHud::DrawHudNumberCentered(int x, int y, int number, int r, int g, int b) 291 | { 292 | size_t digit_width = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left; 293 | size_t digit_count = count_digits(number); 294 | 295 | return DrawHudNumber(x - (digit_width * digit_count) / 2, y, number, r, g, b); 296 | } 297 | 298 | int CBXTHud::DrawMultilineString(int x, int y, std::string s) 299 | { 300 | int max_new_x = 0; 301 | 302 | while (s.size() > 0) 303 | { 304 | size_t pos = s.find('\n'); 305 | 306 | int new_x = g_lpEngfuncs->DrawConsoleString(x, y, const_cast(s.substr(0, pos).c_str())); 307 | max_new_x = std::max(new_x, max_new_x); 308 | y += CharHeight; 309 | 310 | if (pos != std::string::npos) 311 | s = s.substr(pos + 1, std::string::npos); 312 | else 313 | s.erase(); 314 | }; 315 | 316 | return max_new_x; 317 | } 318 | 319 | int CBXTHud::DrawBitmap(int x, int y, const int bitmap[], int width, int height, int r, int g, int b) 320 | { 321 | for (int i = 0; i < height; i++) 322 | for (int j = 0; j < width; j++) 323 | FillRGBA(x + j, y + i, 1, 1, r, g, b, bitmap[i * width + j]); 324 | 325 | return width; 326 | } 327 | 328 | void CBXTHud::DrawDot(int x, int y, int r, int g, int b) 329 | { 330 | const int Dot320[] = { 331 | 143, 199, 122, 332 | 255, 255, 218, 333 | 120, 169, 95}; 334 | 335 | const int Dot640[] = { 336 | 21, 114, 128, 128, 83, 21, 337 | 150, 255, 255, 255, 255, 104, 338 | 239, 255, 255, 255, 255, 192, 339 | 226, 255, 255, 255, 255, 165, 340 | 114, 255, 255, 255, 255, 65, 341 | 29, 43, 89, 89, 29, 29}; 342 | 343 | if (ScreenWidth < 640) 344 | DrawBitmap(x, y, Dot320, 3, 3, r, g, b); 345 | else 346 | DrawBitmap(x, y, Dot640, 6, 6, r, g, b); 347 | } 348 | 349 | void CBXTHud::DrawLine(int x, int y, int length, int r, int g, int b) 350 | { 351 | if ((ScreenWidth < 640 && length < 3) || length < 5) 352 | { 353 | // might as well draw a dot 354 | DrawDot(x, y, r, g, b); 355 | return; 356 | } 357 | 358 | 359 | const int Line640_left[] = { 360 | 21, 114, 361 | 150, 255, 362 | 239, 255, 363 | 226, 255, 364 | 114, 255, 365 | 29, 43}; 366 | 367 | const int Line640_repeat[] = { 368 | 128, 369 | 255, 370 | 255, 371 | 255, 372 | 255, 373 | 89}; 374 | 375 | const int Line640_Right[] = { 376 | 83, 21, 377 | 255, 104, 378 | 255, 192, 379 | 255, 165, 380 | 255, 65, 381 | 29, 29}; 382 | 383 | const int Line320_left[] = { 384 | 143, 385 | 255, 386 | 120, 387 | }; 388 | 389 | const int Line320_repeat[] = { 390 | 199, 391 | 255, 392 | 169, 393 | }; 394 | 395 | const int Line320_Right[] = { 396 | 122, 397 | 218, 398 | 95}; 399 | 400 | const int* line_left; 401 | const int* line_repeat; 402 | const int* line_right; 403 | int linesprite_height; 404 | int linesprite_width; 405 | 406 | if (ScreenWidth <= 640) 407 | { 408 | line_left = Line320_left; 409 | line_repeat = Line320_repeat; 410 | line_right = Line320_Right; 411 | linesprite_height = 3; 412 | linesprite_width = 1; 413 | } 414 | else 415 | { 416 | line_left = Line640_left; 417 | line_repeat = Line640_repeat; 418 | line_right = Line640_Right; 419 | linesprite_height = 6; 420 | linesprite_width = 2; 421 | } 422 | 423 | y -= linesprite_height / 2; 424 | 425 | x += DrawBitmap(x, y, line_left, linesprite_width, linesprite_height, r, g, b); 426 | 427 | for (int xOffset = 0; xOffset < length - linesprite_width * 2; xOffset++) 428 | { 429 | x += DrawBitmap(x, y, line_repeat, 1, linesprite_height, r, g, b); 430 | } 431 | 432 | DrawBitmap(x, y, line_right, linesprite_width, linesprite_height, r, g, b); 433 | } 434 | 435 | int CBXTHud::DrawNumberXT(int number, int x, int y, int r, int g, int b, int fieldMinWidth) 436 | { 437 | if (number < 0) 438 | { 439 | if (number == std::numeric_limits::min()) 440 | { 441 | number = 0; 442 | } 443 | else 444 | { 445 | number = abs(number); 446 | DrawLine(x - NumberWidth, y + NumberHeight / 2, NumberWidth, r, g, b); 447 | } 448 | } 449 | 450 | static_assert(sizeof(int) >= 4, "Int less than 4 bytes in size is not supported."); 451 | 452 | int digits[10] = {0}; 453 | int i; 454 | for (i = 0; i < 10; ++i) 455 | { 456 | if (number == 0) 457 | break; 458 | 459 | digits[i] = number % 10; 460 | number /= 10; 461 | } 462 | 463 | for (; fieldMinWidth > 10; --fieldMinWidth) 464 | { 465 | DrawHudNumber(x, y, 0, r, g, b); 466 | x += NumberWidth; 467 | } 468 | if (fieldMinWidth > i) 469 | i = fieldMinWidth; 470 | 471 | for (int j = i; j > 0; --j) 472 | { 473 | DrawHudNumber(x, y, digits[j - 1], r, g, b); 474 | x += NumberWidth; 475 | } 476 | 477 | return x; 478 | } 479 | 480 | int CBXTHud::DrawNumberTimer(int number, int x, int y, int fieldMinWidth) 481 | { 482 | return DrawNumberXT(number, x, y, SVEN_HUD_COLOR, fieldMinWidth); 483 | } 484 | 485 | int CBXTHud::DrawNumberTimer(int number, int x, int y, int r, int g, int b, int fieldMinWidth) 486 | { 487 | return DrawNumberXT(number, x, y, r, g, b, fieldMinWidth); 488 | } 489 | 490 | void CBXTHud::DrawDecimalSeparator(int x, int y, int r, int g, int b) 491 | { 492 | x += (NumberWidth - 6) / 2; 493 | y += NumberHeight - 5; 494 | DrawDot(x + 1, y, r, g, b); 495 | } 496 | 497 | void CBXTHud::DrawDecimalSeparator(int x, int y) 498 | { 499 | return DrawDecimalSeparator(x, y, SVEN_HUD_COLOR); 500 | } 501 | 502 | void CBXTHud::DrawColon(int x, int y, int r, int g, int b) 503 | { 504 | x += (NumberWidth - 6) / 2; 505 | DrawDot(x + 1, y + 2, r, g, b); 506 | y += NumberHeight - 5; 507 | DrawDot(x + 1, y - 2, r, g, b); 508 | } 509 | 510 | void CBXTHud::DrawColon(int x, int y) 511 | { 512 | return DrawColon(x, y, SVEN_HUD_COLOR); 513 | } -------------------------------------------------------------------------------- /src/cl_dll/hud.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud.h 3 | #else // HUD_H_RECURSE_GUARD 4 | 5 | #define HUD_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_H_GUARD 8 | #define HUD_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | #define DHN_DRAWZERO 1 14 | #define DHN_2DIGITS 2 15 | #define DHN_3DIGITS 4 16 | 17 | #define HUD_ACTIVE (1 << 0) 18 | #define HUD_INTERMISSION (1 << 1) 19 | #define HUD_ALWAYSRENDER (1 << 2) 20 | 21 | #define MAX_SPRITE_NAME_LENGTH 24 22 | 23 | #define SVEN_HUD_COLOR 100, 130, 200 24 | 25 | // ScreenHeight returns the height of the screen, in pixels 26 | #define ScreenHeight (gBXTHud.m_scrinfo.iHeight) 27 | // ScreenWidth returns the width of the screen, in pixels 28 | #define ScreenWidth (gBXTHud.m_scrinfo.iWidth) 29 | // CharHeight returns the height of the char, in pixels 30 | #define CharHeight (gBXTHud.m_scrinfo.iCharHeight) 31 | 32 | #define NumberWidth (gBXTHud.GetSpriteRect(gBXTHud.m_HUD_number_0).right - gBXTHud.GetSpriteRect(gBXTHud.m_HUD_number_0).left) 33 | #define NumberHeight (gBXTHud.GetSpriteRect(gBXTHud.m_HUD_number_0).bottom - gBXTHud.GetSpriteRect(gBXTHud.m_HUD_number_0).top) 34 | 35 | // 36 | //----------------------------------------------------- 37 | // 38 | class CBXTHudBase 39 | { 40 | public: 41 | int m_iFlags; // active, moving, 42 | virtual int Init(void) { return 0; } 43 | virtual int VidInit(void) { return 0; } 44 | virtual int Draw(float flTime) { return 0; } 45 | virtual void Think(void) { return; } 46 | virtual void Reset(void) { return; } 47 | }; 48 | 49 | class CBXTHud 50 | { 51 | private: 52 | bool m_bInitializedHUD; 53 | std::vector m_vecHudList; 54 | 55 | HSPRITE_HL m_hsprLogo; 56 | int m_iLogo; 57 | client_sprite_t* m_pSpriteList; 58 | int m_iSpriteCount; 59 | int m_iSpriteCountAllRes; 60 | 61 | // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded. 62 | // freed in ~CHud() 63 | HSPRITE_HL* m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt 64 | wrect_t* m_rgrcRects; /*[HUD_SPRITE_COUNT]*/ 65 | char* m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/ 66 | 67 | public: 68 | int GetSpriteIndex(const char* SpriteName); 69 | void GetPosition(cvar_t* offset, cvar_t* anchor, int* x, int* y, int rx, int ry); 70 | 71 | void Init(void); 72 | void VidInit(void); 73 | void Think(void); 74 | int RedrawAlwaysVisibleElements(float flTime); 75 | int Redraw(float flTime, int intermission); 76 | int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b); 77 | int DrawHudNumber(int x, int y, int number, int r, int g, int b); 78 | int DrawHudNumberCentered(int x, int y, int number, int r, int g, int b); 79 | int DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b); 80 | int DrawHudNumberStringFixed(int xpos, int ypos, int iNumber, int r, int g, int b); 81 | int DrawMultilineString(int x, int y, std::string s); 82 | int DrawNumberTimer(int number, int x, int y, int fieldMinWidth); 83 | int DrawBitmap(int x, int y, const int bitmap[], int width, int height, int r, int g, int b); 84 | void DrawDot(int x, int y, int r, int g, int b); 85 | void DrawLine(int x, int y, int length, int r, int g, int b); 86 | int DrawNumberXT(int number, int x, int y, int r, int g, int b, int fieldMinWidth); 87 | int DrawNumberTimer(int number, int x, int y, int r, int g, int b, int fieldMinWidth); 88 | void DrawDecimalSeparator(int x, int y, int r, int g, int b); 89 | void DrawDecimalSeparator(int x, int y); 90 | void DrawColon(int x, int y, int r, int g, int b); 91 | void DrawColon(int x, int y); 92 | HSPRITE_HL GetSprite(int index) 93 | { 94 | return (index < 0) ? 0 : m_rghSprites[index]; 95 | } 96 | 97 | wrect_t& GetSpriteRect(int index) 98 | { 99 | return m_rgrcRects[index]; 100 | } 101 | 102 | template 103 | inline T* RegisterHUDElement() 104 | { 105 | T* p = new T(); 106 | m_vecHudList.push_back(p); 107 | return p; 108 | } 109 | 110 | public: 111 | SCREENINFO m_scrinfo; 112 | int m_iRes; 113 | int m_HUD_number_0; 114 | int m_iFontHeight; 115 | cvar_t* hud_precision; 116 | }; 117 | 118 | extern CBXTHud gBXTHud; 119 | 120 | // Macros to hook function calls into the HUD object 121 | #define HOOK_MESSAGE(x) g_lpEngfuncs->HookUserMsg(#x, __MsgFunc_##x); 122 | 123 | #define DECLARE_MESSAGE(y, x) \ 124 | int __MsgFunc_##x(const char* pszName, int iSize, void* pbuf) \ 125 | { \ 126 | return gBXTHud.y.MsgFunc_##x(pszName, iSize, pbuf); \ 127 | } 128 | 129 | 130 | #define HOOK_COMMAND(x, y) g_lpEngfuncs->AddCommand(x, __CmdFunc_##y); 131 | #define DECLARE_COMMAND(y, x) \ 132 | void __CmdFunc_##x(void) \ 133 | { \ 134 | gBXTHud.y.UserCmd_##x(); \ 135 | } 136 | 137 | inline float CVAR_GET_FLOAT(const char* x) { return g_lpEngfuncs->GetCvarFloat(x); } 138 | inline char* CVAR_GET_STRING(const char* x) { return g_lpEngfuncs->GetCvarString(x); } 139 | inline struct cvar_s* CVAR_CREATE(const char* cv, const char* val, const int flags) { return g_lpEngfuncs->RegisterVariable(cv, val, flags); } 140 | 141 | #define SPR_Load (*g_lpEngfuncs->SPR_Load) 142 | #define SPR_Set (*g_lpEngfuncs->SPR_Set) 143 | #define SPR_Frames (*g_lpEngfuncs->SPR_Frames) 144 | #define SPR_GetList (*g_lpEngfuncs->SPR_GetList) 145 | 146 | // SPR_Draw draws a the current sprite as solid 147 | #define SPR_Draw (*g_lpEngfuncs->SPR_Draw) 148 | // SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent) 149 | #define SPR_DrawHoles (*g_lpEngfuncs->SPR_DrawHoles) 150 | // SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency) 151 | #define SPR_DrawAdditive (*g_lpEngfuncs->SPR_DrawAdditive) 152 | 153 | // SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen. 154 | #define SPR_EnableScissor (*g_lpEngfuncs->SPR_EnableScissor) 155 | // SPR_DisableScissor disables the clipping rect 156 | #define SPR_DisableScissor (*g_lpEngfuncs->SPR_DisableScissor) 157 | // 158 | #define FillRGBA (*g_lpEngfuncs->FillRGBA) 159 | 160 | #define BASE_XRES 640.f 161 | 162 | // use this to project world coordinates to screen coordinates 163 | #define XPROJECT(x) ((1.0f + (x)) * ScreenWidth * 0.5f) 164 | #define YPROJECT(y) ((1.0f - (y)) * ScreenHeight * 0.5f) 165 | 166 | static inline float XRES(float x) 167 | { 168 | return x * ScreenWidth / 640; 169 | } 170 | 171 | static inline float YRES(float y) 172 | { 173 | return y * ScreenHeight / 480; 174 | } 175 | 176 | #define ServerCmd (*g_lpEngfuncs->ServerCmd) 177 | #define EngineClientCmd (*g_lpEngfuncs->ClientCmd) 178 | #define SetCrosshair (*g_lpEngfuncs->SetCrosshair) 179 | #define AngleVectors (*g_lpEngfuncs->AngleVectors) 180 | 181 | #define VectorSubtract(a, b, c) \ 182 | { \ 183 | (c)[0] = (a)[0] - (b)[0]; \ 184 | (c)[1] = (a)[1] - (b)[1]; \ 185 | (c)[2] = (a)[2] - (b)[2]; \ 186 | } 187 | #define VectorAdd(a, b, c) \ 188 | { \ 189 | (c)[0] = (a)[0] + (b)[0]; \ 190 | (c)[1] = (a)[1] + (b)[1]; \ 191 | (c)[2] = (a)[2] + (b)[2]; \ 192 | } 193 | #define VectorCopy(a, b) \ 194 | { \ 195 | (b)[0] = (a)[0]; \ 196 | (b)[1] = (a)[1]; \ 197 | (b)[2] = (a)[2]; \ 198 | } 199 | 200 | 201 | // Gets the height & width of a sprite, at the specified frame 202 | inline int SPR_Height(HSPRITE_HL x, int f) { return g_lpEngfuncs->SPR_Height(x, f); } 203 | inline int SPR_Width(HSPRITE_HL x, int f) { return g_lpEngfuncs->SPR_Width(x, f); } 204 | 205 | static size_t count_digits(int n) 206 | { 207 | size_t result = 0; 208 | 209 | do 210 | { 211 | ++result; 212 | } while ((n /= 10) != 0); 213 | 214 | return result; 215 | } 216 | 217 | 218 | #else //!__cplusplus 219 | #error C++ compiler required to compile hud.h 220 | #endif //__cplusplus 221 | 222 | #endif // HUD_H_GUARD 223 | 224 | #undef HUD_H_RECURSE_GUARD 225 | #endif // HUD_H_RECURSE_GUARD 226 | -------------------------------------------------------------------------------- /src/cl_dll/hud_crosshair.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | int CHudCrosshair::Init() 4 | { 5 | m_iFlags |= HUD_ACTIVE; 6 | 7 | // OpenGL crosshair cvars 8 | bxt_cross = CVAR_CREATE("sbxt_cross", "0", 0); 9 | bxt_cross_color = CVAR_CREATE("sbxt_cross_color", "", 0); 10 | bxt_cross_alpha = CVAR_CREATE("sbxt_cross_alpha", "255", 0); 11 | bxt_cross_thickness = CVAR_CREATE("sbxt_cross_thickness", "2", 0); 12 | bxt_cross_size = CVAR_CREATE("sbxt_cross_size", "10", 0); 13 | bxt_cross_gap = CVAR_CREATE("sbxt_cross_gap", "3", 0); 14 | bxt_cross_outline = CVAR_CREATE("sbxt_cross_outline", "0", 0); 15 | bxt_cross_circle_radius = CVAR_CREATE("sbxt_cross_circle_radius", "0", 0); 16 | bxt_cross_dot_color = CVAR_CREATE("sbxt_cross_dot_color", "", 0); 17 | bxt_cross_dot_size = CVAR_CREATE("sbxt_cross_dot_size", "0", 0); 18 | bxt_cross_top_line = CVAR_CREATE("sbxt_cross_top_line", "1", 0); 19 | bxt_cross_bottom_line = CVAR_CREATE("sbxt_cross_bottom_line", "1", 0); 20 | bxt_cross_left_line = CVAR_CREATE("sbxt_cross_left_line", "1", 0); 21 | bxt_cross_right_line = CVAR_CREATE("sbxt_cross_right_line", "1", 0); 22 | 23 | return 0; 24 | } 25 | 26 | int CHudCrosshair::VidInit() 27 | { 28 | return 1; 29 | } 30 | 31 | int CHudCrosshair::Draw(float time) 32 | { 33 | if (!bxt_cross->value) 34 | return 0; 35 | 36 | float old_circle_radius = 0; 37 | std::vector circle_points; 38 | 39 | float r = 0.0f, g = 0.0f, b = 0.0f; 40 | std::istringstream ss(bxt_cross_color->string); 41 | ss >> r >> g >> b; 42 | 43 | static float crosshairColor[3]; 44 | crosshairColor[0] = r; 45 | crosshairColor[1] = g; 46 | crosshairColor[2] = b; 47 | 48 | float alpha = bxt_cross_alpha->value / 255.0f; 49 | 50 | Vector2D center(static_cast(ScreenWidth) / 2.0f, static_cast(ScreenHeight) / 2.0f); 51 | 52 | GLUtils gl; 53 | 54 | // Draw the outline. 55 | if (bxt_cross_outline->value > 0.0f) 56 | { 57 | gl.color(0.0f, 0.0f, 0.0f, alpha); 58 | gl.line_width(bxt_cross_outline->value); 59 | 60 | auto size = bxt_cross_size->value; 61 | auto gap = bxt_cross_gap->value; 62 | auto half_thickness = bxt_cross_thickness->value / 2.0f; 63 | auto half_width = bxt_cross_outline->value / 2.0f; 64 | auto offset = half_thickness + half_width; 65 | 66 | // Top line 67 | if (bxt_cross_top_line->value) 68 | { 69 | gl.line(Vector2D(center.x - offset, center.y - gap - size), Vector2D(center.x + offset, center.y - gap - size)); 70 | gl.line(Vector2D(center.x + half_thickness, center.y - gap - size + half_width), Vector2D(center.x + half_thickness, center.y - gap - half_width)); 71 | gl.line(Vector2D(center.x + offset, center.y - gap), Vector2D(center.x - offset, center.y - gap)); 72 | gl.line(Vector2D(center.x - half_thickness, center.y - gap - half_width), Vector2D(center.x - half_thickness, center.y - gap - size + half_width)); 73 | } 74 | 75 | // Bottom line 76 | if (bxt_cross_bottom_line->value) 77 | { 78 | gl.line(Vector2D(center.x - offset, center.y + gap + size), Vector2D(center.x + offset, center.y + gap + size)); 79 | gl.line(Vector2D(center.x + half_thickness, center.y + gap + size - half_width), Vector2D(center.x + half_thickness, center.y + gap + half_width)); 80 | gl.line(Vector2D(center.x + offset, center.y + gap), Vector2D(center.x - offset, center.y + gap)); 81 | gl.line(Vector2D(center.x - half_thickness, center.y + gap + half_width), Vector2D(center.x - half_thickness, center.y + gap + size - half_width)); 82 | } 83 | 84 | // Left line 85 | if (bxt_cross_left_line->value) 86 | { 87 | gl.line(Vector2D(center.x - gap - size, center.y - offset), Vector2D(center.x - gap - size, center.y + offset)); 88 | gl.line(Vector2D(center.x - gap - size + half_width, center.y + half_thickness), Vector2D(center.x - gap - half_width, center.y + half_thickness)); 89 | gl.line(Vector2D(center.x - gap, center.y + offset), Vector2D(center.x - gap, center.y - offset)); 90 | gl.line(Vector2D(center.x - gap - half_width, center.y - half_thickness), Vector2D(center.x - gap - size + half_width, center.y - half_thickness)); 91 | } 92 | 93 | // Right line 94 | if (bxt_cross_right_line->value) 95 | { 96 | gl.line(Vector2D(center.x + gap + size, center.y - offset), Vector2D(center.x + gap + size, center.y + offset)); 97 | gl.line(Vector2D(center.x + gap + size - half_width, center.y + half_thickness), Vector2D(center.x + gap + half_width, center.y + half_thickness)); 98 | gl.line(Vector2D(center.x + gap, center.y + offset), Vector2D(center.x + gap, center.y - offset)); 99 | gl.line(Vector2D(center.x + gap + half_width, center.y - half_thickness), Vector2D(center.x + gap + size - half_width, center.y - half_thickness)); 100 | } 101 | 102 | // Dot 103 | if (bxt_cross_dot_size->value > 0.0f) 104 | { 105 | auto size = bxt_cross_dot_size->value; 106 | auto offset = Vector2D(size / 2.0f, size / 2.0f); 107 | 108 | gl.line(Vector2D(center.x - offset.x - half_width, center.y - offset.y), Vector2D(center.x + offset.x + half_width, center.y - offset.y)); 109 | gl.line(Vector2D(center.x + offset.x, center.y - offset.y + half_width), Vector2D(center.x + offset.x, center.y + offset.y - half_width)); 110 | gl.line(Vector2D(center.x - offset.x, center.y - offset.y + half_width), Vector2D(center.x - offset.x, center.y + offset.y - half_width)); 111 | gl.line(Vector2D(center.x - offset.x - half_width, center.y + offset.y), Vector2D(center.x + offset.x + half_width, center.y + offset.y)); 112 | } 113 | } 114 | 115 | if (bxt_cross_color->string[0]) 116 | { 117 | gl.color(crosshairColor[0], crosshairColor[1], crosshairColor[2], alpha); 118 | } 119 | else 120 | { 121 | gl.color(0.0f, 255.0f, 0.0f, alpha); 122 | } 123 | 124 | // Draw the crosshairs. 125 | if (bxt_cross_thickness->value > 0.0f) 126 | { 127 | gl.line_width(bxt_cross_thickness->value); 128 | 129 | auto size = bxt_cross_size->value; 130 | auto gap = bxt_cross_gap->value; 131 | 132 | if (bxt_cross_top_line->value) 133 | gl.line(Vector2D(center.x, center.y - gap - size), Vector2D(center.x, center.y - gap)); 134 | if (bxt_cross_bottom_line->value) 135 | gl.line(Vector2D(center.x, center.y + gap + size), Vector2D(center.x, center.y + gap)); 136 | if (bxt_cross_left_line->value) 137 | gl.line(Vector2D(center.x - gap - size, center.y), Vector2D(center.x - gap, center.y)); 138 | if (bxt_cross_right_line->value) 139 | gl.line(Vector2D(center.x + gap + size, center.y), Vector2D(center.x + gap, center.y)); 140 | } 141 | 142 | // Draw the circle. 143 | if (bxt_cross_circle_radius->value > 0.0f) 144 | { 145 | gl.line_width(1.0f); 146 | 147 | auto radius = bxt_cross_circle_radius->value; 148 | if (old_circle_radius != radius) 149 | { 150 | // Recompute the circle points. 151 | circle_points = gl.compute_circle(radius); 152 | old_circle_radius = radius; 153 | } 154 | 155 | gl.circle(center, circle_points); 156 | } 157 | 158 | // Draw the dot. 159 | if (bxt_cross_dot_size->value > 0.0f) 160 | { 161 | float r = 0.0f, g = 0.0f, b = 0.0f; 162 | std::istringstream ss(bxt_cross_dot_color->string); 163 | ss >> r >> g >> b; 164 | 165 | static float crosshairDotColor[3]; 166 | crosshairDotColor[0] = r; 167 | crosshairDotColor[1] = g; 168 | crosshairDotColor[2] = b; 169 | 170 | if (bxt_cross_dot_color->string[0]) 171 | { 172 | gl.color(crosshairDotColor[0], crosshairDotColor[1], crosshairDotColor[2], alpha); 173 | } 174 | else 175 | { 176 | gl.color(255.0f, 0.0f, 0.0f, alpha); 177 | } 178 | 179 | auto size = bxt_cross_dot_size->value; 180 | auto offset = Vector2D(size / 2.0f, size / 2.0f); 181 | 182 | gl.rectangle(center - offset, center + offset); 183 | } 184 | 185 | return 0; 186 | } 187 | -------------------------------------------------------------------------------- /src/cl_dll/hud_crosshair.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_CROSSHAIR_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_crosshair.h 3 | #else //HUD_CROSSHAIR_H_RECURSE_GUARD 4 | 5 | #define HUD_CROSSHAIR_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_CROSSHAIR_H_GUARD 8 | #define HUD_CROSSHAIR_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class CHudCrosshair: public CBXTHudBase 14 | { 15 | public: 16 | virtual int Init(); 17 | virtual int VidInit(); 18 | virtual int Draw(float time); 19 | 20 | private: 21 | cvar_t* bxt_cross; 22 | cvar_t* bxt_cross_color; 23 | cvar_t* bxt_cross_alpha; 24 | cvar_t* bxt_cross_thickness; 25 | cvar_t* bxt_cross_size; 26 | cvar_t* bxt_cross_gap; 27 | cvar_t* bxt_cross_outline; 28 | cvar_t* bxt_cross_circle_radius; 29 | cvar_t* bxt_cross_dot_color; 30 | cvar_t* bxt_cross_dot_size; 31 | cvar_t* bxt_cross_top_line; 32 | cvar_t* bxt_cross_bottom_line; 33 | cvar_t* bxt_cross_left_line; 34 | cvar_t* bxt_cross_right_line; 35 | }; 36 | 37 | 38 | #else //!__cplusplus 39 | #error C++ compiler required to compile hud_crosshair.h 40 | #endif //__cplusplus 41 | 42 | #endif //HUD_CROSSHAIR_H_GUARD 43 | 44 | #undef HUD_CROSSHAIR_H_RECURSE_GUARD 45 | #endif //HUD_CROSSHAIR_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/hud_jumpspeed.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | CHudJumpspeed* g_lpJumpspeedHUD; 4 | 5 | int CHudJumpspeed::Init() 6 | { 7 | g_lpJumpspeedHUD = this; 8 | m_iFlags |= HUD_ACTIVE; 9 | 10 | hud_jumpspeed = CVAR_CREATE("sbxt_hud_jumpspeed", "0", 0); 11 | hud_jumpspeed_below_cross = CVAR_CREATE("sbxt_hud_jumpspeed_below_cross", "0", 0); 12 | hud_jumpspeed_height = CVAR_CREATE("sbxt_hud_jumpspeed_height", "0", 0); 13 | 14 | return 0; 15 | } 16 | 17 | int CHudJumpspeed::VidInit() 18 | { 19 | passedTime = FADE_DURATION_JUMPSPEED; 20 | return 1; 21 | } 22 | 23 | int CHudJumpspeed::Draw(float flTime) 24 | { 25 | if (!hud_jumpspeed->value) 26 | return 0; 27 | 28 | int x = ScreenWidth / 2; 29 | int y = ScreenHeight - gBXTHud.m_iFontHeight - gBXTHud.m_iFontHeight / 2; 30 | 31 | if (hud_jumpspeed_below_cross->value != 0.0f) 32 | y = ScreenHeight / 2 + gBXTHud.m_iFontHeight / 2 + gBXTHud.m_iFontHeight; 33 | else if (hud_jumpspeed_height->value != 0.0f) 34 | y = hud_jumpspeed_height->value; 35 | 36 | // SVEN_HUD_COLOR 37 | int r = 100; 38 | int g = 130; 39 | int b = 200; 40 | 41 | // Can be negative if we went back in time (for example, loaded a save). 42 | double timeDelta = std::fmax(flTime - lastTime, 0.0f); 43 | passedTime += timeDelta; 44 | 45 | // Check for Inf, NaN, etc. 46 | if (passedTime > FADE_DURATION_JUMPSPEED || !std::isnormal(passedTime)) 47 | passedTime = FADE_DURATION_JUMPSPEED; 48 | 49 | float colorVel[3] = {r - fadingFrom[0] / FADE_DURATION_JUMPSPEED, 50 | g - fadingFrom[1] / FADE_DURATION_JUMPSPEED, 51 | b - fadingFrom[2] / FADE_DURATION_JUMPSPEED}; 52 | 53 | r = static_cast(r - colorVel[0] * (FADE_DURATION_JUMPSPEED - passedTime)); 54 | g = static_cast(g - colorVel[1] * (FADE_DURATION_JUMPSPEED - passedTime)); 55 | b = static_cast(b - colorVel[2] * (FADE_DURATION_JUMPSPEED - passedTime)); 56 | 57 | lastTime = flTime; 58 | gBXTHud.DrawHudNumberCentered(x, y, speed, r, g, b); 59 | 60 | return 0; 61 | } 62 | 63 | void CHudJumpspeed::UpdateSpeed(const float velocity[3]) 64 | { 65 | if (FADE_DURATION_JUMPSPEED > 0.0f) 66 | { 67 | if ((velocity[2] != 0.0f && prevVel[2] == 0.0f) || (velocity[2] > 0.0f && prevVel[2] < 0.0f)) 68 | { 69 | double difference = std::hypot(velocity[0], velocity[1]) - speed; 70 | if (difference != 0.0f) 71 | { 72 | if (difference > 0.0f) 73 | { 74 | fadingFrom[0] = 0; 75 | fadingFrom[1] = 255; 76 | fadingFrom[2] = 0; 77 | } 78 | else 79 | { 80 | fadingFrom[0] = 255; 81 | fadingFrom[1] = 0; 82 | fadingFrom[2] = 0; 83 | } 84 | 85 | passedTime = 0.0; 86 | speed = std::hypot(velocity[0], velocity[1]); // TODO: std::round? 87 | } 88 | } 89 | } 90 | VectorCopy(velocity, prevVel); 91 | } -------------------------------------------------------------------------------- /src/cl_dll/hud_jumpspeed.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_JUMPSPEED_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_jumpspeed.h 3 | #else //HUD_JUMPSPEED_H_RECURSE_GUARD 4 | 5 | #define HUD_JUMPSPEED_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_JUMPSPEED_H_GUARD 8 | #define HUD_JUMPSPEED_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | #define FADE_DURATION_JUMPSPEED 0.7f 14 | 15 | class CHudJumpspeed: public CBXTHudBase 16 | { 17 | public: 18 | virtual int Init(); 19 | virtual int VidInit(); 20 | virtual int Draw(float time); 21 | 22 | void UpdateSpeed(const float velocity[3]); 23 | 24 | private: 25 | uint16_t speed; 26 | 27 | cvar_t* hud_jumpspeed; 28 | cvar_t* hud_jumpspeed_below_cross; 29 | cvar_t* hud_jumpspeed_height; 30 | 31 | int fadingFrom[3]; 32 | float prevVel[3] = {0.0f, 0.0f, 0.0f}; 33 | float lastTime; 34 | double passedTime; 35 | }; 36 | 37 | extern CHudJumpspeed* g_lpJumpspeedHUD; 38 | 39 | #else //!__cplusplus 40 | #error C++ compiler required to compile hud_jumpspeed.h 41 | #endif //__cplusplus 42 | 43 | #endif //HUD_JUMPSPEED_H_GUARD 44 | 45 | #undef HUD_JUMPSPEED_H_RECURSE_GUARD 46 | #endif //HUD_JUMPSPEED_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/hud_origin.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | int CHudOrigin::Init() 4 | { 5 | m_iFlags |= HUD_ACTIVE; 6 | 7 | hud_origin = CVAR_CREATE("sbxt_hud_origin", "0", 0); 8 | hud_origin_anchor = CVAR_CREATE("sbxt_hud_origin_anchor", "1 0", 0); 9 | hud_origin_offset = CVAR_CREATE("sbxt_hud_origin_offset", "", 0); 10 | 11 | return 0; 12 | } 13 | 14 | int CHudOrigin::VidInit() 15 | { 16 | return 1; 17 | } 18 | 19 | int CHudOrigin::Draw(float time) 20 | { 21 | if (!hud_origin->value) 22 | return 0; 23 | 24 | int x, y; 25 | gBXTHud.GetPosition(hud_origin_offset, hud_origin_anchor, &x, &y, -200, (CharHeight * 6) + 1); 26 | 27 | g_lpEngfuncs->DrawConsoleString(x, y, "Origin:"); 28 | 29 | y += CharHeight; 30 | 31 | std::ostringstream out; 32 | out.setf(std::ios::fixed); 33 | out.precision((int)gBXTHud.hud_precision->value); 34 | 35 | out << "X: " << g_RefParams.simorg[0] << "\n" 36 | << "Y: " << g_RefParams.simorg[1] << "\n" 37 | << "Z: " << g_RefParams.simorg[2]; 38 | 39 | gBXTHud.DrawMultilineString(x, y, out.str()); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/cl_dll/hud_origin.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_ORIGIN_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_origin.h 3 | #else //HUD_ORIGIN_H_RECURSE_GUARD 4 | 5 | #define HUD_ORIGIN_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_ORIGIN_H_GUARD 8 | #define HUD_ORIGIN_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class CHudOrigin: public CBXTHudBase 14 | { 15 | public: 16 | virtual int Init(); 17 | virtual int VidInit(); 18 | virtual int Draw(float time); 19 | 20 | private: 21 | cvar_t* hud_origin; 22 | cvar_t* hud_origin_anchor; 23 | cvar_t* hud_origin_offset; 24 | }; 25 | 26 | #else //!__cplusplus 27 | #error C++ compiler required to compile hud_origin.h 28 | #endif //__cplusplus 29 | 30 | #endif //HUD_ORIGIN_H_GUARD 31 | 32 | #undef HUD_ORIGIN_H_RECURSE_GUARD 33 | #endif //HUD_ORIGIN_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/hud_speedometer.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | int CHudSpeedometer::Init() 4 | { 5 | m_iFlags = HUD_ACTIVE; 6 | 7 | hud_speedometer = CVAR_CREATE("sbxt_hud_speedometer", "1", 0); 8 | hud_speedometer_below_cross = CVAR_CREATE("sbxt_hud_speedometer_below_cross", "0", 0); 9 | hud_speedometer_height = CVAR_CREATE("sbxt_hud_speedometer_height", "0", 0); 10 | 11 | return 0; 12 | } 13 | 14 | int CHudSpeedometer::VidInit() 15 | { 16 | return 1; 17 | } 18 | 19 | int CHudSpeedometer::Draw(float time) 20 | { 21 | if (!hud_speedometer->value) 22 | return 0; 23 | 24 | int x = ScreenWidth / 2; 25 | int y = ScreenHeight - gBXTHud.m_iFontHeight - gBXTHud.m_iFontHeight / 2 - gBXTHud.m_iFontHeight; 26 | 27 | if (hud_speedometer_below_cross->value) 28 | y = ScreenHeight / 2 + gBXTHud.m_iFontHeight / 2; 29 | else if (hud_speedometer_height->value) 30 | y = hud_speedometer_height->value; 31 | 32 | gBXTHud.DrawHudNumberCentered(x, y, std::round(std::hypot(g_RefParams.simvel[0], g_RefParams.simvel[1])), SVEN_HUD_COLOR); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /src/cl_dll/hud_speedometer.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_SPEEDOMETER_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_speedometer.h 3 | #else // HUD_SPEEDOMETER_H_RECURSE_GUARD 4 | 5 | #define HUD_SPEEDOMETER_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_SPEEDOMETER_H_GUARD 8 | #define HUD_SPEEDOMETER_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class CHudSpeedometer: public CBXTHudBase 14 | { 15 | public: 16 | virtual int Init(); 17 | virtual int VidInit(); 18 | virtual int Draw(float time); 19 | 20 | private: 21 | cvar_t* hud_speedometer; 22 | cvar_t* hud_speedometer_below_cross; 23 | cvar_t* hud_speedometer_height; 24 | }; 25 | 26 | #else //!__cplusplus 27 | #error C++ compiler required to compile hud_speedometer.h 28 | #endif //__cplusplus 29 | 30 | #endif // HUD_SPEEDOMETER_H_GUARD 31 | 32 | #undef HUD_SPEEDOMETER_H_RECURSE_GUARD 33 | #endif // HUD_SPEEDOMETER_H_RECURSE_GUARD 34 | -------------------------------------------------------------------------------- /src/cl_dll/hud_timer.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | CTimer g_RTATimer; 4 | CTimer g_IGTTimer; 5 | 6 | CHudTimer* g_lpHUDTimer; 7 | 8 | void __CmdFunc_TimerStart() 9 | { 10 | if (!g_lpHUDTimer) 11 | return; 12 | 13 | if (g_lpHUDTimer->ShouldSync()) 14 | return; 15 | 16 | g_lpHUDTimer->TimerStart(); 17 | } 18 | 19 | void __CmdFunc_TimerStop() 20 | { 21 | if (!g_lpHUDTimer) 22 | return; 23 | 24 | if (g_lpHUDTimer->ShouldSync()) 25 | return; 26 | 27 | g_lpHUDTimer->TimerStop(); 28 | } 29 | 30 | void __CmdFunc_TimerReset() 31 | { 32 | if (!g_lpHUDTimer) 33 | return; 34 | 35 | if (g_lpHUDTimer->ShouldSync()) 36 | return; 37 | 38 | g_lpHUDTimer->TimerStop(); 39 | g_lpHUDTimer->TimerReset(); 40 | } 41 | 42 | int __MsgFunc_BXTTimer(const char* pszName, int iSize, void* pbuf) 43 | { 44 | BEGIN_READ(pbuf, iSize); 45 | 46 | if (!g_lpHUDTimer->ShouldSync()) 47 | return 0; 48 | 49 | long time = READ_LONG(); 50 | bool stop = READ_BYTE(); 51 | 52 | g_RTATimer.SyncTimer(time, stop); 53 | 54 | return 0; 55 | } 56 | 57 | int CHudTimer::Init() 58 | { 59 | g_lpHUDTimer = this; 60 | m_iFlags |= HUD_ALWAYSRENDER; 61 | 62 | hud_timer_serversync = CVAR_CREATE("sbxt_timer_serversync", "1", 0); 63 | hud_timer_il_mode = CVAR_CREATE("sbxt_timer_il_mode", "0", 0); 64 | hud_timer = CVAR_CREATE("sbxt_hud_timer", "0", 0); 65 | hud_timer_anchor = CVAR_CREATE("sbxt_hud_timer_anchor", "0.0 0.5", 0); 66 | hud_timer_offset = CVAR_CREATE("sbxt_hud_timer_offset", "", 0); 67 | 68 | HOOK_COMMAND("sbxt_timer_start", TimerStart); 69 | HOOK_COMMAND("sbxt_timer_stop", TimerStop); 70 | HOOK_COMMAND("sbxt_timer_reset", TimerReset); 71 | 72 | HOOK_MESSAGE(BXTTimer); 73 | 74 | return 0; 75 | } 76 | 77 | int CHudTimer::VidInit() 78 | { 79 | return 1; 80 | } 81 | 82 | int CHudTimer::Draw(float time) 83 | { 84 | if (!hud_timer->value) 85 | return 0; 86 | 87 | int x, y; 88 | gBXTHud.GetPosition(hud_timer_offset, hud_timer_anchor, &x, &y, 0, 0); 89 | 90 | int hours = g_RTATimer.GetHours(); 91 | int minutes = g_RTATimer.GetMinutes(); 92 | int seconds = g_RTATimer.GetSeconds(); 93 | int milliseconds = g_RTATimer.GetMilliseconds(); 94 | 95 | if (hud_timer->value == 1) 96 | { 97 | char rta_timer[64]; 98 | sprintf(rta_timer, "RTA | %d:%02d:%02d.%03d", hours, minutes, seconds, milliseconds); 99 | g_lpEngfuncs->VGUI2_DrawLocalizedHudString(x, y, rta_timer, SVEN_HUD_COLOR); 100 | } 101 | else if (hud_timer->value >= 2) 102 | { 103 | if (hours) 104 | { 105 | x = gBXTHud.DrawNumberTimer(hours, x, y, 1); 106 | gBXTHud.DrawColon(x, y); 107 | x += NumberWidth; 108 | } 109 | 110 | if (hours || minutes) 111 | { 112 | int fieldMinWidth = (hours && minutes < 10) ? 2 : 1; 113 | x = gBXTHud.DrawNumberTimer(minutes, x, y, fieldMinWidth); 114 | gBXTHud.DrawColon(x, y); 115 | x += NumberWidth; 116 | } 117 | 118 | int fieldMinWidth = ((hours || minutes) && seconds < 10) ? 2 : 1; 119 | x = gBXTHud.DrawNumberTimer(seconds, x, y, fieldMinWidth); 120 | 121 | gBXTHud.DrawDecimalSeparator(x, y); 122 | x += NumberWidth; 123 | 124 | gBXTHud.DrawNumberTimer(milliseconds, x, y, 3); 125 | } 126 | 127 | //sprintf_s(igt_timer, "IGT | %d:%02d:%02d.%03d", g_IGTTimer.GetHours(), g_IGTTimer.GetMinutes(), g_IGTTimer.GetSeconds(), g_IGTTimer.GetMilliseconds()); 128 | //g_lpEngfuncs->VGUI2_DrawLocalizedHudString(x, y + CharHeight, rta_timer, SVEN_HUD_COLOR); 129 | 130 | return 0; 131 | } 132 | 133 | void CHudTimer::TimerStart() 134 | { 135 | g_RTATimer.StartTimer(); 136 | //g_IGTTimer.StartTimer(); 137 | 138 | if (UTIL_IsHost()) 139 | { 140 | SV_SyncTimer(); 141 | } 142 | } 143 | 144 | void CHudTimer::TimerStop() 145 | { 146 | g_RTATimer.StopTimer(); 147 | //g_IGTTimer.StopTimer(); 148 | 149 | if (UTIL_IsHost()) 150 | { 151 | SV_SyncTimer(); 152 | } 153 | } 154 | 155 | void CHudTimer::TimerReset() 156 | { 157 | g_RTATimer.ResetTimer(); 158 | //g_IGTTimer.ResetTimer(); 159 | 160 | if (UTIL_IsHost()) 161 | { 162 | SV_SyncTimer(); 163 | } 164 | } -------------------------------------------------------------------------------- /src/cl_dll/hud_timer.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_TIMER_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_timer.h 3 | #else //HUD_TIMER_H_RECURSE_GUARD 4 | 5 | #define HUD_TIMER_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_TIMER_H_GUARD 8 | #define HUD_TIMER_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | extern CTimer g_RTATimer; 14 | extern CTimer g_IGTTimer; 15 | 16 | class CHudTimer: public CBXTHudBase 17 | { 18 | public: 19 | virtual int Init(); 20 | virtual int VidInit(); 21 | virtual int Draw(float time); 22 | 23 | void TimerStart(); 24 | void TimerStop(); 25 | void TimerReset(); 26 | 27 | bool ShouldSync() { return (hud_timer_serversync->value && !UTIL_IsHost()); } 28 | bool IsInILMode() { return hud_timer_il_mode->value; }; 29 | 30 | private: 31 | cvar_t* hud_timer_serversync; 32 | cvar_t* hud_timer_il_mode; 33 | cvar_t* hud_timer; 34 | cvar_t* hud_timer_anchor; 35 | cvar_t* hud_timer_offset; 36 | }; 37 | 38 | extern CHudTimer* g_lpHUDTimer; 39 | 40 | #else //!__cplusplus 41 | #error C++ compiler required to compile hud_timer.h 42 | #endif //__cplusplus 43 | 44 | #endif //HUD_TIMER_H_GUARD 45 | 46 | #undef HUD_TIMER_H_RECURSE_GUARD 47 | #endif //HUD_TIMER_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/hud_viewangles.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | float AngleNormalize(float angle) 4 | { 5 | angle = fmodf(angle, 360.0f); 6 | if (angle > 180) 7 | { 8 | angle -= 360; 9 | } 10 | if (angle < -180) 11 | { 12 | angle += 360; 13 | } 14 | return angle; 15 | } 16 | 17 | int CHudViewangles::Init() 18 | { 19 | m_iFlags |= HUD_ACTIVE; 20 | 21 | hud_viewangles = CVAR_CREATE("sbxt_hud_viewangles", "0", 0); 22 | hud_viewangles_anchor = CVAR_CREATE("sbxt_hud_viewangles_anchor", "1 0", 0); 23 | hud_viewangles_offset = CVAR_CREATE("sbxt_hud_viewangles_offset", "", 0); 24 | 25 | return 0; 26 | } 27 | 28 | int CHudViewangles::VidInit() 29 | { 30 | return 1; 31 | } 32 | 33 | int CHudViewangles::Draw(float time) 34 | { 35 | if (!hud_viewangles->value) 36 | return 0; 37 | 38 | int x, y; 39 | gBXTHud.GetPosition(hud_viewangles_offset, hud_viewangles_anchor, &x, &y, -200, (CharHeight * 10) + 2); 40 | 41 | float viewangle[2]; 42 | viewangle[0] = AngleNormalize(g_RefParams.viewangles[0]); 43 | viewangle[1] = AngleNormalize(g_RefParams.viewangles[1]); 44 | 45 | std::ostringstream out; 46 | out.setf(std::ios::fixed); 47 | out.precision((int)gBXTHud.hud_precision->value); 48 | 49 | out << "Angles:" 50 | << "\n" 51 | << "Pitch: " << viewangle[0] << "\n" 52 | << "Yaw: " << viewangle[1]; 53 | 54 | gBXTHud.DrawMultilineString(x, y, out.str()); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /src/cl_dll/hud_viewangles.h: -------------------------------------------------------------------------------- 1 | #ifdef HUD_VIEWANGLES_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in hud_viewangles.h 3 | #else //HUD_VIEWANGLES_H_RECURSE_GUARD 4 | 5 | #define HUD_VIEWANGLES_H_RECURSE_GUARD 6 | 7 | #ifndef HUD_VIEWANGLES_H_GUARD 8 | #define HUD_VIEWANGLES_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class CHudViewangles: public CBXTHudBase 14 | { 15 | public: 16 | virtual int Init(); 17 | virtual int VidInit(); 18 | virtual int Draw(float time); 19 | 20 | private: 21 | cvar_t* hud_viewangles; 22 | cvar_t* hud_viewangles_anchor; 23 | cvar_t* hud_viewangles_offset; 24 | }; 25 | 26 | #else //!__cplusplus 27 | #error C++ compiler required to compile hud_viewangles.h 28 | #endif //__cplusplus 29 | 30 | #endif //HUD_VIEWANGLES_H_GUARD 31 | 32 | #undef HUD_VIEWANGLES_H_RECURSE_GUARD 33 | #endif //HUD_VIEWANGLES_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/opengl_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | // From BunnymodXT 4 | 5 | GLUtils::GLUtils() { 6 | // Same steps as FillRGBA does. 7 | glDisable(GL_TEXTURE_2D); 8 | glEnable(GL_BLEND); 9 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 10 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 11 | } 12 | 13 | GLUtils::~GLUtils() { 14 | // Reset the line width in case we changed it. 15 | glLineWidth(1.0f); 16 | 17 | // Same steps as FillRGBA does. 18 | glColor3f(1.0f, 1.0f, 1.0f); 19 | glDisable(GL_BLEND); 20 | glEnable(GL_TEXTURE_2D); 21 | } 22 | 23 | void GLUtils::color(float r, float g, float b, float a) const { 24 | glColor4f(r / 255.0, g / 255.0, b / 255.0, a); 25 | } 26 | 27 | void GLUtils::color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const { 28 | glColor4ub(r, g, b, a); 29 | } 30 | 31 | void GLUtils::line_width(float width) const { 32 | glLineWidth(width); 33 | } 34 | 35 | void GLUtils::line(const Vector2D& start, const Vector2D& end) const { 36 | glBegin(GL_LINES); 37 | glVertex2f(start.x, start.y); 38 | glVertex2f(end.x, end.y); 39 | glEnd(); 40 | } 41 | 42 | void GLUtils::circle(const Vector2D& center, const std::vector& points) const { 43 | glBegin(GL_LINE_STRIP); 44 | 45 | for (const auto& point : points) 46 | glVertex2f(center.x + point.x, center.y + point.y); 47 | 48 | glVertex2f(center.x + points[0].x, center.y + points[0].y); 49 | glEnd(); 50 | } 51 | 52 | void GLUtils::rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const { 53 | glBegin(GL_QUADS); 54 | glVertex2f(corner_a.x, corner_a.y); 55 | glVertex2f(corner_a.x, corner_b.y); 56 | glVertex2f(corner_b.x, corner_b.y); 57 | glVertex2f(corner_b.x, corner_a.y); 58 | glEnd(); 59 | } 60 | 61 | std::vector GLUtils::compute_circle(float radius) { 62 | // Maximum allowed distance between the circle and the rendered line segment. 63 | constexpr float MAX_ERROR = 0.1f; 64 | const unsigned segment_count = 65 | static_cast(ceil(M_PI / acos((radius - MAX_ERROR) / radius))); 66 | 67 | std::vector points; 68 | points.reserve(segment_count); 69 | 70 | for (unsigned i = 0; i < segment_count; ++i) { 71 | float angle = static_cast(M_PI * 2 * i / segment_count); 72 | points.emplace_back(radius * cos(angle), radius * sin(angle)); 73 | } 74 | 75 | return points; 76 | } -------------------------------------------------------------------------------- /src/cl_dll/opengl_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifdef OPENGL_UTILS_HPP_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in opengl_utils.hpp 3 | #else //OPENGL_UTILS_HPP_RECURSE_GUARD 4 | 5 | #define OPENGL_UTILS_HPP_RECURSE_GUARD 6 | 7 | #ifndef OPENGL_UTILS_HPP_GUARD 8 | #define OPENGL_UTILS_HPP_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | class GLUtils 14 | { 15 | public: 16 | GLUtils(); 17 | ~GLUtils(); 18 | 19 | void color(float r, float g, float b, float a) const; 20 | void color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const; 21 | void line_width(float width) const; 22 | void line(const Vector2D& start, const Vector2D& end) const; 23 | void circle(const Vector2D& center, const std::vector& points) const; 24 | void rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const; 25 | 26 | static std::vector compute_circle(float radius); 27 | }; 28 | 29 | #else //!__cplusplus 30 | #error C++ compiler required to compile opengl_utils.hpp 31 | #endif //__cplusplus 32 | 33 | #endif //OPENGL_UTILS_HPP_GUARD 34 | 35 | #undef OPENGL_UTILS_HPP_RECURSE_GUARD 36 | #endif //OPENGL_UTILS_HPP_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/parsemsg.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | * 3 | * Copyright (c) 1999, Valve LLC. All rights reserved. 4 | * 5 | * This product contains software technology licensed from Id 6 | * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. 7 | * All Rights Reserved. 8 | * 9 | * Use, distribution, and modification of this source code and/or resulting 10 | * object code is restricted to non-commercial enhancements to products from 11 | * Valve LLC. All other use, distribution, or modification is prohibited 12 | * without written permission from Valve LLC. 13 | * 14 | ****/ 15 | // 16 | // parsemsg.cpp 17 | // 18 | //-------------------------------------------------------------------------------------------------------------- 19 | #include "SvenBXT.h" 20 | 21 | typedef unsigned char byte; 22 | #define true 1 23 | 24 | static byte* gpBuf; 25 | static int giSize; 26 | static int giRead; 27 | static int giBadRead; 28 | 29 | int READ_OK(void) 30 | { 31 | return !giBadRead; 32 | } 33 | 34 | void BEGIN_READ(void* buf, int size) 35 | { 36 | giRead = 0; 37 | giBadRead = 0; 38 | giSize = size; 39 | gpBuf = (byte*)buf; 40 | } 41 | 42 | 43 | int READ_CHAR(void) 44 | { 45 | int c; 46 | 47 | if (giRead + 1 > giSize) 48 | { 49 | giBadRead = true; 50 | return -1; 51 | } 52 | 53 | c = (signed char)gpBuf[giRead]; 54 | giRead++; 55 | 56 | return c; 57 | } 58 | 59 | int READ_BYTE(void) 60 | { 61 | int c; 62 | 63 | if (giRead + 1 > giSize) 64 | { 65 | giBadRead = true; 66 | return -1; 67 | } 68 | 69 | c = (unsigned char)gpBuf[giRead]; 70 | giRead++; 71 | 72 | return c; 73 | } 74 | 75 | int READ_SHORT(void) 76 | { 77 | int c; 78 | 79 | if (giRead + 2 > giSize) 80 | { 81 | giBadRead = true; 82 | return -1; 83 | } 84 | 85 | c = (short)(gpBuf[giRead] + (gpBuf[giRead + 1] << 8)); 86 | 87 | giRead += 2; 88 | 89 | return c; 90 | } 91 | 92 | int READ_WORD(void) 93 | { 94 | return READ_SHORT(); 95 | } 96 | 97 | 98 | int READ_LONG(void) 99 | { 100 | int c; 101 | 102 | if (giRead + 4 > giSize) 103 | { 104 | giBadRead = true; 105 | return -1; 106 | } 107 | 108 | c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24); 109 | 110 | giRead += 4; 111 | 112 | return c; 113 | } 114 | 115 | float READ_FLOAT(void) 116 | { 117 | union 118 | { 119 | byte b[4]; 120 | float f; 121 | int l; 122 | } dat; 123 | 124 | dat.b[0] = gpBuf[giRead]; 125 | dat.b[1] = gpBuf[giRead + 1]; 126 | dat.b[2] = gpBuf[giRead + 2]; 127 | dat.b[3] = gpBuf[giRead + 3]; 128 | giRead += 4; 129 | 130 | // dat.l = LittleLong (dat.l); 131 | 132 | return dat.f; 133 | } 134 | 135 | char* READ_STRING(void) 136 | { 137 | static char string[2048]; 138 | int l, c; 139 | 140 | string[0] = 0; 141 | 142 | l = 0; 143 | do 144 | { 145 | if (giRead + 1 > giSize) 146 | break; // no more characters 147 | 148 | c = READ_CHAR(); 149 | if (c == -1 || c == 0) 150 | break; 151 | string[l] = c; 152 | l++; 153 | } while (l < sizeof(string) - 1); 154 | 155 | string[l] = 0; 156 | 157 | return string; 158 | } 159 | 160 | float READ_COORD(void) 161 | { 162 | return (float)(READ_SHORT() * (1.0 / 8)); 163 | } 164 | 165 | float READ_ANGLE(void) 166 | { 167 | return (float)(READ_CHAR() * (360.0 / 256)); 168 | } 169 | 170 | float READ_HIRESANGLE(void) 171 | { 172 | return (float)(READ_SHORT() * (360.0 / 65536)); 173 | } 174 | 175 | //-------------------------------------------------------------------------------------------------------------- 176 | BufferWriter::BufferWriter() 177 | { 178 | Init(NULL, 0); 179 | } 180 | 181 | //-------------------------------------------------------------------------------------------------------------- 182 | BufferWriter::BufferWriter(unsigned char* buffer, int bufferLen) 183 | { 184 | Init(buffer, bufferLen); 185 | } 186 | 187 | //-------------------------------------------------------------------------------------------------------------- 188 | void BufferWriter::Init(unsigned char* buffer, int bufferLen) 189 | { 190 | m_overflow = false; 191 | m_buffer = buffer; 192 | m_remaining = bufferLen; 193 | m_overallLength = bufferLen; 194 | } 195 | 196 | //-------------------------------------------------------------------------------------------------------------- 197 | void BufferWriter::WriteByte(unsigned char data) 198 | { 199 | if (!m_buffer || !m_remaining) 200 | { 201 | m_overflow = true; 202 | return; 203 | } 204 | 205 | *m_buffer = data; 206 | ++m_buffer; 207 | --m_remaining; 208 | } 209 | 210 | //-------------------------------------------------------------------------------------------------------------- 211 | void BufferWriter::WriteLong(int data) 212 | { 213 | if (!m_buffer || m_remaining < 4) 214 | { 215 | m_overflow = true; 216 | return; 217 | } 218 | 219 | m_buffer[0] = data & 0xff; 220 | m_buffer[1] = (data >> 8) & 0xff; 221 | m_buffer[2] = (data >> 16) & 0xff; 222 | m_buffer[3] = data >> 24; 223 | m_buffer += 4; 224 | m_remaining -= 4; 225 | } 226 | 227 | //-------------------------------------------------------------------------------------------------------------- 228 | void BufferWriter::WriteString(const char* str) 229 | { 230 | if (!m_buffer || !m_remaining) 231 | { 232 | m_overflow = true; 233 | return; 234 | } 235 | 236 | if (!str) 237 | str = ""; 238 | 239 | int len = strlen(str) + 1; 240 | if (len > m_remaining) 241 | { 242 | m_overflow = true; 243 | str = ""; 244 | len = 1; 245 | } 246 | 247 | strcpy((char*)m_buffer, str); 248 | m_remaining -= len; 249 | m_buffer += len; 250 | } 251 | 252 | //-------------------------------------------------------------------------------------------------------------- 253 | int BufferWriter::GetSpaceUsed() 254 | { 255 | return m_overallLength - m_remaining; 256 | } 257 | 258 | //-------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /src/cl_dll/parsemsg.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * 3 | * Copyright (c) 1999, Valve LLC. All rights reserved. 4 | * 5 | * This product contains software technology licensed from Id 6 | * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. 7 | * All Rights Reserved. 8 | * 9 | * Use, distribution, and modification of this source code and/or resulting 10 | * object code is restricted to non-commercial enhancements to products from 11 | * Valve LLC. All other use, distribution, or modification is prohibited 12 | * without written permission from Valve LLC. 13 | * 14 | ****/ 15 | // 16 | // parsemsg.h 17 | // MDC - copying from cstrike\cl_dll so career-mode stuff can catch messages 18 | // in this dll. (and C++ifying it) 19 | // 20 | 21 | #ifndef PARSEMSG_H 22 | #define PARSEMSG_H 23 | 24 | #define ASSERT( x ) 25 | //-------------------------------------------------------------------------------------------------------------- 26 | void BEGIN_READ(void* buf, int size); 27 | int READ_CHAR(void); 28 | int READ_BYTE(void); 29 | int READ_SHORT(void); 30 | int READ_WORD(void); 31 | int READ_LONG(void); 32 | float READ_FLOAT(void); 33 | char* READ_STRING(void); 34 | float READ_COORD(void); 35 | float READ_ANGLE(void); 36 | float READ_HIRESANGLE(void); 37 | int READ_OK(void); 38 | 39 | //-------------------------------------------------------------------------------------------------------------- 40 | class BufferWriter 41 | { 42 | public: 43 | BufferWriter(); 44 | BufferWriter(unsigned char* buffer, int bufferLen); 45 | void Init(unsigned char* buffer, int bufferLen); 46 | 47 | void WriteByte(unsigned char data); 48 | void WriteLong(int data); 49 | void WriteString(const char* str); 50 | 51 | bool HasOverflowed(); 52 | int GetSpaceUsed(); 53 | 54 | protected: 55 | unsigned char* m_buffer; 56 | int m_remaining; 57 | bool m_overflow; 58 | int m_overallLength; 59 | }; 60 | 61 | //-------------------------------------------------------------------------------------------------------------- 62 | 63 | #endif // PARSEMSG_H -------------------------------------------------------------------------------- /src/cl_dll/tri.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | void HOOKED_HUD_DrawTransparentTriangles(void) 4 | { 5 | ORIG_HUD_DrawTransparentTriangles(); 6 | } -------------------------------------------------------------------------------- /src/cl_dll/tri.h: -------------------------------------------------------------------------------- 1 | #ifdef TRI_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in tri.h 3 | #else //TRI_H_RECURSE_GUARD 4 | 5 | #define TRI_H_RECURSE_GUARD 6 | 7 | #ifndef TRI_H_GUARD 8 | #define TRI_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | void HOOKED_HUD_DrawTransparentTriangles(void); 14 | 15 | #else //!__cplusplus 16 | #error C++ compiler required to compile tri.h 17 | #endif //__cplusplus 18 | 19 | #endif //TRI_H_GUARD 20 | 21 | #undef TRI_H_RECURSE_GUARD 22 | #endif //TRI_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/cl_dll/view.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | ref_params_s g_RefParams; 4 | 5 | void HOOKED_V_CalcRefdef(struct ref_params_s* pparams) 6 | { 7 | g_RefParams = *pparams; 8 | ORIG_V_CalcRefdef(pparams); 9 | 10 | g_lpJumpspeedHUD->UpdateSpeed(g_RefParams.simvel); 11 | } 12 | -------------------------------------------------------------------------------- /src/cl_dll/view.h: -------------------------------------------------------------------------------- 1 | #ifdef VIEW_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in view.h 3 | #else // VIEW_H_RECURSE_GUARD 4 | 5 | #define VIEW_H_RECURSE_GUARD 6 | 7 | #ifndef VIEW_H_GUARD 8 | #define VIEW_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | extern ref_params_s g_RefParams; 14 | void HOOKED_V_CalcRefdef(struct ref_params_s* pparams); 15 | 16 | #else //!__cplusplus 17 | #error C++ compiler required to compile view.h 18 | #endif //__cplusplus 19 | 20 | #endif // VIEW_H_GUARD 21 | 22 | #undef VIEW_H_RECURSE_GUARD 23 | #endif // VIEW_H_RECURSE_GUARD 24 | -------------------------------------------------------------------------------- /src/cmake/InputFilesList.cmake: -------------------------------------------------------------------------------- 1 | if( INPUTFILESLIST_INCLUDED ) 2 | return() 3 | endif() 4 | set( INPUTFILESLIST_INCLUDED true ) 5 | 6 | # 7 | # This file defines functions to build a list of source and include files to be used to create libraries and executables, and install files, respectively. 8 | # 9 | # Call add_sources with one or more source/header files to add them to the list of files. 10 | # Call preprocess_sources to generate a list of files to include in a library or executable. 11 | # Use the PREP_SRCS variable to include the list. 12 | # Call create_source_groups with the root directory for the files in the list after defining the library or executable to generate filters for Visual Studio that match the directory structure. 13 | # Call add_includes to add files to the list of files to install. 14 | # Call install_includes with the root directory for the files in the list after defining the library or executable to install the included files. 15 | # Call clear_sources to clear the sources list and prepare it for the next library or executable. 16 | # 17 | 18 | #! Gets the list of source files 19 | # \arg:dest_var Name of the variable that will contain the list 20 | function( get_sources dest_var ) 21 | get_property( is_defined GLOBAL PROPERTY SRCS_LIST DEFINED ) 22 | 23 | if( is_defined ) 24 | get_property( srcs GLOBAL PROPERTY SRCS_LIST ) 25 | set( ${dest_var} ${srcs} PARENT_SCOPE ) 26 | else() 27 | set( ${dest_var} PARENT_SCOPE ) 28 | endif() 29 | endfunction( get_sources ) 30 | 31 | #! Function to collect all the sources from sub-directories into a single list 32 | # Pass the file paths of source files relative to the CMakeLists that is calling this function 33 | function( add_sources ) 34 | get_property( is_defined GLOBAL PROPERTY SRCS_LIST DEFINED ) 35 | 36 | if( NOT is_defined ) 37 | define_property( GLOBAL PROPERTY SRCS_LIST 38 | BRIEF_DOCS "List of source files" 39 | FULL_DOCS "List of source files to be compiled in one library" 40 | ) 41 | endif() 42 | 43 | # make absolute paths 44 | set( SRCS ) 45 | foreach( s IN LISTS ARGN ) 46 | if( NOT IS_ABSOLUTE "${s}" ) 47 | get_filename_component( s "${s}" ABSOLUTE ) 48 | endif() 49 | list( APPEND SRCS "${s}" ) 50 | endforeach() 51 | 52 | # append to global list 53 | set_property( GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}" ) 54 | endfunction( add_sources ) 55 | 56 | #! Preprocess source files 57 | function( preprocess_sources ) 58 | set( PREP_SRCS PARENT_SCOPE ) 59 | get_property( SRCS GLOBAL PROPERTY SRCS_LIST ) 60 | 61 | foreach( s IN LISTS SRCS ) 62 | file( RELATIVE_PATH rs "${CMAKE_CURRENT_SOURCE_DIR}" "${s}" ) 63 | string( REGEX REPLACE "r$" "" o "${CMAKE_CURRENT_BINARY_DIR}/${rs}" ) 64 | add_custom_command( 65 | OUTPUT "${o}" 66 | COMMAND ${CMAKE_COMMAND} -E copy "${s}" "${o}" 67 | DEPENDS "${s}" 68 | COMMENT "Creating ${o}" 69 | VERBATIM 70 | ) 71 | list( APPEND PREP_SRCS "${s}" ) 72 | endforeach() 73 | 74 | set( PREP_SRCS ${PREP_SRCS} PARENT_SCOPE ) 75 | endfunction( preprocess_sources ) 76 | 77 | #! Create the source groups for source files 78 | # \arg:_src_root_path Root directory for the list of source files 79 | function( create_source_groups _src_root_path ) 80 | get_property( SRCS GLOBAL PROPERTY SRCS_LIST ) 81 | 82 | foreach( _source IN ITEMS ${SRCS} ) 83 | get_filename_component( _source_path "${_source}" PATH ) 84 | file( RELATIVE_PATH _source_path_rel "${_src_root_path}" "${_source_path}" ) 85 | string( REPLACE "/" "\\" _group_path "${_source_path_rel}" ) 86 | source_group( "${_group_path}" FILES "${_source}" ) 87 | endforeach() 88 | endfunction( create_source_groups ) 89 | 90 | #! Function to clear the sources list 91 | # Call once sources have been added to a target and source groups have been created 92 | function( clear_sources ) 93 | set_property( GLOBAL PROPERTY SRCS_LIST "" ) 94 | set( PREP_SRCS PARENT_SCOPE ) 95 | endfunction( clear_sources ) 96 | 97 | #! Function to add include files to a single list 98 | function( add_includes ) 99 | get_property( is_defined GLOBAL PROPERTY INCLUDES_LIST DEFINED ) 100 | if( NOT is_defined ) 101 | define_property( GLOBAL PROPERTY INCLUDES_LIST 102 | BRIEF_DOCS "List of include files" 103 | FULL_DOCS "List of include files to be compiled in one library" 104 | ) 105 | endif() 106 | 107 | # make absolute paths 108 | set( INCLUDES ) 109 | foreach( s IN LISTS ARGN ) 110 | if( NOT IS_ABSOLUTE "${s}" ) 111 | get_filename_component( s "${s}" ABSOLUTE ) 112 | endif() 113 | list( APPEND INCLUDES "${s}" ) 114 | endforeach() 115 | 116 | # append to global list 117 | set_property( GLOBAL APPEND PROPERTY INCLUDES_LIST "${INCLUDES}" ) 118 | endfunction( add_includes ) 119 | 120 | #! Function to install includes 121 | # \arg:_include_root_path Root directory for the list of include files 122 | function( install_includes _include_root_path ) 123 | get_property( INCLUDES GLOBAL PROPERTY INCLUDES_LIST ) 124 | 125 | foreach( _include IN ITEMS ${INCLUDES} ) 126 | get_filename_component( _include_path "${_include}" PATH ) 127 | file( RELATIVE_PATH _include_path_rel "${_include_root_path}" "${_include_path}" ) 128 | string( REPLACE "/" "\\" _group_path "${_include_path_rel}" ) 129 | install( FILES "${_include}" DESTINATION "include/${_group_path}" ) 130 | endforeach() 131 | 132 | set_property( GLOBAL PROPERTY INCLUDES_LIST "" ) 133 | endfunction( install_includes ) -------------------------------------------------------------------------------- /src/cmake/Linux32CrossCompile.cmake: -------------------------------------------------------------------------------- 1 | # Based on pcsx2/cmake/linux-compiler-i386-multilib.cmake 2 | # https://github.com/PCSX2/pcsx2 3 | 4 | # Tell cmake we are cross compiling and targeting linux 5 | set(CMAKE_SYSTEM_NAME Linux) 6 | set(CMAKE_SYSTEM_PROCESSOR i686) 7 | 8 | # cmake 2.8.5 correctly sets CMAKE_LIBRARY_ARCHITECTURE for Debian multiarch. 9 | # Be really strict about what gets used. 10 | if(EXISTS /usr/lib/i386-linux-gnu) 11 | set(CMAKE_SYSTEM_IGNORE_PATH 12 | /lib /lib64 /lib32 13 | /usr/lib /usr/lib64 /usr/lib32 14 | /usr/local/lib /usr/local/lib64 /usr/local/lib32) 15 | list(APPEND CMAKE_LIBRARY_PATH /usr/local/lib/i386-linux-gnu) 16 | list(APPEND CMAKE_LIBRARY_PATH /usr/lib/i386-linux-gnu) 17 | list(APPEND CMAKE_LIBRARY_PATH /lib/i386-linux-gnu) 18 | elseif(EXISTS /usr/lib32) 19 | set(CMAKE_SYSTEM_IGNORE_PATH 20 | /lib /lib64 21 | /usr/lib /usr/lib64 22 | /usr/local/lib /usr/local/lib64) 23 | set(CMAKE_LIBRARY_ARCHITECTURE "../lib32") 24 | list(APPEND CMAKE_LIBRARY_PATH /usr/local/lib32) 25 | list(APPEND CMAKE_LIBRARY_PATH /usr/lib32) 26 | list(APPEND CMAKE_LIBRARY_PATH /lib32) 27 | else() 28 | set(CMAKE_SYSTEM_IGNORE_PATH 29 | /lib64 30 | /usr/lib64 31 | /usr/local/lib64) 32 | set(CMAKE_LIBRARY_ARCHITECTURE ".") 33 | list(APPEND CMAKE_LIBRARY_PATH /usr/local/lib) 34 | list(APPEND CMAKE_LIBRARY_PATH /usr/lib) 35 | list(APPEND CMAKE_LIBRARY_PATH /lib) 36 | endif() 37 | list(REMOVE_DUPLICATES CMAKE_LIBRARY_PATH) 38 | 39 | # If given a CMAKE_FIND_ROOT_PATH then 40 | # FIND_PROGRAM ignores CMAKE_FIND_ROOT_PATH (probably can't run) 41 | # FIND_{LIBRARY,INCLUDE,PACKAGE} only uses the files in CMAKE_FIND_ROOT_PATH. 42 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 43 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 44 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 45 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 46 | -------------------------------------------------------------------------------- /src/cmake/PlatformInfo.cmake: -------------------------------------------------------------------------------- 1 | # This file sets following variables to TRUE when building for... 2 | # 3 | # PLATFORM_WINDOWS Windows 4 | # PLATFORM_UNIX any Unix-like OS 5 | # PLATFORM_LINUX any OS with Linux kernel 6 | # PLATFORM_ANDROID Android specifically 7 | # PLATFORM_MACOS macOS 8 | # 9 | # 10 | # 11 | # This file sets following variables to TRUE when building with... 12 | # 13 | # COMPILER_MSVC MS Visual Studio 14 | # COMPILER_GNU any GCC-compatible compiler 15 | # COMPILER_GCC GCC 16 | # COMPILER_CLANG LLVM/Clang 17 | # 18 | 19 | set( PLATFORM_WINDOWS FALSE ) 20 | set( PLATFORM_UNIX FALSE ) 21 | set( PLATFORM_LINUX FALSE ) 22 | set( PLATFORM_ANDROID FALSE ) 23 | set( PLATFORM_MACOS FALSE ) 24 | 25 | set( COMPILER_MSVC FALSE ) 26 | set( COMPILER_GNU FALSE ) 27 | set( COMPILER_GCC FALSE ) 28 | set( COMPILER_CLANG FALSE ) 29 | 30 | set( PLATFORM_DEFINES "" ) 31 | 32 | #----------------------------------------------------------------------- 33 | # Platform identification 34 | #----------------------------------------------------------------------- 35 | if( WIN32 ) 36 | 37 | # Windows 38 | set( PLATFORM_WINDOWS TRUE ) 39 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} PLATFORM_WINDOWS ) 40 | 41 | elseif( UNIX ) 42 | set( PLATFORM_UNIX TRUE ) 43 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} PLATFORM_UNIX ) 44 | 45 | if( APPLE ) 46 | # macOS 47 | set( PLATFORM_MACOS TRUE ) 48 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} PLATFORM_MACOS ) 49 | else() 50 | # Linux kernel (most likely) 51 | set( PLATFORM_LINUX TRUE ) 52 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} PLATFORM_LINUX ) 53 | 54 | if( ANDROID ) 55 | set( PLATFORM_ANDROID TRUE ) 56 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} PLATFORM_ANDROID ) 57 | endif() 58 | endif() 59 | 60 | else() 61 | message( FATAL_ERROR "Platform identification failed. Please add your platform to cmake/PlatformInfo.cmake" ) 62 | endif() 63 | 64 | #----------------------------------------------------------------------- 65 | # Compiler identification 66 | #----------------------------------------------------------------------- 67 | if( CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU" ) 68 | 69 | # GNU 70 | set( COMPILER_GNU TRUE ) 71 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} COMPILER_GNU ) 72 | 73 | if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" ) 74 | # GCC 75 | set( COMPILER_GCC TRUE ) 76 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} COMPILER_GCC ) 77 | elseif( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) 78 | # Clang 79 | set( COMPILER_CLANG TRUE ) 80 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} COMPILER_CLANG ) 81 | else() 82 | message( FATAL_ERROR "This isn't supposed to happen." ) 83 | endif() 84 | 85 | elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" ) 86 | # MSVC 87 | set( COMPILER_MSVC TRUE ) 88 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} COMPILER_MSVC ) 89 | else() 90 | message( WARNING "Unknown compiler deteceted: ${CMAKE_CXX_COMPILER_ID}. Defaulting to GNU-compatible." ) 91 | set( COMPILER_GNU TRUE ) 92 | set( PLATFORM_DEFINES ${PLATFORM_DEFINES} COMPILER_GNU ) 93 | endif() -------------------------------------------------------------------------------- /src/cmake/ToolchainLinuxGCC.cmake: -------------------------------------------------------------------------------- 1 | include(Linux32CrossCompile) 2 | set(CMAKE_C_COMPILER gcc -m32) 3 | set(CMAKE_CXX_COMPILER g++ -m32) 4 | set(CMAKE_ASM_FLAGS "${ASMFLAGS} -m32") # thanks to tmp64 -------------------------------------------------------------------------------- /src/dlls/enginecallback.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * 3 | * Copyright (c) 1996-2001, Valve LLC. All rights reserved. 4 | * 5 | * This product contains software technology licensed from Id 6 | * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. 7 | * All Rights Reserved. 8 | * 9 | * Use, distribution, and modification of this source code and/or resulting 10 | * object code is restricted to non-commercial enhancements to products from 11 | * Valve LLC. All other use, distribution, or modification is prohibited 12 | * without written permission from Valve LLC. 13 | * 14 | ****/ 15 | #ifndef ENGINECALLBACK_H 16 | #define ENGINECALLBACK_H 17 | #pragma once 18 | 19 | // The actual engine callbacks 20 | #define GETPLAYERUSERID (*g_engfuncs->pfnGetPlayerUserId) 21 | #define PRECACHE_MODEL (*g_engfuncs->pfnPrecacheModel) 22 | #define PRECACHE_SOUND (*g_engfuncs->pfnPrecacheSound) 23 | #define PRECACHE_GENERIC (*g_engfuncs->pfnPrecacheGeneric) 24 | #define SET_MODEL (*g_engfuncs->pfnSetModel) 25 | #define MODEL_INDEX (*g_engfuncs->pfnModelIndex) 26 | #define MODEL_FRAMES (*g_engfuncs->pfnModelFrames) 27 | #define SET_SIZE (*g_engfuncs->pfnSetSize) 28 | #define CHANGE_LEVEL (*g_engfuncs->pfnChangeLevel) 29 | #define GET_SPAWN_PARMS (*g_engfuncs->pfnGetSpawnParms) 30 | #define SAVE_SPAWN_PARMS (*g_engfuncs->pfnSaveSpawnParms) 31 | #define VEC_TO_YAW (*g_engfuncs->pfnVecToYaw) 32 | #define VEC_TO_ANGLES (*g_engfuncs->pfnVecToAngles) 33 | #define MOVE_TO_ORIGIN (*g_engfuncs->pfnMoveToOrigin) 34 | #define oldCHANGE_YAW (*g_engfuncs->pfnChangeYaw) 35 | #define CHANGE_PITCH (*g_engfuncs->pfnChangePitch) 36 | #define MAKE_VECTORS (*g_engfuncs->pfnMakeVectors) 37 | #define CREATE_ENTITY (*g_engfuncs->pfnCreateEntity) 38 | #define REMOVE_ENTITY (*g_engfuncs->pfnRemoveEntity) 39 | #define CREATE_NAMED_ENTITY (*g_engfuncs->pfnCreateNamedEntity) 40 | #define MAKE_STATIC (*g_engfuncs->pfnMakeStatic) 41 | #define ENT_IS_ON_FLOOR (*g_engfuncs->pfnEntIsOnFloor) 42 | #define DROP_TO_FLOOR (*g_engfuncs->pfnDropToFloor) 43 | #define WALK_MOVE (*g_engfuncs->pfnWalkMove) 44 | #define SET_ORIGIN (*g_engfuncs->pfnSetOrigin) 45 | #define EMIT_SOUND_DYN2 (*g_engfuncs->pfnEmitSound) 46 | #define BUILD_SOUND_MSG (*g_engfuncs->pfnBuildSoundMsg) 47 | #define TRACE_LINE (*g_engfuncs->pfnTraceLine) 48 | #define TRACE_TOSS (*g_engfuncs->pfnTraceToss) 49 | #define TRACE_MONSTER_HULL (*g_engfuncs->pfnTraceMonsterHull) 50 | #define TRACE_HULL (*g_engfuncs->pfnTraceHull) 51 | #define GET_AIM_VECTOR (*g_engfuncs->pfnGetAimVector) 52 | #define SERVER_COMMAND (*g_engfuncs->pfnServerCommand) 53 | #define CLIENT_COMMAND (*g_engfuncs->pfnClientCommand) 54 | #define PARTICLE_EFFECT (*g_engfuncs->pfnParticleEffect) 55 | #define LIGHT_STYLE (*g_engfuncs->pfnLightStyle) 56 | #define DECAL_INDEX (*g_engfuncs->pfnDecalIndex) 57 | #define POINT_CONTENTS (*g_engfuncs->pfnPointContents) 58 | #define CRC32_INIT (*g_engfuncs->pfnCRC32_Init) 59 | #define CRC32_PROCESS_BUFFER (*g_engfuncs->pfnCRC32_ProcessBuffer) 60 | #define CRC32_PROCESS_BYTE (*g_engfuncs->pfnCRC32_ProcessByte) 61 | #define CRC32_FINAL (*g_engfuncs->pfnCRC32_Final) 62 | #define RANDOM_LONG (*g_engfuncs->pfnRandomLong) 63 | #define RANDOM_FLOAT (*g_engfuncs->pfnRandomFloat) 64 | #define GETPLAYERAUTHID (*g_engfuncs->pfnGetPlayerAuthId) 65 | 66 | inline void MESSAGE_BEGIN(int msg_dest, int msg_type, const float* pOrigin = NULL, edict_t* ed = NULL) { 67 | (*g_engfuncs->pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed); 68 | } 69 | #define MESSAGE_END (*g_engfuncs->pfnMessageEnd) 70 | #define WRITE_BYTE (*g_engfuncs->pfnWriteByte) 71 | #define WRITE_CHAR (*g_engfuncs->pfnWriteChar) 72 | #define WRITE_SHORT (*g_engfuncs->pfnWriteShort) 73 | #define WRITE_LONG (*g_engfuncs->pfnWriteLong) 74 | #define WRITE_ANGLE (*g_engfuncs->pfnWriteAngle) 75 | #define WRITE_COORD (*g_engfuncs->pfnWriteCoord) 76 | #define WRITE_STRING (*g_engfuncs->pfnWriteString) 77 | #define WRITE_ENTITY (*g_engfuncs->pfnWriteEntity) 78 | #define CVAR_REGISTER (*g_engfuncs->pfnCVarRegister) 79 | #define CVAR_GET_FLOAT (*g_engfuncs->pfnCVarGetFloat) 80 | #define CVAR_GET_STRING (*g_engfuncs->pfnCVarGetString) 81 | #define CVAR_SET_FLOAT (*g_engfuncs->pfnCVarSetFloat) 82 | #define CVAR_SET_STRING (*g_engfuncs->pfnCVarSetString) 83 | #define CVAR_GET_POINTER (*g_engfuncs->pfnCVarGetPointer) 84 | #define ALERT (*g_engfuncs->pfnAlertMessage) 85 | #define ENGINE_FPRINTF (*g_engfuncs->pfnEngineFprintf) 86 | #define ALLOC_PRIVATE (*g_engfuncs->pfnPvAllocEntPrivateData) 87 | inline void* GET_PRIVATE(edict_t* pent) 88 | { 89 | if (pent) 90 | return pent->pvPrivateData; 91 | return NULL; 92 | } 93 | 94 | #define FREE_PRIVATE (*g_engfuncs->pfnFreeEntPrivateData) 95 | //#define STRING (*g_engfuncs->pfnSzFromIndex) 96 | #define ALLOC_STRING (*g_engfuncs->pfnAllocString) 97 | #define FIND_ENTITY_BY_STRING (*g_engfuncs->pfnFindEntityByString) 98 | #define GETENTITYILLUM (*g_engfuncs->pfnGetEntityIllum) 99 | #define FIND_ENTITY_IN_SPHERE (*g_engfuncs->pfnFindEntityInSphere) 100 | #define FIND_CLIENT_IN_PVS (*g_engfuncs->pfnFindClientInPVS) 101 | #define EMIT_AMBIENT_SOUND (*g_engfuncs->pfnEmitAmbientSound) 102 | #define GET_MODEL_PTR (*g_engfuncs->pfnGetModelPtr) 103 | #define REG_USER_MSG (*g_engfuncs->pfnRegUserMsg) 104 | #define GET_BONE_POSITION (*g_engfuncs->pfnGetBonePosition) 105 | #define FUNCTION_FROM_NAME (*g_engfuncs->pfnFunctionFromName) 106 | #define NAME_FOR_FUNCTION (*g_engfuncs->pfnNameForFunction) 107 | #define TRACE_TEXTURE (*g_engfuncs->pfnTraceTexture) 108 | #define CLIENT_PRINTF (*g_engfuncs->pfnClientPrintf) 109 | #define CMD_ARGS (*g_engfuncs->pfnCmd_Args) 110 | #define CMD_ARGC (*g_engfuncs->pfnCmd_Argc) 111 | #define CMD_ARGV (*g_engfuncs->pfnCmd_Argv) 112 | #define GET_ATTACHMENT (*g_engfuncs->pfnGetAttachment) 113 | #define SET_VIEW (*g_engfuncs->pfnSetView) 114 | #define SET_CROSSHAIRANGLE (*g_engfuncs->pfnCrosshairAngle) 115 | #define LOAD_FILE_FOR_ME (*g_engfuncs->pfnLoadFileForMe) 116 | #define FREE_FILE (*g_engfuncs->pfnFreeFile) 117 | #define COMPARE_FILE_TIME (*g_engfuncs->pfnCompareFileTime) 118 | #define GET_GAME_DIR (*g_engfuncs->pfnGetGameDir) 119 | #define IS_MAP_VALID (*g_engfuncs->pfnIsMapValid) 120 | #define NUMBER_OF_ENTITIES (*g_engfuncs->pfnNumberOfEntities) 121 | #define IS_DEDICATED_SERVER (*g_engfuncs->pfnIsDedicatedServer) 122 | 123 | #define PRECACHE_EVENT (*g_engfuncs->pfnPrecacheEvent) 124 | #define PLAYBACK_EVENT_FULL (*g_engfuncs->pfnPlaybackEvent) 125 | 126 | #define ENGINE_SET_PVS (*g_engfuncs->pfnSetFatPVS) 127 | #define ENGINE_SET_PAS (*g_engfuncs->pfnSetFatPAS) 128 | 129 | #define ENGINE_CHECK_VISIBILITY (*g_engfuncs->pfnCheckVisibility) 130 | 131 | #define DELTA_SET ( *g_engfuncs->pfnDeltaSetField ) 132 | #define DELTA_UNSET ( *g_engfuncs->pfnDeltaUnsetField ) 133 | #define DELTA_ADDENCODER ( *g_engfuncs->pfnDeltaAddEncoder ) 134 | #define ENGINE_CURRENT_PLAYER ( *g_engfuncs->pfnGetCurrentPlayer ) 135 | 136 | #define ENGINE_CANSKIP ( *g_engfuncs->pfnCanSkipPlayer ) 137 | 138 | #define DELTA_FINDFIELD ( *g_engfuncs->pfnDeltaFindField ) 139 | #define DELTA_SETBYINDEX ( *g_engfuncs->pfnDeltaSetFieldByIndex ) 140 | #define DELTA_UNSETBYINDEX ( *g_engfuncs->pfnDeltaUnsetFieldByIndex ) 141 | 142 | #define ENGINE_GETPHYSINFO ( *g_engfuncs->pfnGetPhysicsInfoString ) 143 | 144 | #define ENGINE_SETGROUPMASK ( *g_engfuncs->pfnSetGroupMask ) 145 | 146 | #define ENGINE_INSTANCE_BASELINE ( *g_engfuncs->pfnCreateInstancedBaseline ) 147 | 148 | #define ENGINE_FORCE_UNMODIFIED ( *g_engfuncs->pfnForceUnmodified ) 149 | 150 | #define PLAYER_CNX_STATS ( *g_engfuncs->pfnGetPlayerStats ) 151 | 152 | #endif //ENGINECALLBACK_H -------------------------------------------------------------------------------- /src/dlls/server.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | typedef void (FASTCALL* _CNihilanth_DyingThink)(void* thisptr); 4 | 5 | _CNihilanth_DyingThink ORIG_CNihilanth_DyingThink = NULL; 6 | _LoadThisDll ORIG_LoadThisDll = NULL; 7 | 8 | int gmsgBXTTimer = 0; 9 | 10 | void FASTCALL HOOKED_CNihilanth_DyingThink(void* thisptr) 11 | { 12 | g_lpHUDTimer->TimerStop(); 13 | 14 | ORIG_CNihilanth_DyingThink(thisptr); 15 | } 16 | 17 | void HOOKED_LoadThisDll(char* szDllFilename) 18 | { 19 | ORIG_LoadThisDll(szDllFilename); 20 | 21 | g_lpServer = Sys_GetModuleHandle(szDllFilename); 22 | 23 | if (!g_lpServer) 24 | { 25 | Sys_Printf("[Server] Failed to get module handle. Path: \"%s\"\n", szDllFilename); 26 | return; 27 | } 28 | 29 | SV_HookStuff(); 30 | SV_Initialize(); // may break some things but seems ok 31 | } 32 | 33 | void SV_SyncTimer() 34 | { 35 | if (gmsgBXTTimer <= 0) 36 | { 37 | Sys_Printf("[Server] Tried to send BXTTimer message but it's not valid!\n"); 38 | return; 39 | } 40 | 41 | MESSAGE_BEGIN(MSG_ALL, gmsgBXTTimer); 42 | WRITE_LONG(g_RTATimer.GetTime()); 43 | WRITE_BYTE(g_RTATimer.IsStopped()); 44 | MESSAGE_END(); 45 | } 46 | 47 | void SV_Initialize() 48 | { 49 | if (!g_engfuncs) 50 | return; 51 | 52 | gmsgBXTTimer = REG_USER_MSG("BXTTimer", -1); 53 | g_engfuncs->pfnAddServerCommand("sbxt_sv_synctimer", SV_SyncTimer); 54 | } 55 | 56 | void SV_HookStuff() 57 | { 58 | g_lpFuncHook_Server = funchook_create(); 59 | 60 | int status; 61 | 62 | #ifdef PLATFORM_LINUX 63 | GET_VARIABLE(Server, ORIG_CNihilanth_DyingThink, _ZN10CNihilanth10DyingThinkEv); 64 | #else // PLATFORM_WINDOWS 65 | static void* handle; 66 | static void* base; 67 | static size_t size; 68 | 69 | if (!MemUtils::GetModuleInfo(L"svencoop\\dlls\\server.dll", &handle, &base, &size)) // TODO: use szDllFilename 70 | { 71 | Sys_Printf("[Server] Failed to get module info from server.\n"); 72 | return; 73 | } 74 | 75 | sv_utils = Utils::Utils(handle, base, size); 76 | 77 | SPTServerFind(CNihilanth_DyingThink); 78 | #endif 79 | 80 | CreateHook(Server, CNihilanth_DyingThink); 81 | funchook_install(g_lpFuncHook_Server, 0); 82 | } -------------------------------------------------------------------------------- /src/dlls/server.h: -------------------------------------------------------------------------------- 1 | #ifdef SERVER_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in server.h 3 | #else //SERVER_H_RECURSE_GUARD 4 | 5 | #define SERVER_H_RECURSE_GUARD 6 | 7 | #ifndef SERVER_H_GUARD 8 | #define SERVER_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | typedef void (*_LoadThisDll)(char* szDllFilename); 14 | extern _LoadThisDll ORIG_LoadThisDll; 15 | 16 | extern int gmsgBXTTimer; 17 | 18 | void HOOKED_LoadThisDll(char* szDllFilename); 19 | 20 | void SV_SyncTimer(); 21 | void SV_Initialize(); 22 | void SV_HookStuff(); 23 | 24 | #else //!__cplusplus 25 | #error C++ compiler required to compile server.h 26 | #endif //__cplusplus 27 | 28 | #endif //SERVER_H_GUARD 29 | 30 | #undef SERVER_H_RECURSE_GUARD 31 | #endif //SERVER_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/engine/gl_screen.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | _SCR_BeginLoadingPlaque ORIG_SCR_BeginLoadingPlaque = NULL; 4 | _SCR_EndLoadingPlaque ORIG_SCR_EndLoadingPlaque = NULL; 5 | 6 | _GL_Begin2D ORIG_GL_Begin2D = NULL; 7 | _GL_Finish2D ORIG_GL_Finish2D = NULL; 8 | 9 | _GL_EndRendering ORIG_GL_EndRendering = NULL; 10 | 11 | void HOOKED_SCR_BeginLoadingPlaque(qboolean reconnect) 12 | { 13 | ORIG_SCR_BeginLoadingPlaque(reconnect); 14 | 15 | if (g_lpHUDTimer->IsInILMode()) 16 | g_lpHUDTimer->TimerStop(); 17 | } 18 | 19 | void HOOKED_SCR_EndLoadingPlaque() 20 | { 21 | ORIG_SCR_EndLoadingPlaque(); 22 | 23 | if (g_lpHUDTimer->IsInILMode() && g_RTATimer.GetMilliseconds() <= 0) 24 | g_lpHUDTimer->TimerStart(); 25 | } 26 | 27 | void HOOKED_GL_EndRendering() 28 | { 29 | // FIXME: GameUI background somehow hides HUD sprites 30 | // And it happens in the end of rendering (after all shenanigans)... 31 | ORIG_GL_Begin2D(); 32 | gBXTHud.RedrawAlwaysVisibleElements(g_lpEngfuncs->GetClientTime()); 33 | ORIG_GL_Finish2D(); 34 | 35 | ORIG_GL_EndRendering(); 36 | } -------------------------------------------------------------------------------- /src/engine/gl_screen.h: -------------------------------------------------------------------------------- 1 | #ifdef GL_SCREEN_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in gl_screen.h 3 | #else //GL_SCREEN_H_RECURSE_GUARD 4 | 5 | #define GL_SCREEN_H_RECURSE_GUARD 6 | 7 | #ifndef GL_SCREEN_H_GUARD 8 | #define GL_SCREEN_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | typedef void (*_SCR_BeginLoadingPlaque)(qboolean reconnect); 14 | typedef void (*_SCR_EndLoadingPlaque)(); 15 | typedef void (*_GL_Begin2D)(); 16 | typedef void (*_GL_Finish2D)(); 17 | typedef void (*_GL_EndRendering)(); 18 | 19 | extern _SCR_BeginLoadingPlaque ORIG_SCR_BeginLoadingPlaque; 20 | extern _SCR_EndLoadingPlaque ORIG_SCR_EndLoadingPlaque; 21 | extern _GL_Begin2D ORIG_GL_Begin2D; 22 | extern _GL_Finish2D ORIG_GL_Finish2D; 23 | extern _GL_EndRendering ORIG_GL_EndRendering; 24 | 25 | void HOOKED_SCR_BeginLoadingPlaque(qboolean reconnect); 26 | void HOOKED_SCR_EndLoadingPlaque(); 27 | void HOOKED_GL_EndRendering(); 28 | 29 | #else //!__cplusplus 30 | #error C++ compiler required to compile gl_screen.h 31 | #endif //__cplusplus 32 | 33 | #endif //GL_SCREEN_H_GUARD 34 | 35 | #undef GL_SCREEN_H_RECURSE_GUARD 36 | #endif //GL_SCREEN_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/engine/server.h: -------------------------------------------------------------------------------- 1 | #ifdef SVC_MESSAGES_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in svc_messages.h 3 | #else //SVC_MESSAGES_H_RECURSE_GUARD 4 | 5 | #define SVC_MESSAGES_H_RECURSE_GUARD 6 | 7 | #ifndef SVC_MESSAGES_H_GUARD 8 | #define SVC_MESSAGES_H_GUARD 9 | #pragma once 10 | 11 | #ifdef __cplusplus 12 | 13 | #define SVC_BAD 0 14 | #define SVC_NOP 1 15 | #define SVC_DISCONNECT 2 16 | #define SVC_EVENT 3 17 | #define SVC_VERSION 4 18 | #define SVC_SETVIEW 5 19 | #define SVC_SOUND 6 20 | #define SVC_TIME 7 21 | #define SVC_PRINT 8 22 | #define SVC_STUFFTEXT 9 23 | #define SVC_SETANGLE 10 24 | #define SVC_SERVERINFO 11 25 | #define SVC_LIGHTSTYLE 12 26 | #define SVC_UPDATEUSERINFO 13 27 | #define SVC_DELTADESCRIPTION 14 28 | #define SVC_CLIENTDATA 15 29 | #define SVC_STOPSOUND 16 30 | #define SVC_PINGS 17 31 | #define SVC_PARTICLE 18 32 | #define SVC_DAMAGE 19 33 | #define SVC_SPAWNSTATIC 20 34 | #define SVC_EVENT_RELIABLE 21 35 | #define SVC_SPAWNBASELINE 22 36 | #define SVC_TEMPENTITY 23 37 | #define SVC_SETPAUSE 24 38 | #define SVC_SIGNONNUM 25 39 | #define SVC_CENTERPRINT 26 40 | #define SVC_KILLEDMONSTER 27 41 | #define SVC_FOUNDSECRET 28 42 | #define SVC_SPAWNSTATICSOUND 29 43 | #define SVC_INTERMISSION 30 44 | #define SVC_FINALE 31 45 | #define SVC_CDTRACK 32 46 | #define SVC_RESTORE 33 47 | #define SVC_CUTSCENE 34 48 | #define SVC_WEAPONANIM 35 49 | #define SVC_DECALNAME 36 50 | #define SVC_ROOMTYPE 37 51 | #define SVC_ADDANGLE 38 52 | #define SVC_NEWUSERMSG 39 53 | #define SVC_PACKETENTITIES 40 54 | #define SVC_DELTAPACKETENTITIES 41 55 | #define SVC_CHOKE 42 56 | #define SVC_RESOURCELIST 43 57 | #define SVC_NEWMOVEVARS 44 58 | #define SVC_RESOURCEREQUEST 45 59 | #define SVC_CUSTOMIZATION 46 60 | #define SVC_CROSSHAIRANGLE 47 61 | #define SVC_SOUNDFADE 48 62 | #define SVC_FILETXFERFAILED 49 63 | #define SVC_HLTV 50 64 | #define SVC_DIRECTOR 51 65 | #define SVC_VOICEINIT 52 66 | #define SVC_VOICEDATA 53 67 | #define SVC_SENDEXTRAINFO 54 68 | #define SVC_TIMESCALE 55 69 | #define SVC_RESOURCELOCATION 56 70 | #define SVC_SENDCVARVALUE 57 71 | #define SVC_SENDCVARVALUE2 58 72 | 73 | typedef struct _UserMsg 74 | { 75 | int iMsg; 76 | int iSize; 77 | char szName[16]; 78 | _UserMsg* next; 79 | pfnUserMsgHook pfn; 80 | } UserMsg; 81 | 82 | const int MAX_CONSISTENCY_LIST = 512; 83 | 84 | typedef struct consistency_s 85 | { 86 | char* filename; 87 | int issound; 88 | int orig_index; 89 | int value; 90 | int check_type; 91 | float mins[3]; 92 | float maxs[3]; 93 | } consistency_t; 94 | 95 | typedef struct event_s 96 | { 97 | unsigned short index; 98 | const char* filename; 99 | int filesize; 100 | const char* pszScript; 101 | } event_t; 102 | 103 | typedef enum server_state_e 104 | { 105 | ss_dead = 0, 106 | ss_loading = 1, 107 | ss_active = 2, 108 | } server_state_t; 109 | 110 | typedef struct sizebuf_s 111 | { 112 | const char* buffername; 113 | uint16_t flags; 114 | byte* data; 115 | int maxsize; 116 | int cursize; 117 | } sizebuf_t; 118 | 119 | const int NUM_BASELINES = 64; 120 | #define MAX_RESOURCE_LIST 1280 121 | 122 | #define MAX_MODEL_INDEX_BITS 9 // sent as a short 123 | #define MAX_MODELS (1 << MAX_MODEL_INDEX_BITS) 124 | 125 | #define MAX_EVENTS 256 126 | 127 | #define MAX_SOUND_INDEX_BITS 9 128 | #define MAX_SOUNDS (1 << MAX_SOUND_INDEX_BITS) 129 | #define MAX_SOUNDS_HASHLOOKUP_SIZE (MAX_SOUNDS * 2 - 1) 130 | 131 | #define MAX_GENERIC_INDEX_BITS 9 132 | #define MAX_GENERIC (1 << MAX_GENERIC_INDEX_BITS) 133 | 134 | #define MAX_LIGHTSTYLE_INDEX_BITS 6 135 | #define MAX_LIGHTSTYLES (1 << MAX_LIGHTSTYLE_INDEX_BITS) 136 | 137 | const int MAX_DATAGRAM = 4000; 138 | 139 | typedef struct extra_baselines_s 140 | { 141 | int number; 142 | int classname[NUM_BASELINES]; 143 | entity_state_t baseline[NUM_BASELINES]; 144 | } extra_baselines_t; 145 | 146 | typedef struct server_s 147 | { 148 | qboolean active; 149 | qboolean paused; 150 | qboolean loadgame; 151 | double time; 152 | double oldtime; 153 | int lastcheck; 154 | double lastchecktime; 155 | char name[64]; 156 | char oldname[64]; 157 | char startspot[64]; 158 | char modelname[64]; 159 | struct model_s* worldmodel; 160 | CRC32_t worldmapCRC; 161 | unsigned char clientdllmd5[16]; 162 | resource_t resourcelist[MAX_RESOURCE_LIST]; 163 | int num_resources; 164 | consistency_t consistency_list[MAX_CONSISTENCY_LIST]; 165 | int num_consistency; 166 | const char* model_precache[MAX_MODELS]; 167 | struct model_s* models[MAX_MODELS]; 168 | unsigned char model_precache_flags[MAX_MODELS]; 169 | struct event_s event_precache[MAX_EVENTS]; 170 | const char* sound_precache[MAX_SOUNDS]; 171 | short int sound_precache_hashedlookup[MAX_SOUNDS_HASHLOOKUP_SIZE]; 172 | qboolean sound_precache_hashedlookup_built; 173 | const char* generic_precache[MAX_GENERIC]; 174 | char generic_precache_names[MAX_GENERIC][64]; 175 | int num_generic_names; 176 | const char* lightstyles[MAX_LIGHTSTYLES]; 177 | int num_edicts; 178 | int max_edicts; 179 | edict_t* edicts; 180 | entity_state_s* baselines; 181 | extra_baselines_t* instance_baselines; 182 | server_state_t state; 183 | sizebuf_t datagram; 184 | unsigned char datagram_buf[MAX_DATAGRAM]; 185 | sizebuf_t reliable_datagram; 186 | unsigned char reliable_datagram_buf[MAX_DATAGRAM]; 187 | sizebuf_t multicast; 188 | unsigned char multicast_buf[1024]; 189 | sizebuf_t spectator; 190 | unsigned char spectator_buf[1024]; 191 | sizebuf_t signon; 192 | unsigned char signon_data[32768]; 193 | } server_t; 194 | 195 | #define MAX_PACKET_ENTITIES 256 196 | #define MAX_PACKET_ENTITIES_HL25 1024 197 | 198 | struct packet_entities_t 199 | { 200 | int num_entities; 201 | byte flags[MAX_PACKET_ENTITIES / 8]; 202 | entity_state_s* entities; 203 | }; 204 | 205 | struct packet_entities_HL25_t 206 | { 207 | int num_entities; 208 | byte flags[MAX_PACKET_ENTITIES_HL25 / 8]; 209 | entity_state_s* entities; 210 | }; 211 | 212 | typedef struct cmd_s 213 | { 214 | usercmd_t cmd; 215 | float senttime; 216 | float receivedtime; 217 | float frame_lerp; 218 | qboolean processedfuncs; 219 | qboolean heldback; 220 | int sendsize; 221 | } cmd_t; 222 | 223 | typedef struct event_args_s 224 | { 225 | int flags; 226 | int entindex; 227 | float origin[3]; 228 | float angles[3]; 229 | float velocity[3]; 230 | int ducking; 231 | float fparam1; 232 | float fparam2; 233 | int iparam1; 234 | int iparam2; 235 | int bparam1; 236 | int bparam2; 237 | } event_args_t; 238 | 239 | 240 | struct event_info_s 241 | { 242 | unsigned short index; // 0 implies not in use 243 | 244 | short packet_index; // Use data from state info for entity in delta_packet . -1 implies separate info based on event 245 | // parameter signature 246 | short entity_index; // The edict this event is associated with 247 | 248 | float fire_time; // if non-zero, the time when the event should be fired ( fixed up on the client ) 249 | 250 | event_args_t args; 251 | 252 | // CLIENT ONLY 253 | int flags; // Reliable or not, etc. 254 | }; 255 | 256 | typedef struct event_state_s event_state_t; 257 | 258 | struct event_state_s 259 | { 260 | struct event_info_s ei[64]; 261 | }; 262 | 263 | typedef struct screenfade_s 264 | { 265 | float fadeSpeed; 266 | float fadeEnd; 267 | float fadeTotalEnd; 268 | float fadeReset; 269 | byte fader; 270 | byte fadeg; 271 | byte fadeb; 272 | byte fadealpha; 273 | int fadeFlags; 274 | } screenfade_t; 275 | 276 | typedef struct clientdata_s 277 | { 278 | vec3_t origin; 279 | vec3_t velocity; 280 | int viewmodel; 281 | vec3_t punchangle; 282 | int flags; 283 | int waterlevel; 284 | int watertype; 285 | vec3_t view_ofs; 286 | float health; 287 | int bInDuck; 288 | int weapons; 289 | int flTimeStepSound; 290 | int flDuckTime; 291 | int flSwimTime; 292 | int waterjumptime; 293 | float maxspeed; 294 | float fov; 295 | int weaponanim; 296 | int m_iId; 297 | int ammo_shells; 298 | int ammo_nails; 299 | int ammo_cells; 300 | int ammo_rockets; 301 | float m_flNextAttack; 302 | int tfstate; 303 | int pushmsec; 304 | int deadflag; 305 | char physinfo[256]; 306 | int iuser1; 307 | int iuser2; 308 | int iuser3; 309 | int iuser4; 310 | float fuser1; 311 | float fuser2; 312 | float fuser3; 313 | float fuser4; 314 | vec3_t vuser1; 315 | vec3_t vuser2; 316 | vec3_t vuser3; 317 | vec3_t vuser4; 318 | } clientdata_t; 319 | 320 | typedef struct weapon_data_s 321 | { 322 | int m_iId; 323 | int m_iClip; 324 | float m_flNextPrimaryAttack; 325 | float m_flNextSecondaryAttack; 326 | float m_flTimeWeaponIdle; 327 | int m_fInReload; 328 | int m_fInSpecialReload; 329 | float m_flNextReload; 330 | float m_flPumpTime; 331 | float m_fReloadTime; 332 | float m_fAimedDamage; 333 | float m_fNextAimBonus; 334 | int m_fInZoom; 335 | int m_iWeaponState; 336 | int iuser1; 337 | int iuser2; 338 | int iuser3; 339 | int iuser4; 340 | float fuser1; 341 | float fuser2; 342 | float fuser3; 343 | float fuser4; 344 | } weapon_data_t; 345 | 346 | typedef struct local_state_s 347 | { 348 | entity_state_t playerstate; 349 | clientdata_t client; 350 | weapon_data_t weapondata[64]; 351 | } local_state_t; 352 | 353 | typedef struct dlight_s 354 | { 355 | vec3_t origin; 356 | float radius; 357 | color24 color; 358 | float die; 359 | float decay; 360 | float minlight; 361 | int key; 362 | qboolean dark; 363 | } dlight_t; 364 | 365 | typedef struct player_info_s 366 | { 367 | int userid; 368 | char userinfo[256]; 369 | char name[32]; 370 | int spectator; 371 | int ping; 372 | int packet_loss; 373 | char model[64]; 374 | int topcolor; 375 | int bottomcolor; 376 | int renderframe; 377 | int gaitsequence; 378 | float gaitframe; 379 | float gaityaw; 380 | vec3_t prevgaitorigin; 381 | customization_t customdata; 382 | char hashedcdkey[16]; 383 | uint64_t m_nSteamID; 384 | } player_info_t; 385 | 386 | typedef struct frame_s 387 | { 388 | double receivedtime; 389 | double latency; 390 | qboolean invalid; 391 | qboolean choked; 392 | entity_state_t playerstate[32]; 393 | double time; 394 | clientdata_t clientdata; 395 | weapon_data_t weapondata[64]; 396 | packet_entities_t packet_entities; 397 | unsigned short clientbytes; 398 | unsigned short playerinfobytes; 399 | unsigned short packetentitybytes; 400 | unsigned short tentitybytes; 401 | unsigned short soundbytes; 402 | unsigned short eventbytes; 403 | unsigned short usrbytes; 404 | unsigned short voicebytes; 405 | unsigned short msgbytes; 406 | 407 | } frame_t; 408 | 409 | typedef struct frame_HL25_s 410 | { 411 | double receivedtime; 412 | double latency; 413 | qboolean invalid; 414 | qboolean choked; 415 | entity_state_t playerstate[32]; 416 | double time; 417 | clientdata_t clientdata; 418 | weapon_data_t weapondata[64]; 419 | packet_entities_HL25_t packet_entities; 420 | unsigned short clientbytes; 421 | unsigned short playerinfobytes; 422 | unsigned short packetentitybytes; 423 | unsigned short tentitybytes; 424 | unsigned short soundbytes; 425 | unsigned short eventbytes; 426 | unsigned short usrbytes; 427 | unsigned short voicebytes; 428 | unsigned short msgbytes; 429 | } frame_HL25_t; 430 | 431 | typedef struct client_state_s 432 | { 433 | int max_edicts; 434 | resource_t resourcesonhand; 435 | resource_t resourcesneeded; 436 | resource_t resourcelist[MAX_RESOURCE_LIST]; 437 | int num_resources; 438 | qboolean need_force_consistency_response; 439 | char serverinfo[512]; 440 | int servercount; 441 | int validsequence; 442 | int parsecount; 443 | int parsecountmod; 444 | int stats[32]; 445 | int weapons; 446 | usercmd_t cmd; 447 | Vector viewangles; 448 | Vector punchangle; 449 | Vector crosshairangle; 450 | Vector simorg; 451 | Vector simvel; 452 | Vector simangles; 453 | Vector predicted_origins[64]; 454 | Vector prediction_error; 455 | float idealpitch; 456 | Vector viewheight; 457 | screenfade_t sf; 458 | qboolean paused; 459 | int onground; 460 | int moving; 461 | int waterlevel; 462 | int usehull; 463 | float maxspeed; 464 | int pushmsec; 465 | int light_level; 466 | int intermission; 467 | double mtime[2]; 468 | double time; 469 | double oldtime; 470 | frame_t frames[64]; 471 | cmd_t commands[64]; 472 | local_state_t predicted_frames[64]; 473 | int delta_sequence; 474 | int playernum; 475 | event_t event_precache[MAX_EVENTS]; 476 | model_t* model_precache[MAX_MODELS]; 477 | int model_precache_count; 478 | sfx_t* sound_precache[MAX_SOUNDS]; 479 | consistency_t consistency_list[MAX_CONSISTENCY_LIST]; 480 | int num_consistency; 481 | int highentity; 482 | char levelname[40]; 483 | int maxclients; 484 | int gametype; 485 | int viewentity; 486 | model_t* worldmodel; 487 | efrag_t* free_efrags; 488 | int num_entities; 489 | int num_statics; 490 | cl_entity_t viewent; 491 | int cdtrack; 492 | int looptrack; 493 | CRC32_t serverCRC; 494 | unsigned char clientdllmd5[16]; 495 | float weaponstarttime; 496 | int weaponsequence; 497 | int fPrecaching; 498 | dlight_t* pLight; 499 | player_info_t players[32]; 500 | entity_state_t instanced_baseline[64]; 501 | int instanced_baseline_number; 502 | CRC32_t mapCRC; 503 | event_state_t events; 504 | char downloadUrl[128]; 505 | } client_state_t; 506 | 507 | typedef struct client_state_HL25_s 508 | { 509 | int max_edicts; 510 | resource_t resourcesonhand; 511 | resource_t resourcesneeded; 512 | resource_t resourcelist[MAX_RESOURCE_LIST]; 513 | int num_resources; 514 | qboolean need_force_consistency_response; 515 | char serverinfo[512]; 516 | int servercount; 517 | int validsequence; 518 | int parsecount; 519 | int parsecountmod; 520 | int stats[32]; 521 | int weapons; 522 | usercmd_t cmd; 523 | Vector viewangles; 524 | Vector punchangle; 525 | Vector crosshairangle; 526 | Vector simorg; 527 | Vector simvel; 528 | Vector simangles; 529 | Vector predicted_origins[64]; 530 | Vector prediction_error; 531 | float idealpitch; 532 | Vector viewheight; 533 | screenfade_t sf; 534 | qboolean paused; 535 | int onground; 536 | int moving; 537 | int waterlevel; 538 | int usehull; 539 | float maxspeed; 540 | int pushmsec; 541 | int light_level; 542 | int intermission; 543 | double mtime[2]; 544 | double time; 545 | double oldtime; 546 | frame_HL25_t frames[64]; 547 | cmd_t commands[64]; 548 | local_state_t predicted_frames[64]; 549 | int delta_sequence; 550 | int playernum; 551 | event_t event_precache[MAX_EVENTS]; 552 | model_t* model_precache[MAX_MODELS]; 553 | int model_precache_count; 554 | sfx_t* sound_precache[MAX_SOUNDS]; 555 | consistency_t consistency_list[MAX_CONSISTENCY_LIST]; 556 | int num_consistency; 557 | int highentity; 558 | char levelname[40]; 559 | int maxclients; 560 | int gametype; 561 | int viewentity; 562 | model_t* worldmodel; 563 | efrag_t* free_efrags; 564 | int num_entities; 565 | int num_statics; 566 | cl_entity_t viewent; 567 | int cdtrack; 568 | int looptrack; 569 | CRC32_t serverCRC; 570 | unsigned char clientdllmd5[16]; 571 | float weaponstarttime; 572 | int weaponsequence; 573 | int fPrecaching; 574 | dlight_t* pLight; 575 | player_info_t players[32]; 576 | entity_state_t instanced_baseline[64]; 577 | int instanced_baseline_number; 578 | CRC32_t mapCRC; 579 | event_state_t events; 580 | char downloadUrl[128]; 581 | } client_state_HL25_t; 582 | 583 | 584 | #else //!__cplusplus 585 | #error C++ compiler required to compile svc_messages.h 586 | #endif //__cplusplus 587 | 588 | #endif //SVC_MESSAGES_H_GUARD 589 | 590 | #undef SVC_MESSAGES_H_RECURSE_GUARD 591 | #endif //SVC_MESSAGES_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/engine/sound.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * 3 | * Copyright (c) 1996-2002, Valve LLC. All rights reserved. 4 | * 5 | * This product contains software technology licensed from Id 6 | * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. 7 | * All Rights Reserved. 8 | * 9 | * Use, distribution, and modification of this source code and/or resulting 10 | * object code is restricted to non-commercial enhancements to products from 11 | * Valve LLC. All other use, distribution, or modification is prohibited 12 | * without written permission from Valve LLC. 13 | * 14 | ****/ 15 | 16 | // sound.h -- client sound i/o functions 17 | 18 | #ifndef SOUND_H 19 | #define SOUND_H 20 | #ifdef _WIN32 21 | #pragma once 22 | #endif 23 | 24 | #define MAX_QPATH 64 // Must match value in quakedefs.h 25 | 26 | #define PAINTBUFFER_SIZE 512 27 | 28 | // sound engine rate defines 29 | #define SOUND_DMA_SPEED 22050 // hardware playback rate 30 | 31 | #define SOUND_11k 11025 // 11khz sample rate 32 | 33 | // sentence groups 34 | #define CBSENTENCENAME_MAX 16 35 | #define CVOXFILESENTENCEMAX 1536 // max number of sentences in game. NOTE: this must match 36 | // CVOXFILESENTENCEMAX in dlls\util.h!!! 37 | 38 | //===================================================================== 39 | // FX presets 40 | //===================================================================== 41 | 42 | #define SXROOM_OFF 0 43 | 44 | #define SXROOM_GENERIC 1 // general, low reflective, diffuse room 45 | 46 | #define SXROOM_METALIC_S 2 // highly reflective, parallel surfaces 47 | #define SXROOM_METALIC_M 3 48 | #define SXROOM_METALIC_L 4 49 | 50 | #define SXROOM_TUNNEL_S 5 // resonant reflective, long surfaces 51 | #define SXROOM_TUNNEL_M 6 52 | #define SXROOM_TUNNEL_L 7 53 | 54 | #define SXROOM_CHAMBER_S 8 // diffuse, moderately reflective surfaces 55 | #define SXROOM_CHAMBER_M 9 56 | #define SXROOM_CHAMBER_L 10 57 | 58 | #define SXROOM_BRITE_S 11 // diffuse, highly reflective 59 | #define SXROOM_BRITE_M 12 60 | #define SXROOM_BRITE_L 13 61 | 62 | #define SXROOM_WATER1 14 // underwater fx 63 | #define SXROOM_WATER2 15 64 | #define SXROOM_WATER3 16 65 | 66 | #define SXROOM_CONCRETE_S 17 // bare, reflective, parallel surfaces 67 | #define SXROOM_CONCRETE_M 18 68 | #define SXROOM_CONCRETE_L 19 69 | 70 | #define SXROOM_OUTSIDE1 20 // echoing, moderately reflective 71 | #define SXROOM_OUTSIDE2 21 // echoing, dull 72 | #define SXROOM_OUTSIDE3 22 // echoing, very dull 73 | 74 | #define SXROOM_CAVERN_S 23 // large, echoing area 75 | #define SXROOM_CAVERN_M 24 76 | #define SXROOM_CAVERN_L 25 77 | 78 | #define SXROOM_WEIRDO1 26 79 | #define SXROOM_WEIRDO2 27 80 | #define SXROOM_WEIRDO3 28 81 | 82 | #define CSXROOM 29 83 | 84 | // !!! if this is changed, it much be changed in asm_i386.h too !!! 85 | struct portable_samplepair_t 86 | { 87 | int left; 88 | int right; 89 | }; 90 | 91 | struct sfx_t 92 | { 93 | char name[MAX_QPATH]; 94 | cache_user_t cache; 95 | int servercount; 96 | }; 97 | 98 | // !!! if this is changed, it much be changed in asm_i386.h too !!! 99 | struct sfxcache_t 100 | { 101 | int length; 102 | int loopstart; 103 | int speed; 104 | int width; 105 | int stereo; 106 | byte data[1]; // variable sized 107 | }; 108 | 109 | struct dma_t 110 | { 111 | qboolean gamealive; 112 | qboolean soundalive; 113 | qboolean splitbuffer; 114 | int channels; 115 | int samples; // mono samples in buffer 116 | int submission_chunk; // don't mix less than this # 117 | int samplepos; // in mono samples 118 | int samplebits; 119 | int speed; 120 | int dmaspeed; 121 | unsigned char* buffer; 122 | }; 123 | 124 | // !!! if this is changed, it much be changed in asm_i386.h too !!! 125 | struct channel_t 126 | { 127 | sfx_t* sfx; // sfx number 128 | int leftvol; // 0-255 volume 129 | int rightvol; // 0-255 volume 130 | 131 | int end; // end time in global paintsamples 132 | int pos; // sample position in sfx 133 | 134 | int looping; // where to loop, -1 = no looping 135 | 136 | int entnum; // to allow overriding a specific sound 137 | int entchannel; // TODO: Define as enum, modify const.h then -Enko 138 | 139 | vec3_t origin; // origin of sound effect 140 | vec_t dist_mult; // distance multiplier (attenuation/clipK) 141 | 142 | int master_vol; // 0-255 master volume 143 | 144 | int isentence; // true if playing linked sentence 145 | int iword; 146 | 147 | int pitch; 148 | }; 149 | 150 | struct wavinfo_t 151 | { 152 | int rate; 153 | int width; 154 | int channels; 155 | int loopstart; 156 | int samples; 157 | int dataofs; // chunk starts this many bytes from file start 158 | }; 159 | 160 | struct wavstream_t 161 | { 162 | int csamplesplayed; 163 | int csamplesinmem; 164 | void* hFile; 165 | wavinfo_t info; 166 | int lastposloaded; 167 | }; 168 | 169 | struct voxword_t 170 | { 171 | int volume; // increase percent, ie: 125 = 125% increase 172 | int pitch; // pitch shift up percent 173 | int start; // offset start of wave percent 174 | int end; // offset end of wave percent 175 | int cbtrim; // end of wave after being trimmed to 'end' 176 | int fKeepCached; // 1 if this word was already in cache before sentence referenced it 177 | int samplefrac; // if pitch shifting, this is position into wav * 256 178 | int timecompress; // % of wave to skip during playback (causes no pitch shift) 179 | sfx_t* sfx; // name and cache pointer 180 | }; 181 | 182 | #define CVOXWORDMAX 32 183 | 184 | // ==================================================================== 185 | // User-setable variables 186 | // ==================================================================== 187 | 188 | #define MAX_CHANNELS 128 189 | #define MAX_DYNAMIC_CHANNELS 8 190 | 191 | #endif // SOUND_H -------------------------------------------------------------------------------- /src/engine_patterns.hpp: -------------------------------------------------------------------------------- 1 | #ifdef REGS_PATTERNS_HPP_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in engine_patterns.hpp 3 | #else //REGS_PATTERNS_HPP_RECURSE_GUARD 4 | 5 | #define REGS_PATTERNS_HPP_RECURSE_GUARD 6 | 7 | #ifndef REGS_PATTERNS_HPP_GUARD 8 | #define REGS_PATTERNS_HPP_GUARD 9 | #pragma once 10 | 11 | #include "external/SPTLib/patterns.hpp" 12 | #include "external/SPTLib/MemUtils.h" 13 | 14 | namespace patterns 15 | { 16 | namespace server 17 | { 18 | PATTERNS(CNihilanth_DyingThink, 19 | "Sven-5.25", 20 | "A1 ?? ?? ?? ?? 83 EC 74 F3 0F 10 00", 21 | "Sven-5.26", 22 | "83 EC 6C A1 ?? ?? ?? ?? 53 56 8B F1 F3 0F 10 00 0F 5A C0 57 8B 46 ?? 51 C7 04 24 CD CC CC 3D F2 0F 58 05 ?? ?? ?? ??"); 23 | } 24 | 25 | namespace engine 26 | { 27 | // STRINGS 28 | // ../engine/cdll_int.c, line %d: could not link client DLL for HUD initialization 29 | // joysupported 30 | // HUD_GetStudioModelInterface 31 | PATTERNS(ClientDLL_HudInit, 32 | "Sven-5.25", 33 | "A1 ?? ?? ?? ?? 85 C0 75 ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? A1 ?? ?? ?? ??" 34 | ); 35 | 36 | // STRINGS 37 | // cl_dlls/client 38 | // ScreenShake 39 | // ScreenFade 40 | PATTERNS(ClientDLL_Init, 41 | "Sven-5.25", 42 | "81 EC 04 02 00 00 A1 ?? ?? ?? ?? 33 C4 89 84 24 ?? ?? ?? ?? 68 ?? ?? ?? ?? 8D 44 24 ?? 68 00 02 00 00", 43 | "Sven-5.26-rc1", 44 | "81 EC 04 02 00 00 A1 ?? ?? ?? ?? 33 C4 89 84 24 ?? ?? ?? ?? 68 00 02 00 00 8D 44 24 ?? 6A 00 50 E8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 8D 44 24 ?? 68 FF 01 00 00" 45 | ); 46 | 47 | PATTERNS(GL_Begin2D, // a.k.a GLBeginHud 48 | "Sven-5.25", 49 | "56 FF 35 ?? ?? ?? ?? FF 35 ?? ?? ?? ?? FF 35 ?? ?? ?? ??"); 50 | 51 | PATTERNS(GL_Finish2D, 52 | "Sven-5.25", 53 | "56 68 01 17 00 00 FF 15 ?? ?? ?? ?? 8B 35 ?? ?? ?? ?? FF D6 68 00 17 00 00"); 54 | 55 | // STRINGS 56 | // Clearing memory 57 | PATTERNS(Host_ClearMemory, 58 | "Sven-5.25", 59 | "E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 7C 24 ?? 00 75 ??"); 60 | 61 | PATTERNS(LoadThisDll, 62 | "Sven-5.25", 63 | "53 57 8B 7C 24 ?? 57 E8 ?? ?? ?? ?? 8B D8 83 C4 04 85 DB 75 ?? E8 ?? ?? ?? ??"); 64 | 65 | PATTERNS(Netchan_CreateFragments, 66 | "Sven-5.25", "B8 1C 00 04 00 E8 ?? ?? ?? ?? A1 ?? ?? ?? ?? 33 C4 89 84 24 ?? ?? ?? ?? 55 8B AC 24 ?? ?? ?? ??"); 67 | 68 | PATTERNS(SZ_Write, 69 | "Sven-5.25", "8B 4C 24 ?? 85 C9 75 ?? 56"); 70 | 71 | PATTERNS(SZ_GetSpace, 72 | "Sven-5.25", "56 8B 74 24 08 57 8B 7C 24 10 8B 4E 10 8B 56 0C 8D 04 39 3B C2 0F 8E ?? ?? ?? ?? F6 46 04 01 75 2E 8B 06 85 D2 75 11 85 C0 75 05 B8 ?? ?? ?? ?? 50 68 ?? ?? ?? ?? EB 0F 85 C0 75 05 B8"); 73 | 74 | PATTERNS(Mod_LoadTextures, 75 | "Sven-5.25", "83 EC 74 A1 ?? ?? ?? ?? 33 C4 89 44 24 ?? 53 8B 5C 24 ??"); 76 | 77 | PATTERNS(SCR_BeginLoadingPlaque, 78 | "Sven-5.25", 79 | "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 83 C4 04 83 F8 03 74 ?? 83 F8 04 74 ?? 83 F8 05 75 ?? 83 3D ?? ?? ?? ?? 02"); 80 | 81 | PATTERNS(SCR_EndLoadingPlaque, 82 | "Sven-5.25", 83 | "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 08 C7 05 ?? ?? ?? ?? 00 00 00 00"); 84 | 85 | PATTERNS(GL_EndRendering, 86 | "Sven-5.25", 87 | "?? ?? ?? ?? ?? ?? ?? ?? 30 83 3D ?? ?? ?? ?? 00 53 55 56 57 0F 84 ?? ?? ?? ??"); 88 | 89 | PATTERNS(S_StartDynamicSound, 90 | "Sven-5.25", 91 | "83 EC 58 A1 ?? ?? ?? ?? 33 C4 89 44 24 ?? 8B 44 24 ??"); 92 | 93 | PATTERNS(S_StartStaticSound, 94 | "Sven-5.25", 95 | "83 EC 4C A1 ?? ?? ?? ?? 33 C4 89 44 24 ?? 57 8B 7C 24 ?? 85 FF 0F 84 ?? ?? ?? ?? 80 3F 2A 55 56"); 96 | } 97 | } 98 | 99 | #endif //REGS_PATTERNS_HPP_GUARD 100 | 101 | #undef REGS_PATTERNS_HPP_RECURSE_GUARD 102 | #endif //REGS_PATTERNS_HPP_RECURSE_GUARD -------------------------------------------------------------------------------- /src/external/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_FOLDER "External") 2 | 3 | add_subdirectory(funchook) -------------------------------------------------------------------------------- /src/external/SPTLib/MemUtils.h: -------------------------------------------------------------------------------- 1 | #ifdef MEMUTILS_H_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in MemUtils.h 3 | #else //MEMUTILS_H_RECURSE_GUARD 4 | 5 | #define MEMUTILS_H_RECURSE_GUARD 6 | 7 | #ifndef MEMUTILS_H_GUARD 8 | #define MEMUTILS_H_GUARD 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "patterns.hpp" 22 | #include 23 | #pragma comment(lib, "psapi.lib") 24 | 25 | namespace MemUtils 26 | { 27 | using namespace patterns; 28 | 29 | template 30 | class LazilyConstructed 31 | { 32 | // Not a unique_ptr to prevent any further "constructors haven't run yet" issues. 33 | // _Hopefully_ this gets put in BSS so it's nullptr by default for global objects. 34 | T* object; 35 | 36 | public: 37 | LazilyConstructed(): object(nullptr) {} 38 | // The object is leaked (this is meant to be used only for global stuff anyway). 39 | // Some stuff calls dlclose after the destructors have been run, so destroying the 40 | // object here leads to crashes. 41 | ~LazilyConstructed() {} 42 | 43 | T& get() 44 | { 45 | if (!object) 46 | object = new T(); 47 | 48 | assert(object); 49 | return *object; 50 | } 51 | }; 52 | 53 | inline bool GetModuleInfo(void* moduleHandle, void** moduleBase, size_t* moduleSize) 54 | { 55 | if (!moduleHandle) 56 | return false; 57 | 58 | MODULEINFO Info; 59 | GetModuleInformation(GetCurrentProcess(), reinterpret_cast(moduleHandle), &Info, sizeof(Info)); 60 | 61 | if (moduleBase) 62 | *moduleBase = Info.lpBaseOfDll; 63 | 64 | if (moduleSize) 65 | *moduleSize = (size_t)Info.SizeOfImage; 66 | 67 | return true; 68 | } 69 | 70 | inline bool GetModuleInfo(const std::wstring& moduleName, void** moduleHandle, void** moduleBase, size_t* moduleSize) 71 | { 72 | HMODULE Handle = GetModuleHandleW(moduleName.c_str()); 73 | auto ret = GetModuleInfo(Handle, moduleBase, moduleSize); 74 | 75 | if (ret && moduleHandle) 76 | *moduleHandle = Handle; 77 | 78 | return ret; 79 | } 80 | 81 | inline void* GetSymbolAddress(void* moduleHandle, const char* functionName) 82 | { 83 | return GetProcAddress(reinterpret_cast(moduleHandle), functionName); 84 | } 85 | 86 | inline uintptr_t find_pattern(const void* start, size_t length, const PatternWrapper& pattern) 87 | { 88 | if (length < pattern.length()) 89 | return 0; 90 | 91 | auto p = static_cast(start); 92 | for (auto end = p + length - pattern.length(); p <= end; ++p) 93 | { 94 | if (pattern.match(p)) 95 | return reinterpret_cast(p); 96 | } 97 | 98 | return 0; 99 | } 100 | 101 | template 102 | inline Iterator find_first_sequence( 103 | const void* start, 104 | size_t length, 105 | Iterator begin, 106 | Iterator end, 107 | uintptr_t& address) 108 | { 109 | for (auto pattern = begin; pattern != end; ++pattern) 110 | { 111 | address = find_pattern(start, length, *pattern); 112 | if (address) 113 | return pattern; 114 | } 115 | address = 0; 116 | return end; 117 | } 118 | 119 | 120 | inline void MarkAsExecutable(void* addr) 121 | { 122 | if (!addr) 123 | return; 124 | 125 | MEMORY_BASIC_INFORMATION mi; 126 | if (!VirtualQuery(addr, &mi, sizeof(MEMORY_BASIC_INFORMATION))) 127 | return; 128 | 129 | if (mi.State != MEM_COMMIT) 130 | return; 131 | 132 | DWORD protect; 133 | switch (mi.Protect) 134 | { 135 | case PAGE_READONLY: 136 | protect = PAGE_EXECUTE_READ; 137 | break; 138 | 139 | case PAGE_READWRITE: 140 | protect = PAGE_EXECUTE_READWRITE; 141 | break; 142 | 143 | case PAGE_WRITECOPY: 144 | protect = PAGE_EXECUTE_WRITECOPY; 145 | break; 146 | 147 | default: 148 | return; 149 | } 150 | 151 | DWORD temp; 152 | VirtualProtect(addr, 1, protect, &temp); 153 | } 154 | 155 | template 156 | inline void MarkAsExecutable(T addr) 157 | { 158 | MarkAsExecutable(reinterpret_cast(addr)); 159 | } 160 | 161 | inline void ReplaceBytes(void* addr, size_t length, const uint8_t* newBytes) 162 | { 163 | DWORD dwOldProtect; 164 | auto result = VirtualProtect(addr, length, PAGE_EXECUTE_READWRITE, &dwOldProtect); 165 | 166 | for (size_t i = 0; i < length; ++i) 167 | *(reinterpret_cast(addr) + i) = newBytes[i]; 168 | 169 | // The first call might have failed, but the target might have still been accessible. 170 | if (result) 171 | VirtualProtect(addr, length, dwOldProtect, &dwOldProtect); 172 | } 173 | 174 | template 175 | inline Iterator find_first_sequence( 176 | const void* start, 177 | size_t length, 178 | Iterator begin, 179 | Iterator end, 180 | Result& address) 181 | { 182 | uintptr_t addr; 183 | auto rv = find_first_sequence(start, length, begin, end, addr); 184 | // C-style cast... Because reinterpret_cast can't cast uintptr_t to integral types. 185 | address = (Result)addr; 186 | return rv; 187 | } 188 | 189 | template 190 | Iterator find_unique_sequence( 191 | const void* start, 192 | size_t length, 193 | Iterator begin, 194 | Iterator end, 195 | uintptr_t& address) 196 | { 197 | for (auto pattern = begin; pattern != end; ++pattern) { 198 | address = find_pattern(start, length, *pattern); 199 | if (address) 200 | { 201 | // Check if match is ambiguous for pattern 202 | auto new_length = length - (address - reinterpret_cast(start) + 1); 203 | auto address2 = find_pattern(reinterpret_cast(address + 1), new_length, *pattern); 204 | 205 | if (!address2) 206 | { 207 | // No 2nd match found, report unique match 208 | return pattern; 209 | } 210 | } 211 | } 212 | } 213 | 214 | template 215 | inline Iterator find_unique_sequence( 216 | const void* start, 217 | size_t length, 218 | Iterator begin, 219 | Iterator end, 220 | Result& address) 221 | { 222 | uintptr_t addr; 223 | auto rv = find_unique_sequence(start, length, begin, end, addr); 224 | // C-style cast... Because reinterpret_cast can't cast uintptr_t to integral types. 225 | address = (Result)addr; 226 | return rv; 227 | } 228 | 229 | template 230 | inline auto find_unique_sequence_async( 231 | Result& address, 232 | const void* start, 233 | size_t length, 234 | Iterator begin, 235 | Iterator end) 236 | { 237 | return std::async(find_unique_sequence, start, length, begin, end, std::ref(address)); 238 | } 239 | 240 | template 241 | auto find_unique_sequence_async( 242 | Result& address, 243 | const void* start, 244 | size_t length, 245 | Iterator begin, 246 | Iterator end, 247 | std::function onFound) 248 | { 249 | return std::async([=, &address]() 250 | { 251 | auto it = find_unique_sequence(start, length, begin, end, address); 252 | if (address) 253 | onFound(it); 254 | return it; }); 255 | } 256 | 257 | template 258 | auto find_function_async( 259 | Result& address, 260 | void* handle, 261 | const char* name, 262 | const void* start, 263 | size_t length, 264 | Iterator begin, 265 | Iterator end) 266 | { 267 | return std::async([=, &address]() 268 | { 269 | auto it = end; 270 | address = reinterpret_cast(GetSymbolAddress(handle, name)); 271 | if (!address) 272 | it = find_unique_sequence(start, length, begin, end, address); 273 | return it; }); 274 | } 275 | 276 | template 277 | auto find_function_async( 278 | Result& address, 279 | void* handle, 280 | const char* name, 281 | const void* start, 282 | size_t length, 283 | Iterator begin, 284 | Iterator end, 285 | std::function onFound) 286 | { 287 | return std::async([=, &address]() 288 | { 289 | auto it = end; 290 | address = reinterpret_cast(GetSymbolAddress(handle, name)); 291 | if (!address) 292 | it = find_unique_sequence(start, length, begin, end, address); 293 | if (address) 294 | onFound(it); 295 | return it; }); 296 | } 297 | } 298 | 299 | #endif //MEMUTILS_H_GUARD 300 | 301 | #undef MEMUTILS_H_RECURSE_GUARD 302 | #endif //MEMUTILS_H_RECURSE_GUARD -------------------------------------------------------------------------------- /src/external/SPTLib/Utils.hpp: -------------------------------------------------------------------------------- 1 | #ifdef UTILS_HPP_RECURSE_GUARD 2 | #error Recursive header files inclusion detected in Utils.hpp 3 | #else //UTILS_HPP_RECURSE_GUARD 4 | 5 | #define UTILS_HPP_RECURSE_GUARD 6 | 7 | #ifndef UTILS_HPP_GUARD 8 | #define UTILS_HPP_GUARD 9 | #pragma once 10 | 11 | #include 12 | #include "MemUtils.h" 13 | #include "patterns.hpp" 14 | #include 15 | 16 | typedef struct Utils 17 | { 18 | Utils(void* handle, void* base, size_t length) 19 | { 20 | this->m_Handle = handle; 21 | this->m_Base = base; 22 | this->m_Length = length; 23 | } 24 | 25 | template 26 | inline auto FindAsync( 27 | Result& address, 28 | const std::array& patterns) 29 | { 30 | return MemUtils::find_unique_sequence_async( 31 | reinterpret_cast(address), 32 | m_Base, 33 | m_Length, 34 | patterns.cbegin(), 35 | patterns.cend()); 36 | } 37 | 38 | template 39 | inline auto FindSync( 40 | Result& address, 41 | const std::array& patterns) 42 | { 43 | return MemUtils::find_unique_sequence( 44 | reinterpret_cast(address), 45 | m_Base, 46 | m_Length, 47 | patterns.cbegin(), 48 | patterns.cend()); 49 | } 50 | 51 | template 52 | inline auto FindAsync( 53 | Result& address, 54 | const std::array& patterns, 55 | std::function::const_iterator)> onFound) 56 | { 57 | return MemUtils::find_unique_sequence_async( 58 | reinterpret_cast(address), 59 | m_Base, 60 | m_Length, 61 | patterns.cbegin(), 62 | patterns.cend(), 63 | onFound); 64 | } 65 | 66 | template 67 | inline auto FindFunctionAsync( 68 | Result& address, 69 | const char* name, 70 | const std::array& patterns) 71 | { 72 | return MemUtils::find_function_async( 73 | reinterpret_cast(address), 74 | m_Handle, 75 | name, 76 | m_Base, 77 | m_Length, 78 | patterns.cbegin(), 79 | patterns.cend()); 80 | } 81 | 82 | template 83 | inline auto FindFunctionAsync( 84 | Result& address, 85 | const char* name, 86 | const std::array& patterns, 87 | std::function::const_iterator)> onFound) 88 | { 89 | return MemUtils::find_function_async( 90 | reinterpret_cast(address), 91 | m_Handle, 92 | name, 93 | m_Base, 94 | m_Length, 95 | patterns.cbegin(), 96 | patterns.cend(), 97 | onFound); 98 | } 99 | 100 | protected: 101 | void* m_Handle; 102 | void* m_Base; 103 | size_t m_Length; 104 | } Utils; 105 | 106 | #endif //UTILS_HPP_GUARD 107 | 108 | #undef UTILS_HPP_RECURSE_GUARD 109 | #endif //UTILS_HPP_RECURSE_GUARDS 110 | -------------------------------------------------------------------------------- /src/external/SPTLib/patterns.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace patterns 7 | { 8 | namespace detail 9 | { 10 | constexpr uint8_t hex(char c) 11 | { 12 | return (c >= '0' && c <= '9') ? static_cast(c - '0') 13 | : (c >= 'a' && c <= 'f') ? static_cast(c - 'a' + 10) 14 | : (c >= 'A' && c <= 'F') ? static_cast(c - 'A' + 10) 15 | : throw std::domain_error("not a hex digit"); 16 | } 17 | 18 | constexpr bool ishex(char c) 19 | { 20 | return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); 21 | } 22 | } 23 | 24 | constexpr size_t count_bytes(const char* pattern) 25 | { 26 | size_t count = 0; 27 | 28 | for (; pattern[0]; ++pattern) 29 | { 30 | if (pattern[0] == ' ') 31 | continue; 32 | 33 | if (detail::ishex(pattern[0])) 34 | { 35 | if (!detail::ishex((++pattern)[0])) 36 | throw std::logic_error("the second hex digit is missing"); 37 | 38 | ++count; 39 | continue; 40 | } 41 | 42 | if (pattern[0] == '?') 43 | { 44 | if ((++pattern)[0] != '?') 45 | throw std::logic_error("the second question mark is missing"); 46 | 47 | ++count; 48 | continue; 49 | } 50 | else 51 | { 52 | throw std::domain_error("only hex digits, spaces and question marks are allowed"); 53 | } 54 | } 55 | 56 | return count; 57 | } 58 | 59 | template 60 | struct Pattern 61 | { 62 | uint8_t bytes[PatternLength]; 63 | char mask[PatternLength]; 64 | 65 | constexpr Pattern(const char* pattern) 66 | : bytes(), mask() 67 | { 68 | // Note that some input validation is absent from here, 69 | // because the input is expected to have already been validated in count_bytes(). 70 | size_t i = 0; 71 | 72 | for (; pattern[0]; ++pattern) 73 | { 74 | if (pattern[0] == ' ') 75 | continue; 76 | 77 | if (detail::ishex(pattern[0])) 78 | { 79 | bytes[i] = detail::hex(pattern[0]) * 16 + detail::hex(pattern[1]); 80 | mask[i++] = 'x'; 81 | 82 | ++pattern; 83 | continue; 84 | } 85 | 86 | if (pattern[0] == '?') 87 | { 88 | mask[i++] = '?'; 89 | 90 | ++pattern; 91 | continue; 92 | } 93 | 94 | throw std::domain_error("only hex digits, spaces and question marks are allowed"); 95 | } 96 | 97 | if (i != PatternLength) 98 | throw std::logic_error("wrong pattern length"); 99 | } 100 | }; 101 | 102 | #define PATTERN(pattern) \ 103 | ::patterns::Pattern<::patterns::count_bytes(pattern)>(pattern) 104 | 105 | class PatternWrapper 106 | { 107 | const char* name_; 108 | const uint8_t* bytes; 109 | const char* mask; 110 | const size_t length_; 111 | 112 | public: 113 | template 114 | constexpr PatternWrapper(const char* name, const Pattern& pattern) 115 | : name_(name), bytes(pattern.bytes), mask(pattern.mask), length_(PatternLength) 116 | { 117 | } 118 | 119 | template 120 | constexpr PatternWrapper(const Pattern& pattern) 121 | : PatternWrapper("", pattern) 122 | { 123 | } 124 | 125 | constexpr const char* name() const 126 | { 127 | return name_; 128 | } 129 | 130 | constexpr size_t length() const 131 | { 132 | return length_; 133 | } 134 | 135 | inline bool match(const uint8_t* memory) const 136 | { 137 | for (size_t i = 0; i < length_; ++i) 138 | if (mask[i] == 'x' && memory[i] != bytes[i]) 139 | return false; 140 | 141 | return true; 142 | } 143 | }; 144 | 145 | template 146 | constexpr std::array make_pattern_array(const Pattern&... patterns) 147 | { 148 | return {patterns...}; 149 | } 150 | 151 | #define CONCATENATE1(arg1, arg2) arg1##arg2 152 | #define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) 153 | 154 | #include "patterns_macros.hpp" 155 | 156 | #define FOR_EACH2_NARG_(...) CONCATENATE(FOR_EACH2_ARG_N(__VA_ARGS__), ) 157 | #define FOR_EACH2_NARG(...) FOR_EACH2_NARG_(__VA_ARGS__, FOR_EACH2_RSEQ_N) 158 | 159 | #define MAKE_PATTERNS_(N, ...) CONCATENATE(CONCATENATE(MAKE_PATTERN_, N)(__VA_ARGS__), ) 160 | #define MAKE_PATTERNS(name, ...) MAKE_PATTERNS_(FOR_EACH2_NARG(__VA_ARGS__), name, __VA_ARGS__) 161 | 162 | #ifdef _MSC_VER // MSVC 163 | #define NAME_PATTERNS_(N, ...) CONCATENATE(CONCATENATE(NAME_PATTERN_, N)(__VA_ARGS__), ) 164 | #define NAME_PATTERNS(name, ...) NAME_PATTERNS_(FOR_EACH2_NARG(__VA_ARGS__), name, __VA_ARGS__) 165 | #else // Not MSVC 166 | #define NAME_PATTERNS_(N, ...) CONCATENATE(NAME_PATTERN_, N)(__VA_ARGS__) 167 | #define NAME_PATTERNS(name, ...) NAME_PATTERNS_(FOR_EACH2_NARG(__VA_ARGS__), name, __VA_ARGS__) 168 | #endif 169 | 170 | /* 171 | * Defines an array of compile-time patterns. 172 | * Example: 173 | * 174 | * PATTERNS(MyPattern, 175 | * "HL-SteamPipe", 176 | * "11 22 33 ?? ?? FF AC", 177 | * "HL-NGHL", 178 | * "C0 AB 22 33 ?? 11" 179 | * ); 180 | * 181 | * is converted into: 182 | * 183 | * static constexpr auto ptn_MyPattern_2 = ::patterns::Pattern<::patterns::count_bytes("11 22 33 ?? ?? FF AC")>("11 22 33 ?? ?? FF AC"); 184 | * static constexpr auto ptn_MyPattern_1 = ::patterns::Pattern<::patterns::count_bytes("C0 AB 22 33 ?? 11")>("C0 AB 22 33 ?? 11"); 185 | * constexpr auto MyPattern = ::patterns::make_pattern_array( 186 | * PatternWrapper{ "HL-SteamPipe", ptn_MyPattern_2 }, 187 | * PatternWrapper{ "HL-NGHL", ptn_MyPattern_1 } 188 | * ); 189 | */ 190 | #define PATTERNS(name, ...) \ 191 | MAKE_PATTERNS(name, __VA_ARGS__) \ 192 | constexpr auto name = ::patterns::make_pattern_array( \ 193 | NAME_PATTERNS(name, __VA_ARGS__)); 194 | } 195 | -------------------------------------------------------------------------------- /src/iface.cpp: -------------------------------------------------------------------------------- 1 | #include "SvenBXT.h" 2 | 3 | InterfaceReg* InterfaceReg::s_pInterfaceRegs = NULL; -------------------------------------------------------------------------------- /src/iface.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - xWhitey, 2024. 3 | * iface.hpp - interface.h from Source SDK 4 | * 5 | * Lightning a.k.a. lightning.tech (Sven Co-op) header file 6 | * Authors: xWhitey. Refer to common.hpp file for dependencies and their authors. 7 | * Do not delete this comment block. Respect others' work! 8 | */ 9 | 10 | #ifdef IFACE_HPP_RECURSE_GUARD 11 | #error Recursive header files inclusion detected in iface.hpp 12 | #else //IFACE_HPP_RECURSE_GUARD 13 | 14 | #define IFACE_HPP_RECURSE_GUARD 15 | 16 | #ifndef IFACE_HPP_GUARD 17 | #define IFACE_HPP_GUARD 18 | #pragma once 19 | 20 | #ifdef __cplusplus 21 | 22 | typedef void* (*InstantiateInterfaceFn)(); 23 | 24 | class IBaseInterface 25 | { 26 | public: 27 | virtual ~IBaseInterface() {} 28 | }; 29 | 30 | typedef IBaseInterface* (*CreateInterfaceFn)(const char* pName, int* pReturnCode); 31 | 32 | // Used internally to register classes. 33 | class InterfaceReg 34 | { 35 | public: 36 | InterfaceReg(InstantiateInterfaceFn fn, const char* pName): m_pName(pName) 37 | { 38 | m_CreateFn = fn; 39 | m_pNext = s_pInterfaceRegs; 40 | s_pInterfaceRegs = this; 41 | } 42 | 43 | public: 44 | InstantiateInterfaceFn m_CreateFn; 45 | const char* m_pName; 46 | 47 | InterfaceReg* m_pNext; // For the global list. 48 | static InterfaceReg* s_pInterfaceRegs; 49 | }; 50 | 51 | #if !defined(_X360) 52 | #define CREATEINTERFACE_PROCNAME "CreateInterface" 53 | #else 54 | // x360 only allows ordinal exports, .def files export "CreateInterface" at 1 55 | #define CREATEINTERFACE_PROCNAME ((const char*)1) 56 | #endif 57 | 58 | // Use this if you want to write the factory function. 59 | #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) 60 | #define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ 61 | static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); 62 | #else 63 | #define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ 64 | namespace _SUBSYSTEM \ 65 | { \ 66 | static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); \ 67 | } 68 | #endif 69 | 70 | #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) 71 | #define EXPOSE_INTERFACE(className, interfaceName, versionName) \ 72 | static void* __Create##className##_interface() { return static_cast(new className); } \ 73 | static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName); 74 | #else 75 | #define EXPOSE_INTERFACE(className, interfaceName, versionName) \ 76 | namespace _SUBSYSTEM \ 77 | { \ 78 | static void* __Create##className##_interface() { return static_cast(new className); } \ 79 | static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName); \ 80 | } 81 | #endif 82 | 83 | // Use this to expose a singleton interface with a global variable you've created. 84 | #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) 85 | #define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \ 86 | static void* __Create##className##interfaceName##_interface() { return static_cast(&globalVarName); } \ 87 | static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); 88 | #else 89 | #define EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, interfaceNamespace, interfaceName, versionName, globalVarName) \ 90 | namespace _SUBSYSTEM \ 91 | { \ 92 | static void* __Create##className##interfaceName##_interface() { return static_cast(&globalVarName); } \ 93 | static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \ 94 | } 95 | #endif 96 | 97 | #define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ 98 | EXPOSE_SINGLE_INTERFACE_GLOBALVAR_WITH_NAMESPACE(className, , interfaceName, versionName, globalVarName) 99 | 100 | // Use this to expose a singleton interface. This creates the global variable for you automatically. 101 | #if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) 102 | #define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ 103 | static className __g_##className##_singleton; \ 104 | EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) 105 | #else 106 | #define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ 107 | namespace _SUBSYSTEM \ 108 | { \ 109 | static className __g_##className##_singleton; \ 110 | } \ 111 | EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) 112 | #endif 113 | 114 | #else //!__cplusplus 115 | #error C++ compiler required to compile iface.hpp 116 | #endif //__cplusplus 117 | 118 | #endif //IFACE_HPP_GUARD 119 | 120 | #undef IFACE_HPP_RECURSE_GUARD 121 | #endif //IFACE_HPP_RECURSE_GUARD -------------------------------------------------------------------------------- /src/metahook_emulation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - xWhitey, 2024. 3 | * svenmod_emulation.cpp - actual implementation of the emulation system 4 | * 5 | * Lightning a.k.a. lightning.tech (Sven Co-op) source file 6 | * Authors: xWhitey. Refer to common.hpp file for dependencies and their authors. 7 | * Do not delete this comment block. Respect others' work! 8 | */ 9 | 10 | #include "SvenBXT.h" 11 | #include "metahook_emulation.hpp" 12 | 13 | void CMHSvenBXT::Init(void* _MetaHookAPI, void* _Interface, void* _Save) { 14 | } 15 | 16 | void CMHSvenBXT::Shutdown() { 17 | } 18 | 19 | void CMHSvenBXT::LoadEngine(void* _Engfuncs) { 20 | //g_lpEngfuncs = indirect_cast(_Engfuncs); 21 | } 22 | 23 | void CMHSvenBXT::LoadClient(void* _ExportFunc) { 24 | } 25 | 26 | void CMHSvenBXT::ExitGame(int _Result) { 27 | } 28 | 29 | EXPOSE_SINGLE_INTERFACE(CMHSvenBXT, CMHSvenBXT, METAHOOK_PLUGIN_API_VERSION_V3); -------------------------------------------------------------------------------- /src/metahook_emulation.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - xWhitey, 2024. 3 | * metahook_emulation.hpp - here we're going to emulate metahook plugin behaviour 4 | * 5 | * Lightning a.k.a. lightning.tech (Sven Co-op) header file 6 | * Authors: xWhitey. Refer to common.hpp file for dependencies and their authors. 7 | * Do not delete this comment block. Respect others' work! 8 | */ 9 | 10 | #ifdef METAHOOK_EMULATION_HPP_RECURSE_GUARD 11 | #error Recursive header files inclusion detected in metahook_emulation.hpp 12 | #else //METAHOOK_EMULATION_HPP_RECURSE_GUARD 13 | 14 | #define METAHOOK_EMULATION_HPP_RECURSE_GUARD 15 | 16 | #ifndef METAHOOK_EMULATION_HPP_GUARD 17 | #define METAHOOK_EMULATION_HPP_GUARD 18 | #pragma once 19 | 20 | #ifdef __cplusplus 21 | 22 | typedef struct CMHSvenBXT : public IBaseInterface { 23 | virtual void Init(_In_ void* _MetaHookAPI, _In_ void* _Interface, _In_ void* _Save); 24 | virtual void Shutdown(); 25 | virtual void LoadEngine(_In_ void* _EngineFuncs); 26 | virtual void LoadClient(_In_ void* _ExportFuncs); 27 | virtual void ExitGame(_In_ int Result); 28 | } CMHSvenBXT; 29 | 30 | using CMHSvenBXT = struct CMHSvenBXT; 31 | 32 | #define METAHOOK_PLUGIN_API_VERSION_V3 "METAHOOK_PLUGIN_API_VERSION003" 33 | 34 | #else //!__cplusplus 35 | #error C++ compiler required to compile metahook_emulation.hpp 36 | #endif //__cplusplus 37 | 38 | #endif //METAHOOK_EMULATION_HPP_GUARD 39 | 40 | #undef METAHOOK_EMULATION_HPP_RECURSE_GUARD 41 | #endif //METAHOOK_EMULATION_HPP_RECURSE_GUARD -------------------------------------------------------------------------------- /src/svenmod_emulation.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - xWhitey, 2024. 3 | * svenmod_emulation.cpp - actual implementation of the emulation system 4 | * 5 | * Lightning a.k.a. lightning.tech (Sven Co-op) source file 6 | * Authors: xWhitey. Refer to common.hpp file for dependencies and their authors. 7 | * Do not delete this comment block. Respect others' work! 8 | */ 9 | 10 | #include "SvenBXT.h" 11 | #include "svenmod_emulation.hpp" 12 | 13 | CSMSvenBXT g_SMSvenBXT; 14 | EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CSMSvenBXT, IClientPlugin, "ClientPlugin002", g_SMSvenBXT); 15 | 16 | CSMSvenBXT* g_lpSMSvenBXT = &g_SMSvenBXT; 17 | 18 | api_version_t CSMSvenBXT::GetAPIVersion() { 19 | return { (4), (0) }; 20 | } 21 | 22 | bool CSMSvenBXT::Load(CreateInterfaceFn _Factory, void* _SvenModAPI, void* _Unused) { 23 | return true; 24 | } 25 | 26 | void CSMSvenBXT::PostLoad(bool _GlobalLoad) {} 27 | 28 | void CSMSvenBXT::Unload() { 29 | } 30 | 31 | bool CSMSvenBXT::Pause() { 32 | return false; 33 | } 34 | 35 | void CSMSvenBXT::Unpause() {} 36 | 37 | void CSMSvenBXT::OnFirstClientdataReceived(void *pcldata, float flTime) { 38 | 39 | } 40 | 41 | void CSMSvenBXT::OnBeginLoading() { 42 | 43 | } 44 | 45 | void CSMSvenBXT::OnEndLoading() { 46 | 47 | } 48 | 49 | void CSMSvenBXT::OnDisconnect() { 50 | 51 | } 52 | 53 | void CSMSvenBXT::GameFrame(void*, double, bool) {} 54 | 55 | PLUGIN_RESULT CSMSvenBXT::Draw() { 56 | return PLUGIN_RESULT::PLUGIN_CONTINUE; 57 | } 58 | 59 | PLUGIN_RESULT CSMSvenBXT::DrawHUD(float time, int intermission) { 60 | return PLUGIN_RESULT::PLUGIN_CONTINUE; 61 | } 62 | 63 | const char* CSMSvenBXT::GetName() { 64 | return "SvenBXT"; 65 | } 66 | 67 | const char* CSMSvenBXT::GetAuthor() { 68 | return "ScriptedSnark"; 69 | } 70 | 71 | const char* CSMSvenBXT::GetVersion() { 72 | return SVENBXT_VERSION; 73 | } 74 | 75 | const char* CSMSvenBXT::GetDescription() { 76 | return "an advanced utility mod for Sven Co-op providing speedrunning tools"; 77 | } 78 | 79 | const char* CSMSvenBXT::GetURL() { 80 | return SVENBXT_GITHUB_URL; 81 | } 82 | 83 | const char* CSMSvenBXT::GetDate() { 84 | return __TIMESTAMP__; 85 | } 86 | 87 | const char* CSMSvenBXT::GetLogTag() { 88 | return "SvenBXT"; 89 | } 90 | 91 | enum 92 | { 93 | IFACE_OK = 0, 94 | IFACE_FAILED 95 | }; 96 | 97 | extern "C" __declspec(dllexport) void* CreateInterface(const char* _lpszName,int* _lpReturnCode) { 98 | InterfaceReg *pCur; 99 | 100 | for (pCur = InterfaceReg::s_pInterfaceRegs; pCur; pCur = pCur->m_pNext) 101 | { 102 | if (!strcmp(pCur->m_pName, _lpszName)) 103 | { 104 | if (_lpReturnCode) 105 | *_lpReturnCode = IFACE_OK; 106 | 107 | return pCur->m_CreateFn(); 108 | } 109 | } 110 | 111 | if (_lpReturnCode) 112 | *_lpReturnCode = IFACE_FAILED; 113 | 114 | return NULL; 115 | } -------------------------------------------------------------------------------- /src/svenmod_emulation.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - xWhitey, 2024. 3 | * svenmod_emulation.hpp - an advanced emulation system which allows us to act as a SvenMod plugin. 4 | * 5 | * SMSvenBXT a.k.a. lightning.tech (Sven Co-op) header file 6 | * Authors: xWhitey. Refer to common.hpp file for dependencies and their authors. 7 | * Do not delete this comment block. Respect others' work! 8 | */ 9 | 10 | #ifdef SVENMOD_EMULATION_HPP_RECURSE_GUARD 11 | #error Recursive header files inclusion detected in svenmod_emulation.hpp 12 | #else //SVENMOD_EMULATION_HPP_RECURSE_GUARD 13 | 14 | #define SVENMOD_EMULATION_HPP_RECURSE_GUARD 15 | 16 | #ifndef SVENMOD_EMULATION_HPP_GUARD 17 | #define SVENMOD_EMULATION_HPP_GUARD 18 | #pragma once 19 | 20 | #ifdef __cplusplus 21 | 22 | typedef struct api_version_s 23 | { 24 | int major_version; 25 | int minor_version; 26 | } api_version_t; 27 | 28 | typedef enum 29 | { 30 | PLUGIN_CONTINUE = 0, // keep going 31 | PLUGIN_OVERRIDE, // run the game dll function but use our return value instead 32 | PLUGIN_STOP, // don't run the game dll function at all 33 | PLUGIN_CALL_STOP // call the game dll function and stop further hooks from executing 34 | } PLUGIN_RESULT; 35 | 36 | class IClientPlugin 37 | { 38 | public: 39 | virtual ~IClientPlugin() {} 40 | 41 | virtual api_version_t GetAPIVersion(void) = 0; 42 | 43 | virtual bool Load(CreateInterfaceFn pfnSvenModFactory, void *pSvenModAPI, void *pPluginHelpers) = 0; 44 | 45 | virtual void PostLoad(bool bGlobalLoad) = 0; 46 | 47 | virtual void Unload(void) = 0; 48 | 49 | virtual bool Pause(void) = 0; 50 | 51 | virtual void Unpause(void) = 0; 52 | 53 | virtual void OnFirstClientdataReceived(void *pcldata, float flTime) = 0; 54 | 55 | virtual void OnBeginLoading(void) = 0; 56 | 57 | virtual void OnEndLoading(void) = 0; 58 | 59 | virtual void OnDisconnect(void) = 0; 60 | 61 | virtual void GameFrame(void* state, double frametime, bool bPostRunCmd) = 0; 62 | 63 | // Called to draw 2D paints after rendering the game view 64 | virtual PLUGIN_RESULT Draw(void) = 0; 65 | 66 | // Called to redraw client's HUD 67 | virtual PLUGIN_RESULT DrawHUD(float time, int intermission) = 0; 68 | 69 | // Name of the plugin 70 | virtual const char *GetName(void) = 0; 71 | 72 | // Author of the plugin 73 | virtual const char *GetAuthor(void) = 0; 74 | 75 | // Version of the plugin 76 | virtual const char *GetVersion(void) = 0; 77 | 78 | // Description of the plugin 79 | virtual const char *GetDescription(void) = 0; 80 | 81 | // URL of the plugin 82 | virtual const char *GetURL(void) = 0; 83 | 84 | // Build date of the plugin 85 | virtual const char *GetDate(void) = 0; 86 | 87 | // Tag of the plugin to log 88 | virtual const char *GetLogTag(void) = 0; 89 | }; 90 | 91 | typedef struct CSMSvenBXT : IClientPlugin { 92 | virtual api_version_t GetAPIVersion(void); 93 | 94 | virtual bool Load(CreateInterfaceFn pfnSvenModFactory, void *pSvenModAPI, void *pPluginHelpers); 95 | 96 | virtual void PostLoad(bool bGlobalLoad); 97 | 98 | virtual void Unload(void); 99 | 100 | virtual bool Pause(void); 101 | 102 | virtual void Unpause(void); 103 | 104 | virtual void OnFirstClientdataReceived(void *pcldata, float flTime); 105 | 106 | virtual void OnBeginLoading(void); 107 | 108 | virtual void OnEndLoading(void); 109 | 110 | virtual void OnDisconnect(void); 111 | 112 | virtual void GameFrame(void* state, double frametime, bool bPostRunCmd); 113 | 114 | // Called to draw 2D paints after rendering the game view 115 | virtual PLUGIN_RESULT Draw(void); 116 | 117 | // Called to redraw client's HUD 118 | virtual PLUGIN_RESULT DrawHUD(float time, int intermission); 119 | 120 | // Name of the plugin 121 | virtual const char *GetName(void); 122 | 123 | // Author of the plugin 124 | virtual const char *GetAuthor(void); 125 | 126 | // Version of the plugin 127 | virtual const char *GetVersion(void); 128 | 129 | // Description of the plugin 130 | virtual const char *GetDescription(void); 131 | 132 | // URL of the plugin 133 | virtual const char *GetURL(void); 134 | 135 | // Build date of the plugin 136 | virtual const char *GetDate(void); 137 | 138 | // Tag of the plugin to log 139 | virtual const char *GetLogTag(void); 140 | } CSMSvenBXT; 141 | 142 | using CSMSvenBXT = struct CSMSvenBXT; 143 | 144 | extern CSMSvenBXT g_SMSvenBXT; 145 | extern CSMSvenBXT* g_lpSMSvenBXT; 146 | 147 | #else //!__cplusplus 148 | #error C++ compiler required to compile svenmod_emulation.hpp 149 | #endif //__cplusplus 150 | 151 | #endif //SVENMOD_EMULATION_HPP_GUARD 152 | 153 | #undef SVENMOD_EMULATION_HPP_RECURSE_GUARD 154 | #endif //SVENMOD_EMULATION_HPP_RECURSE_GUARD -------------------------------------------------------------------------------- /svenbxt.cfg: -------------------------------------------------------------------------------- 1 | // ██████ ██▒ █▓▓█████ ███▄ █ ▄▄▄▄ ▒██ ██▒▄▄▄█████▓ 2 | // ▒██ ▒▓██░ █▒▓█ ▀ ██ ▀█ █ ▓█████▄ ▒▒ █ █ ▒░▓ ██▒ ▓▒ 3 | // ░ ▓██▄ ▓██ █▒░▒███ ▓██ ▀█ ██▒▒██▒ ▄██░░ █ ░▒ ▓██░ ▒░ 4 | // ▒ ██▒ ▒██ █░░▒▓█ ▄ ▓██▒ ▐▌██▒▒██░█▀ ░ █ █ ▒ ░ ▓██▓ ░ 5 | // ▒██████▒▒ ▒▀█░ ░▒████▒▒██░ ▓██░░▓█ ▀█▓▒██▒ ▒██▒ ▒██▒ ░ 6 | // ▒ ▒▓▒ ▒ ░ ░ ▐░ ░░ ▒░ ░░ ▒░ ▒ ▒ ░▒▓███▀▒▒▒ ░ ░▓ ░ ▒ ░░ 7 | // ░ ░▒ ░ ░ ░ ░░ ░ ░ ░░ ░░ ░ ▒░▒░▒ ░ ░░ ░▒ ░ ░ 8 | // ░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ 9 | // ░ ░ ░ ░ ░ ░ ░ ░ 10 | // ░ ░ 11 | 12 | 13 | // SvenBXT configuration file (svenbxt.cfg) 14 | 15 | // *************************************************************** 16 | // HUD 17 | // *************************************************************** 18 | sbxt_hud_precision "6" // How many numbers after decimal point to display 19 | sbxt_hud_speedometer "1" // Speedometer 20 | sbxt_hud_speedometer_below_cross "1" // Display speedometer below crosshair 21 | sbxt_hud_speedometer_height "0" // Custom height for speedometer 22 | sbxt_hud_viewangles "1" // Viewangles info HUD (pitch, yaw) 23 | sbxt_hud_viewangles_anchor "1 0" // Position of viewangles 24 | sbxt_hud_origin "1" // Origin info HUD (coordinates) 25 | sbxt_hud_origin_anchor "1 0" // Position of origin HUD 26 | sbxt_hud_timer "2" // 0 - disable timer, 1 - VGUI2 text display, 2 - number HUD display 27 | sbxt_hud_timer_anchor "0.0 0.5" // Position of timer 28 | sbxt_hud_jumpspeed "1" // Display your speed after jump 29 | sbxt_hud_jumpspeed_below_cross "0" // Display jumpspeed HUD below crosshair 30 | sbxt_hud_jumpspeed_height "0" // Custom height for jumpspeed HUD 31 | 32 | // ****** TIMER SETTINGS 33 | sbxt_timer_serversync "1" // Synchronize your timer with host (DISABLE IF YOU WANT TO UNLOCK CLIENT-SIDE TIMER) 34 | sbxt_timer_il_mode "0" // If you want to speedrun individual levels, you need to enable this (automatic start, automatic stop during changelevel) 35 | 36 | // ****** CROSSHAIR 37 | bxt_cross "1" // Enable crosshair 38 | bxt_cross_color "100 130 200" // Crosshair color ("R G B") 39 | bxt_cross_alpha "255" // Crosshair transparency ("A") 40 | bxt_cross_thickness "8" // Crosshair thickness 41 | bxt_cross_size "8" // Crosshair size 42 | bxt_cross_gap "3" // Crosshair gap 43 | bxt_cross_outline "1" // Enable outline for crosshair 44 | bxt_cross_circle_radius "0" // Crosshair circle radius 45 | bxt_cross_dot_color "100 130 200" // Crosshair dot color ("R G B") 46 | bxt_cross_dot_size "0" // Crosshair dot size 47 | bxt_cross_top_line "1" // Enable crosshair top line 48 | bxt_cross_bottom_line "1" // Enable crosshair bottom line 49 | bxt_cross_left_line "1" // Enable crosshair left line 50 | bxt_cross_right_line "1" // Enable crosshair right line 51 | 52 | 53 | // *************************************************************** 54 | // BINDS 55 | // *************************************************************** 56 | bind KEY "sbxt_timer_start" // Start timer manually 57 | bind KEY "sbxt_timer_reset" // Reset timer manually 58 | bind KEY "sbxt_timer_stop" // Stop timer manually 59 | bind KEY "sbxt_sv_synctimer" // If you are host, you need to use this to synchronize timers between clients 60 | --------------------------------------------------------------------------------